Tuesday, February 26, 2019

Push Aurelia => Electron build

Now that we have added an Electron skeleton app to our project it is time to integrate the Aurelia project into the Electron project so that we can build for the desktop.

Merge Aurelia => Electron

The first step will be merging the Aurelia project into the Electron project so that when we run the Electron project we will be launching the Aurelia project, much like we did with Cordova.

The good news is ... it is relatively simple to do. The Electron project loads the app/main.js file which in turn loads the app/index.html file. All we have to do is copy our index.html file from the root and it's associated files into the app directory and voila ... Aurelia running inside Electron ... sweet !

There is one small gotcha which we will fix first. The integration of Aurelia and Electron causes some DOM conflicts with require, export and module keywords. There is a simple fix to avoid this from happening. We add a script to the index.html file that corrects the DOM definitions for Aurelia. This script runs after Electron has loaded so it does not impact the Electron functionality.
This is a known issue that effects most node based libraries. You can read about it here.
  1. Open index.html in the editor from the project root
  2. Add the following immediately before the <script src="cordova.js"></script> tag


  3. Your index.html file should look like this

That's it. Next we need to push the Aurelia files to the Electron project

Push Aurelia => Electron

The first thing we need to do is address a small shortcoming in the Aurelia copy-files routine that we used previously to copy files into the Cordova project. We want to continue copying the files to the Cordova project as well as copy them to the Electron project. The copy-files routine does not support multiple destinations and does not allow us to add the same file more than once. This creates a challenge for us. We could duplicate the copy-files routine but that violates the DRY mantra. The best solution is to modify the copy-files routine to support multiple destinations.
  1. Open aurelia_project/tasks/copy-files.js in your editor
  2. Change the code to the following. You can download the file here.

This modified routine will now accept an array of destinations for each instruction.
Next we need to add our new destinations to the aurelia_project/aurelia.json file
  1. Open aurelia_project/aureia.json file in your editor
  2. Change "platforms/browser/www/cordova*.js": "scripts" to  ["scripts", "app/scripts"]
  3. Change "platforms/browser/www/plugins/**/*.js": "scripts/plugins" to ["scripts/plugins" , "app/scripts/plugins"]
  4. Your file should look like this

Remember, the copy-files routine runs "pre build" and we are using it to ensure the Cordova scripts and plugins are included in the build.

NOTE: As of this writing I have logged a feature request with the Aurelia CLI team to add this functionality to the Aurelia project. If it is picked up by the team and included in a release then you will not have to make this change to copy-files.js on new projects in the future!

We need to add two more files to the copy-files routine for Electron. We need the platforms/browser/www/config.xml and the cordova.js shim file from the root so that the Cordova browser platform can run inside the Electron app.
  1. Open aurelia_project/aureia.json file in your editor
  2. Add "platforms/browser/www/config.xml": ["app"] to the copyFiles node
  3. Add "cordova.js": ["app"] to the copyFiles node
  4. Your file should look like this

Next we want to to push the Aurelia "post build" files to the Electron app directory.
  1. Open aurelia_project/aureia.json file in your editor
  2. Add "app" to the pushFiles/targets node
  3. Your file should look like this

Next we need to do a little housekeeping.

  1. Open the .gitignore file and make the following changes

  2. We are only interested in saving the app/main.js file and the app/package.json file. All other files and folders are dynamic and do not need to be stored in the source code repository.

That is it for changes. Let's test our Electron app!

  1. Open a command prompt
  2. Run command 'npm start'
  3. The Electron app should open on your desktop

  4. Have a look in dev tools. Notice that app has loaded the Cordova libraries and started Aurelia
    Add caption

Now let's build an installable package

  1. Open a command prompt
  2. Run command 'npm run dist'
  3. The compiler will build an installable for your local environment. This means an exe file for Windows machines or a dmg package for Macs.

  4. The installable package is located in the dist directory.
    Add caption
  5. Go ahead and install it and then launch the app from the desktop.
    Add caption


Now I will swing over to the Mac and test our build for the Apple platform.

  1. Open a terminal in the project root
  2. Run command 'npm run dist'

  3. Look in the dist folder

  4. Install the dmg and open the app

  5. You should see the Cordova plugins load and the Aurelia app has started without any errors logged

We now have a single code base that can run in a browser, Android device, IOS Device, Windows desktop and MAC desktop ... mission accomplished!

My next blog will recap the various steps needed to build the solutions as well as a complete list of the multitude of command line instructions for this project. I will also introduce some automation to help you simplify the command structure and improve productivity.

4 comments:

  1. Hi Daryl

    I really appreciate your guides to create an aurelia desktop application. I do however get stuck at the beginning of this page. When I configure my index.html like you do and run npm start I get the error: "require.nodeRequire is not a function". I have looked on google and didn't yet find a solution to this.

    Since in my project I only am trying to run an Aurelia Desktop app I do not have Cordova stuff nor the copyfiles code. But I don't think this would be the problem, right?

    Have you had any experience with that error? Or could you perhaps post your project on Git so I can inspect it?

    Kind regards
    Karel

    ReplyDelete
    Replies
    1. Thanks for the kind words ... see my comments below

      Delete
  2. Hey Karel, I think you may have a typo ... there are only 2 places in the entire app where we access nodeRequire ... one is in index.html where we assign it and the other is in our shim file electron.js where we test to see if it is initialized. Both instances are referenced by "window.nodeRequire" however your error states "require.nodeRequire" ... Find the statement and replace the word require with window ... hopefully that should do it!

    ReplyDelete
  3. PS ... The entire project is posted on GitHub at https://github.com/SmokeHouseProject/applewood

    ReplyDelete