Angular 4 + Electron - How to run application and watch for changes (live reload)

Viewed 8694

I am creating an Electron application using Angular 4. How can i set it up so that it watches for any changes and live reloads it.

package.json

{
  "name": "angular-electron",
  "version": "0.0.0",
  "license": "MIT",
  "main": "main.js",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "electron": "electron .",
    "electron-build": "ng build --prod && electron ."
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^4.2.4",
    "@angular/common": "^4.2.4",
    "@angular/compiler": "^4.2.4",
    "@angular/core": "^4.2.4",
    "@angular/forms": "^4.2.4",
    "@angular/http": "^4.2.4",
    "@angular/platform-browser": "^4.2.4",
    "@angular/platform-browser-dynamic": "^4.2.4",
    "@angular/router": "^4.2.4",
    "angular-svg-round-progressbar": "^1.1.0",
    "bulma": "^0.5.3",
    "core-js": "^2.4.1",
    "rxjs": "^5.4.2",
    "zone.js": "^0.8.14"
  },
  "devDependencies": {
    "@angular/cli": "1.4.1",
    "@angular/compiler-cli": "^4.2.4",
    "@angular/language-service": "^4.2.4",
    "@types/jasmine": "~2.5.53",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "~3.1.1",
    "electron": "^1.7.6",
    "electron-packager": "^9.1.0",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~3.2.0",
    "tslint": "~5.3.2",
    "typescript": "~2.3.3"
  }
}

electron

const { app, BrowserWindow } = require('electron')

let win;

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({
    width: 600, 
    height: 600,
    backgroundColor: '#ffffff',
    icon: `file://${__dirname}/dist/assets/logo.png`
  })

  win.loadURL(`file://${__dirname}/dist/index.html`)

  //// uncomment below to open the DevTools.
  // win.webContents.openDevTools()

  // Event when the window is closed.
  win.on('closed', function () {
    win = null
  })
}

// Create window on electron intialization
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {

  // On macOS specific close process
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // macOS specific close process
  if (win === null) {
    createWindow()
  }
})

thanks.

Currently, i build my application every time using the following command

ng build --prod && electron .

This gets tiring, so i want to be able to build run one command so it watches for changes and live reloads.

4 Answers

You can use electron-reload for hot module reload. It listens on file changes and reloads the electron app.

Simply add it to the devDependencies in your package.json.

Then, you have to add it to your main.ts:

import { app, BrowserWindow, Menu } from 'electron';

let win, serve;
const args = process.argv.slice(1);
serve = args.some(val => val === '--serve');

if (serve) {
  require('electron-reload')(__dirname, {});
}

Then add a command to your package json

"start": "webpack --watch",
"serve": "npm run build:main && electron ./dist --serve",
"build:main": "tsc main.ts --outDir dist && copyfiles package.json dist && cd dist && npm install --prod"

where build:main is your build script to compile your project. This compiles all Typescript files and puts them into the dist folder. Afterwards, it runs npm install to download and install modules from NPM.

You need the module-bundler Webpack for this to run. Install it with

npm install --save-dev webpack

First, in a console run npm start. Afterwards, in a second console executenpm run serve. Now, it listens for changes and recompiles on file changes.

tsc stands for TypeScript compiler. If you're using tsc as a node module, make sure its installed:

npm install -g typescript

I use it currently for a project with the same setup (Angular 4, Electron) and it works perfectly.

I personally hate pretty much all other answers out there on the internet. I chose to do something more off the wall. I do ALL development with just raw angular, and stub out the parts of the application that require electron things, like sharing the desktop, or getting a config file from somewhere like this:

if (!this.electron.isElectronApp) {
  return {
    config:data,
    more:data,
  }
} else {
  do electron things
}

It so far has worked wonderfully. If can anyone think how this is going to bite me in the butt later please share.

You can concurrently run ng build with watch and the electron.

"electron": "tsc application/start.ts && concurrently \"ng build --watch  --base-href ./\"  \"devMode=1 electron .\""

Also use electron-reload and configure it to reload every time the dist folder is changed.

require('electron-reload')(__dirname);

For the first time electron window will open with errors as dist folder is not generated, once the ng build is completed, dist will be generated and electron-reload will reload the app. After that on every change dist folder will change because of --watch and electron-reload will reload the app.

Related npm packages

https://www.npmjs.com/package/concurrently

https://www.npmjs.com/package/electron-reload

First of all, we need to understand what actually is the issue being asked. There are two issues, as given below, regarding using electron with angular and live reload:

  1. How to reload Electron on the Build change
  2. How to reload Electron on the Source change

Now, when I was searching for the answer I actually was looking for issue no 2 but was getting the answer for issue no 1. There was so much confusion for me and no clear answer. So, let's get rid of this confusion and I am going to answer issue 2.

How to Reload Electron on the Source Change

This is clear that when we are developing the Angular app, we run the ng serve command, and the TS compiled to JS and put in memory and served from the memory instead of the disk (when we create the build).

So to use that in-memory source for live electron reload do the following:

Install the electron-reloader:

npm install electron-reloader --save-dev

Add this in the main.js file:

require('electron-reload')(__dirname, {
  electron: path.join(__dirname, 'node_modules/.bin/electron')
});

Run the Angular app in one terminal using ng serve and you will get the address something like this http://localhost:4200.

And in other terminal run electron, for this add "electron": "electron ." in your package.json scripts file and run node electrone.

Now in the main.js provide the local address in mainWindow.loadURL() as string.

Now, your electron app will get reloaded whenever you make changes and this will provide you with the same reload experience when the Angular app is run on the browser.

Related