Electron Tutorial: Getting started with Electron and Angular CLI
In this Electron tutorial I will walk through the steps you can take to turn an Angular application into a native desktop application using Electron. A technology stack using Angular and Electron allows developers to build cross platform desktop applications for Windows, Mac and Linux using web technologies. If you are new to Angular, I have written a blog series on getting started with Angular. It can be found here: http://www.blackslatesoftware.com/angular-tutorial-getting-started-with-the-angular-cli/
This Electron tutorial will focus mainly on Electron and how to get started developing an Electron application with Angular. If you are unfamiliar with what Electron is, it essentially is a chrome browser dedicated to running a single application. Electron also has to natively interact with a computer’s operating system. Electron is packaged with your application, meaning, there will be consistency across operating systems in the same way a chrome browser is consistent across operating systems. Thus, you can write a single web application, with a single code base and use that application with Electron to turn a web application into cross platform desktop applications.
I’ve also created a video to accompany this tutorial that walks through the different sections of this blog post. You can view that here as well as get more in depth description below.
Electron has a core set of API’s it uses to interact with the user’s operating system. On top of that, it includes all of Chromium’s APIs, all of NodeJS’s built in modules and can support third party modules.
Electron Tutorial Prerequisites
For this Electron tutorial, I am going to be using an example repo I have created in that getting started blog I linked above. With that in mind, you will need to have the proper node and npm packages installed for any Angular application. This Electron tutorial is assuming your Angular application was created and maintained using the Angular CLI.
Electron Forge
Electron has a fairly large open source community, with that comes a wide variety of options on how you want to leverage the framework. Thus, setting up an Electron application can be done in a variety of ways. One way, the way I am going to demonstrate in this Electron tutorial, is using Electron Forge: https://electronforge.io/. Electron Forge is Electron’s command line interface (CLI) tool. By leveraging the Electron Forge CLI the way I am about to demonstrate, we are able to add one file and modify the package.json
in an Angular CLI generated project to create a cross platform desktop application. Let’s get started!
Create Your Main Script
Electron uses the main script defined in your package.json
to start up. Meaning it will check your package.json
for the “main” script and execute whatever it finds. So we will need to create this script in our project. The main script is going to start the electron application, create a window and the load a specified URL. The URL can be a remote web URL if you feel like creating a desktop app out of your favorite website (this does have some limitations). In our case we are going to have our main script load the entry point to our application.
Inside of your Angular CLI generated project, add the following code block to a file that I am going to call electronMain.js
. This file comes from Electron’s documentation for getting started https://electron.atom.io/docs/tutorial/quick-start/ with a few changes to it to work with our Angular application. Create the file in the src/
folder of your project (Electron Forge won’t allow it to be in the same directory as package.json
).
const { app, BrowserWindow } = require('electron') const path = require('path') const url = require('url') let win; function isDev() { return process.mainModule.filename.indexOf('app.asar') === -1; }; function createWindow() { win = new BrowserWindow({ width: 800, height: 600 }) win.loadURL(url.format({ pathname: path.join(__dirname, '../dist/index.html'), protocol: 'file', slashes: true })); if (isDev()) { win.webContents.openDevTools() } win.on('closed', () => { win = null }) } app.on('ready', createWindow) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { if (win === null) { createWindow() } })
**If you are using Angular v6+ your pathname will be: ‘../dist/appName/index.html’
I have made a few changes from what is found in the Electron getting started guide for this Electron tutorial. The changes I have done are for the Electron app to use a loadURL that points at our dist/
folder and loads the index.html
file. If you are a beginner to Angular and the CLI, when you run npm run build
in a CLI generated project, it builds the application and puts it into the dist/
folder with index.html
as your entry point for the app. Additionally, I have added a check for if the application is being run in dev mode, the isDev()
function. If it is in dev mode the Electron app will open Chrome’s dev tools when the application starts up, which I find very useful for development.
Next, we need to update our package.json
with a couple things to get this all to work. An Electron app requires a few pieces of information in your package.json
to work:
- name (should be generated by Angular CLI)
- version (should be generated by Angular CLI)
- main (set to the main script we just created)
- author
- description
Additionally, we are going to add a few packages to our dependencies, three scripts and some config
information to get Electron Forge to work.
"main": "src/electronMain.js", "author": "rroot", "description": "Example Angular and Electron" "scripts": { ... "forge-start": "electron-forge start", "package": "electron-forge package", "make": "electron-forge make", ... }, ... "config": { "forge": { "make_targets": { "win32": [ "squirrel" ], "darwin": [ "zip" ], "linux": [ "deb", "rpm" ] }, "electronPackagerConfig": { "packageManager": "npm" }, "electronWinstallerConfig": { "name": "ng-example" }, "electronInstallerDebian": {}, "electronInstallerRedhat": {}, "github_repository": { "owner": "", "name": "" }, "windowsStoreConfig": { "packageName": "", "name": "ngExample" } } }, "dependencies": { ... "electron-compile": "^6.4.2", "electron-squirrel-startup": "^1.0.0", ... }, "devDependencies": { ... "electron": "^2.0.0", "electron-forge": "^5.2.0", "electron-prebuilt-compile": "2.0.0", ... }
Electron Forge has a set of templates for React, Angular, Vue.JS and ES6/7. To get the configuration information above, I just ran the init command with the Angular flag set for the template in an empty project folder. A barebones template for Electron and Angular was generated. Then I took that information and put it into my Angular CLI generated project.
One final step we will need to do is update the href
used by the Angular application to use a relative path. This allows electron to find the resources of the project. In honesty, I’m not a big fan of this step, but it works and it also doesn’t break the web version of your app. To do so, open index.html
and modify the base href to look likes this: <base href=”./”> . (Just adding a period before the slash to use a relative path to our project.)
With that we can build and run our electron app to verify we have set our project up correctly.
Building and Running the Application
Make sure you run an npm install
after updating your package.json
with the electron dependencies. Then you can build the application like any other Angular application, npm run build
. Now just run the start script: npm run start-electron
and an Electron window should open up with your Angular CLI application running inside.
If you want to check that your web application still works, run ng serve
and navigate to localhost:4200
and you should find the same results.
Make and Package
This is my favorite part about using Electron Forge. With that simple setup, not only are we able to get started developing an Electron Application with Angular in a short amount of time, but we are able to make distributables of the desktop application as well. As a web developer with no desktop development experience, I am able to build and distribute a cross platform desktop application using the skills I already have. So awesome!! All you have to do is run the make
command script we added to our package.json
and Electron Forge will do the work for you from there. Give it a shot!
Two things to note about make
:
- Electron Forge is going to build the target corresponding to the OS you are running the command on. Windows makes windows, Mac makes mac.. etc.
- To properly distribute Mac builds, you will have to set up code signing. I am not going to cover doing that here but it’s a pretty straight forward process.
Additional steps for improving development process
With the setup described above, you will have to run npm run build
and npm run electron
for every change that you make while developing. This is not ideal, so lets speed up this development process a bit.
Add a script to package.json
that will rebuild the application whenever changes are made to the codebase. I choose to use ng build
without the --prod
flag, because at this time, rebuilding without aot
is significantly faster. If you are on Angular v6, aot
is used by default and the rebuilds are super fast. Here’s the script:
"build-watch": "ng build --op dist -w"
You will need to use two terminals, in the first run npm run build-watch
and in the second run npm run electron-start
. Use the second terminal to kill and restart the electron app. This will work well for most development, I have run into times where build-watch
doesn’t catch some changes, like adding new modules. If you are running into errors you don’t understand, kill build-watch and restart it. You shouldn’t be in that situation often but it’s good to know.
Conclusion
With that, you are setup to start building your cross platform desktop application using Angular and Electron. In a future post I will discuss using the Electron API to add more desktop functionality, including Auto-update features. Thanks for reading this Electron tutorial, drop a comment or question below!
Trackbacks/Pingbacks