Our website is made possible by displaying online advertisements to our visitors. Please consider supporting us by disabling your ad blocker.

Build Electron Applications With Vue.js And Webpack

TwitterFacebookRedditLinkedInHacker News

This tutorial was updated on May 14, 2020 to reflect the latest versions of the technologies mentioned.

If you’re like me, you thought you’d try to build a cross-platform desktop application using the very popular Electron framework as well as the very popular Vue.js JavaScript framework. At first glance it might seem as easy as defining an Electron configuration, but in reality, a little more needs to be done when using Webpack to build the project.

I had written a few tutorials a while back around Electron, and even one with Vue.js, but in that example the Vue CLI and Webpack were not part of the equation. In this tutorial, we’re going to see how to create a new Vue.js application using the Vue CLI, configure it for use with Electron, and then deploy it in all its glory.

Creating a New Vue.js Application with the Vue CLI

To be successful with this project, you will need to have the Vue CLI installed. As of right now, I’m using version 3.0.4 of the CLI, but future versions will likely have some similarity to the content found in this tutorial. With the CLI available, execute the following command to create a new project:

vue create electron-project

The CLI has its own configuration wizard for creating Vue.js applications. The emphasis of this tutorial is not to create an extravagant application, so we’re going to go with the defaults. If you navigate into the project with your command line and try to serve the application, it should work without issues.

npm run serve

The above command will start the serving scripts that come with a new Vue.js project. Now that we have a working application, we need to configure Electron so the application can be packaged within it and deployed as a desktop application rather than a web application.

Installing and Configuring Electron as a Development Dependency

Because Vue.js is powering our application rather than Node.js, the Electron configuration is quite short and simple. In fact, most of what we’re going to see has been copied from the documentation.

Before we worry about the configuration, let’s get Electron installed as a development dependency to the project. From the command line, execute the following:

npm install electron --save-dev

Now we can focus on the configuration. At the root of your project, create an electron.js file with the following:

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

let win

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

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

    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()
    }
})

Does the above look familiar? Like I said, it was taken from the Electron documentation. There is one change to note in the above code. Rather than trying to serve a Vue.js application inside an Electron application, we want to use a production build. When we do a production build of our Vue.js project, the output will end up in the project’s dist directory.

Even though we have an Electron configuration, the project isn’t quite ready to be ran as a desktop application.

Open the project’s package.json so we can set the electron.js file as our entry point:

// ...
"main": "electron.js",
"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "electron": "vue-cli-service build; electron ."
},
// ...

Rather than including my entire package.json file, I’ve only included a subset. In the main property we set the electron.js file and we also create a build script. The build script will first build the Vue.js project, then it will launch it with Electron based on the main entry.

Go ahead and run the following command to run the application:

npm run electron

The application should launch as a desktop application, but you’ll probably notice some problems in the logs.

Configuring the Application to Build with Webpack for Electron

If you look at the console logs for the running Electron application, you’ll probably notice a few errors that include something like the following:

Failed to load resource: net::ERR_FILE_NOT_FOUND app.7542f025.css:1
Failed to load resource: net::ERR_FILE_NOT_FOUND app.21484df5.js:1
Failed to load resource: net::ERR_FILE_NOT_FOUND chunk-vendors.6c9cb6ef.js:1

We’re getting these resource related errors because of how the paths are defined between the files in our project as part of the Webpack build process. For example, if you look in the projects dist/index.html file, either in the dist directory or in the inspector, you’ll probably notice the following:

<script src="/js/chunk-vendors.6c9cb6ef.js"></script>
<script src="/js/app.21484df5.js"></script>

The above lines are only a small subset of the similar problems that we’re looking at. Notice that these files have a leading slash for the path. Electron will have a tough time pulling all the pieces of your application together with absolute paths like this. Instead, we should change the paths to relative paths.

At the root of your project, create a vue.config.js file with the following JavaScript code:

module.exports = {
    baseUrl: process.env.NODE_ENV === 'production' ? './' : '/'
}

When we have a production build, we’ll use a relative path. In other words, the leading slash will be removed from all resources and as a result the Electron application will work correctly. By creating a vue.config.js file, we are doing things the recommended way for Vue.js rather than trying to directly modify Webpack through the Webpack configuration.

UPDATE 05/2020: As one user in the comments pointed out, the baseUrl field is deprecated in recent releases. If you’re using a recent release, the following should be done instead:

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

Notice that publicPath is now being used instead of baseUrl which was recently deprecated.

Conclusion

You just saw how to create a web application with Vue.js, build it with Webpack, and package it for deployment with Electron so that it can be used on platforms such as Mac, Windows, and Linux. If your building a Vue.js application without the CLI and without Webpack, you won’t have to worry about this. Likewise if you’re building an Electron application with Angular or React.js, the process will be slightly different for handling the paths.

A video version of this tutorial can be found below.

Nic Raboy

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in C#, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Unity. Nic writes about his development experiences related to making web and mobile development easier to understand.