简体   繁体   中英

How do I use Babel with Electron?

I want to build an Electron app with ES6 import syntax so I can re-use modules between my Node.js and browser side JS without code duplication and found Electron is frustratingly behind the times on ES6 syntax support.

I learned about this magical solution only to discover it was no longer maintained.

So Babel to the rescue, or so I thought. Google isn't exactly fruitful on the topic of Babel + Electron tutorials. I also wanted to throw in Nodemon.

Here's my setup:

package.json

{
  "name": "infinitum",
  "version": "1.0.0",
  "description": "",
  "main": "compiled.js",
  "directories": {
    "test": "tests"
  },
  "scripts": {
    "start": " electron .",
    "compile": "nodemon --exec babel-node app.js --out-file compiled.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/node": "^7.12.10",
    "@babel/preset-env": "^7.12.11",
    "electron": "^11.1.0",
    "nodemon": "^2.0.6"
  }
}

As you're going to see in the following output and debugging logs, the problem here is we're trying to compile the node module to use ES6 syntax, but any Electron app is dependent on the Electron module, which seems to not export in a traditional way, resolving the electron executable path (string) instead of a Node.js module. It's a circular problem.

app.js

import {app, BrowserWindow} from 'electron'
import 'url'
import 'path'

let win

function createWindow() {
   win = new BrowserWindow({width: 800, height: 600})
   win.loadURL(url.format ({
      pathname: path.join(__dirname, 'index.html'),
      protocol: 'file:',
      slashes: true
   }))
}

app.on('ready', createWindow)

.babelrc

{
  "presets": [
    "@babel/preset-env"
  ]
}

I'm running:

npm run compile

Which gives the error:

C:\Users\jonat\documents\github\infinitum\app.js:23
_electron.app.on('ready', createWindow);
              ^

TypeError: Cannot read property 'on' of undefined
    at Object.<anonymous> (C:\Users\jonat\documents\github\infinitum\/app.js:16:5)
    at Module._compile (internal/modules/cjs/loader.js:1076:30)
    at Module._compile (C:\Users\jonat\Documents\GitHub\infinitum\node_modules\pirates\lib\index.js:99:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:1097:10)
    at Object.newLoader [as .js] (C:\Users\jonat\Documents\GitHub\infinitum\node_modules\pirates\lib\index.js:104:7)
    at Module.load (internal/modules/cjs/loader.js:941:32)
    at Function.Module._load (internal/modules/cjs/loader.js:782:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at Object.<anonymous> (C:\Users\jonat\Documents\GitHub\infinitum\node_modules\@babel\node\lib\_babel-node.js:172:21)
    at Module._compile (internal/modules/cjs/loader.js:1076:30)

So to debug I tried this app.js :

import electron from 'electron'
console.log("typeof electron:", typeof electron, "\nelectron:", electron)

Output:

typeof electron: string
electron: C:\Users\jonat\documents\github\infinitum\node_modules\electron\dist\electron.exe

And as further clarification, an app.js like this:

import * as name from 'electron'
console.log({ name })

logs:

{
  name: {
    default: 'C:\\Users\\jonat\\documents\\github\\infinitum\\node_modules\\electron\\dist\\electron.exe'
  }
}

I'm realizing this is probably because the "electron." does something special in the parsing pipeline. But I've definitely heard of Babel being the solution to using ES6 import syntax in Electron, I just cant find an actual guide on doing it. So how can I use Babel with Electron?

I think the problem is about your usage of babel-node . babel-node is a node cli clone that does babel transformations before executing JS code. It is not a compiler. There is no --out-file flag defined for this cli. It's a pity that it does not warn you for using an unrecognized flag.

In order to compile your ES6 files, you need to use babel cli. Replacing babel-node with babel at your compile task should do the trick.

Also you need to replace your imports to import * as... from... syntax:

import * as url from 'url'
import * as path from 'path'

You can also check Electron 12 previews. They support Node 14, which supports ES modules. So when Electron 12 is out, it should theoretically be possible to use ES modules without Babel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM