Vue.js as desktop executable

Vue.js as desktop executable

Learn how to build a cross-platform desktop app based on a Vue.js app. By using Electron we can create a desktop app based on a website and adding the Electron builder at the end we can create an installer. This desktop app is based on a Vue.js app but this can be almost any app or website.

Prerequisites

The only prerequisite is that Node.js should be installed.

Yarn The upcommingsteps are using Yarn instead of npm. If you have not installed Yarn, then use the npm command below to install Yarn (globally).

npm install yarn --global

Vue CLI If you haven't already, install the Vue CLI (globally) by running te following command.

yarn add global @vue/cli

Create a Vue.js website

To create the Vue.js website we'll use the Vue CLI. By using the vue create command the Vue.js CLI creates a Vue.js app with the name my-vue-app. The --default option skips prompting for presets by using the Vue.js defaults.

vue create my-vue-app --default --no-git

Now run the project executing the following followed by opening the address http://localhost:8080/ in your favorite browser.

cd my-vue-app
yarn serve

When all wen't okay, the Vue.js welcome page is displayed and showing the message Welcome to Your Vue.js App.

Create the Electron app

The next step is to build the cross-platform desktop app that is based on the Vue.js app.

Install electron using the yarn add electron command. We install this locally (--dev).

yarn add electron --dev

In the root of the Vue.js project we create a main.js file. Keep in mind, this file is created at the root of our project (/my-vue-app/main.js). The main.js file is the entry point contents of our application. The contents of the main.js file is shown below. Copy/past the content into the main.js file.

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

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  win.loadFile('index.html') // this needs to be changed to './dist/index.html' for the my-vue-app
  win.webContents.openDevTools()
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

Set entry point

The win.loadFile('index.html') line points to the wrong file. By default index.html is set as startpage. After running a build for our Vue.js app, our index.html is located in ./dist. This means we need to change the startpage. Change the line into the following to point to the right location.

win.loadFile('./dist/index.html')

The setting that is easy to look over is adding the Vue.js public path. This setting is depending on the build environment that you have used. Create a vue.config.js file that in the root of the project and setup the public path. Note the differences between "./" and "/".

module.exports = {
    publicPath: process.env.NODE_ENV === "production" ? "./" : "/"
}

We need to modify the package.json file to point to our main.js file. Add the main json element to the root of the package.json file.

{
  "main": "main.js"
}

Setup dev command

Next add the electron:dev element to the scripts element in the package.json file. With this command the can call Yarn to build our Vue.js app followed by a Electron command that build and runs the app.

{
  "scripts": {
      "electron:dev": "vue-cli-service build && electron ."
  },
}

Run dev command

To test everything works, use the electron:dev Yarn command.

Yarn electron:dev

A Electron window is shown. Probably with the developer tools openen. This can be hidden by default by removing the win.webContents.openDevTools() line from the main.js file.

Configure cross-platform build

To package and build the electron app for Windows, Linux or MacOS we need a package called electron-builder. Install this with Yarn.

yarn add electron-builder --dev

Open the package.json file and add the following build element to the root of the file. Change the values for your requirements. For this example I use the appId my.vue.app and build a win (windows) executable targetting nsis (Nullsoft Scriptable Install System). This means I'll get an installer for our my-vue-app. To view all options see Electron Common Configuration.

{
  "build": {
    "appId": "my.vue.app",
    "win": {
      "target": "nsis"
    }
  }
}

Configure dist folder as build resource

The mostly forgotten part took some time for me to figure out. When building the dist folder isn't packaged, but the src folder(s) do. That's something we do not want. To fix this, open the package.json again and extend the build element with two other elements, files and directories. The first one (files) tells the build to include the files that match the given patterns. The second one (directories) tells we want to use dist as build resource and we want to output everything to the release folder.

{
  "build": {
    "files": ["**/*", "dist/**/*"],
    "directories": {
      "buildResources": "dist",
      "output": "release"
    }
  }
}

Setup executable build command

To use the build configuration, modify the package.json file and add another element to scripts.

{
  "scripts": {
    "electron:build": "vue-cli-service build --mode production && electron-builder build"
  }
}

Now let's build our installer with the electron:build Yarn command.

Yarn electron:build

Run the app

Open the my-vue-app/release folder and there it is, the Windows NSIS installer calles my-vue-app Setup 0.1.0.exe. You can also view the application without installing by opening the my-vue-app/release/win-unpacked folder and running the my-vue-app.exe.

That's All Folks!