- when you probably really need Electron
- how to integrate Webpack with Electron
- develop (and test) browser and Electron app
- Electron vs. system-wide node.js
OMG, another Electron freak!
Yeah yeah, I hear you saying Why don’t you learn Swift/C#/C++/…, Electron is so much memory intensive etc. I know you’re there, Electron haters. Well, in my opinion it’s super convenient to develop web application and have a possibility to run it inside Electron (with a great advantage—access to underlying node.js). Personally, it’s been thrilling to communicate with node.js from Electron (I’m kind of passionate developer). Sure, you can feel no Electron app is native, but that’s what trade-off is about.
When you may need Electron
I’ll show you how to communicate with serialport device from your Electron app. First, we’ll create a project and install dependencies. Then Webpack needs to be configured. After this step we can finally run the app. The demo project will be fully functional in Electron and will gracefully degrade in a browser.
Prerequisites and project structure
1 2 3 4 5 6 7 8 9 10 11 12
Actual app code is inside
app.js; we will write some tests in
app.test.js; built bundle inside
build directory; Electron main file is
index.electron.js; our webpage index file is
package.json contains list of dependencies and scripts; into
release-builds we will pack whole Electron ready for distribution (in the next article); and finally
webpack.config.js serves as Webpack config file.
Paste this into
package.json and run
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Let’s start with Webpack
Paste this into
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
You probably already know Webpack. What’s critical in configuration below is
You need to set
electron-renderer if you’re building code for Electron. Long story short—this setting will enable node.js and browser environment in your bundle.
index.electron.js code looks like this:
1 2 3 4 5 6 7 8
if clause; the code inside the clause will be executed only if the bundle was built for Electron environment.
1 2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
There’s nothing special in
index.electron.js is (almost) a vanilla Electron configuration.
All right, run Webpack with
npm run build and open
index.html in your browser (e.g.
file:///Users/joedoe/electron/index.html). You should see something like on the screenshot below.
Now run Webpack in Electron mode:
PLATFORM=electron npm run build. Open the
index.html file with Electron:
npm run electron.
Most native node.js modules are loaded via node-bindings library. The library tries to find native module in
We need to copy
build/. If you already have a prebuilt module in
node_modules/serialport/build/Release/serialport.node just copy it:
cp node_modules/serialport/build/Release/serialport.node build/.
If the module is missing build it with
./node_modules/.bin/electron-rebuild -e node_modules/electron and copy to
Try Electron again with previous npm command. Now you’re actually scanned your serial ports thanks to node.js native module!
Living with two node.js environments
There’s a chance you’ll eventually see an error message
The module ... was compiled against a different Node.js version using NODE_MODULE_VERSION X. This version of Node.js requires
NODE_MODULE_VERSION Y. In that case just run the
./node_modules/.bin/electron-rebuild -e node_modules/electron command. The reason why it might happen is Electron node.js usually slightly differs from the system-wide node.js version. In other words, Electron environment doesn’t depend on system-wide node.js.
My strategy is to keep native modules built against Electron in
build/ directory and (if needed, because of tests e.g.) modules built against system-wide node.js in
npm rebuild command).
Let’s write a simple test which actually
require() serialport dependency:
1 2 3 4
This will load native module in
node_modules/serialport/build/Release/serialport.node and the test will pass. Run tests with
npm run test.