See all articles from the series

The idea

Frontend Apps can easily be built for a various range of platforms. You can use Apache Crodova for building cross platform mobile apps. For building cross platform desktop apps you can either use Electron or NW.js.

No matter which one you’re using (NW.js / cordova / electron), all of them will utilise our Frontend App (x-note) and package it for distribution to the requested platforms. During this post I’d like to address desktop builds using NW.js, Cordova builds will be addressed within the upcoming post.

NW.js desktop builds

The build already contained a sample implementation for the NW.js build (see gulptasks/desktop.js).

 gulp.task('private:build:nw', function(done) {
    var nw = new tasks.NwBuilder({
        files: 'dist/**/*',
        version: '0.12.3',
        platforms: ['osx64']

The underlying npm module nw-builder (see package.json’s devDependencies) is offering way more options and settings that you can - and we will do so in a minute - use to configure desktop builds with respect to all common requirements.

Adding / Compiling for more platforms

Use the platforms property to spectify which platforms you’re app should be compiled for. You can choose from five different platforms (osx64, linux32, linux64, win32 and win64).

Let’s change our private:build:nw task to build for all available platforms now.

// ...
    platforms: ['win32', 'win64', 'osx64', 'linux32', 'linux64']
// ...

nw-builder documentation says that there is a osx32 platform which is true, but the support for osx32 has been dropped with 0.13.0-aplha.

If you’re using a Mac for development you’re fine with those settings. OS-X is able to build apps for all platforms. I’ve never tried to execute such a task on Windows. If you’ve problems when executing this task on windows, post a comment and I’ll look into that.

Dealing with cacheDir and buildDir

By default the cacheDir will be placed within your project’s directory. This is fine for some developers, but not for me. I’ve multiple projects that are compiling to all platforms using NW.js, so each and every project / app would have it’s own downloads of NW.js’ executables. Using a dead simple trick you can minimise the required downloads and stop waisting your hard disk with the same files for each and every project.

First, update gulpfile.js and add the node path module to the tasks object using

path: require('path'),

That said, add the following line of code inside of the private:build:nw right before instantiating NwBuilder

var homeDir = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;

Finally set the cacheDir property like shown below

cacheDir: tasks.path.join(homeDir, '.cache'), 

The buildDir property specifies where the compiled apps will be placed. By default all compiled apps go to the build sub-folder. If you want to change that location, just specify a directory. You can either specify a relative or an absolute path. For demonstrating purpose let’s change the default buildDir to a subfolder called desktop-builds by adding the following line of code

buildDir: tasks.path.join(process.cwd(), "desktop-build"),

Specifying Icons

A lot of people asked me how to specify custom icons for desktop executables. For the Mac App, it’s pretty easy, just specify the macIcns property and point it to your .icns file. nw-builder will automatically set the icns file as application icon.

If you’re building NW.js apps on Windows, you can just specify the winIco and point to a .ico file. The build pipeline will take care about everything else. If you’re running on OS-X or Linux, follow this Guide to setup all required tools for including the .ico file into the executables from OS-X or Linux.

In our x-note app we specify the icon paths like this

macIcns: 'assets/x-note.icns',
// winIco: 'assets/x-note.ico'
// uncomment the line above only if you've finished the the guide above

Zip app contents for Mac App

When building the app for OS-X platform, you can set the macZip to true. But be aware when setting this property to true, the startup time on OS-X will increase because NW.js has to decompress your app for each and every start on-the-fly.

This property defaults to false.

More properties for desktop builds

There are plenty more properties available for nw-builder go and checkout the following documentation on github.