升级Electron
当你第一次在Quasar项目中添加Electron模式时,你会得到最新版本的Electron软件包。在某个时间点上,你会想要升级Electron的版本。
在升级Electron之前,请参考它的发行说明。是否有破坏性的变化?
# 从你的Quasar项目的根目录下
$ yarn upgrade electron@latest
# 或者: npm install electron@latest
从Quasar v1升级
Quasar v2的Electron模式几乎完全颠覆了之前的版本,大大改善了开发者的体验。为了确保与Electron世界的最新发展相兼容,这里的一些变化是必须的(所以要为即将到来的上游变化做出防范)。
改进概述
- 开箱即用的对Typescript的支持。只需将electron-main.js和electron-preload.js重命名为electron-main.ts和electron-preload.ts。
- 支持Electron 11,并为即将到来的Electron 12+的变化准备开箱即用的支持(未来你不需要改变任何东西)。其中一个变化是我们将使用
contextIsolation
而不是被废弃的Node Integration
。 - 预加载脚本不再有旧的限制。你可以用相对路径导入其他js文件,因为该脚本现在被捆绑并通过Babel传递(所以你也可以使用
import X from Y
语法)。你也可以为它启用提示功能。 - 你也可以为主线程和预加载脚本启用提示功能。
- 我们删除了默认的electron-main.dev.js支持,因为它似乎不再需要了。然而,你可以通过创建它并从electron-main中引用它来把它添加回来(Quasar CLI不再自动检测它–因为我们不需要;稍后会有更多的内容)。
/src-electron文件夹
# 旧的结构
.
└── src-electron/
├── icons/ # 你的应用程序在所有平台上的图标
| ├── icon.icns # 适用于Darwin(MacOS)平台的图标文件
| ├── icon.ico # win32 (Windows) 平台的图标文件
| └── linux-512x512.png # Linux平台的图标文件(当使用electron-builder)。
└── main-process/
└── electron-preload.js # Electron 预加载脚本(将 Node.js 的东西注入到渲染器线程)。
└── electron-main.dev.js # 主线程代码(前面只有开发代码)。
└── electron-main.js # 主线程代码(生产代码)。
# 新结构
.
└── src-electron/
└──图标/ # 你的应用程序在所有平台上的图标
| ├── icon.icns # 达尔文(MacOS)平台的图标文件
| ├── icon.ico # win32 (Windows) 平台的图标文件
| └── linux-512x512.png # Linux平台的图标文件(当使用electron-builder时)。
└── electron-preload.js # (或.ts) Electron 预加载脚本(将 Node.js 的东西注入到渲染器线程中)。
└── electron-main.js # (或 .ts) 主线程代码
注意,现在已经没有electron-main.dev.js
文件了(不再需要了),electron-preload/main.js
文件需要直接移到/src-electron
下。
electron-main.js文件
为了使我们在使用未来版本的Electron时能够向前兼容,你需要做一些小的(但很重要!)改动:
// 老方法
mainWindow = new BrowserWindow({
// ...
webPreferences: {
nodeIntegration: process.env.QUASAR_NODE_INTEGRATION,
nodeIntegrationInWorker: process.env.QUASAR_NODE_INTEGRATION,
// preload: path.resolve(__dirname, 'electron-preload.js')
}
})
// 新方法
mainWindow = new BrowserWindow({
// ...
webPreferences: {
// 我们启用上下文隔离(反正Electron 12+已经默认启用)。
contextIsolation: true,
// 我们使用一种新的方式来引用预加载脚本
// (这将是需要的,所以添加它并创建文件,如果它不在那里的话)
preload: path.resolve(__dirname, process.env.QUASAR_ELECTRON_PRELOAD)
}
})
electron-preload.js文件
如果你还没有这个文件,你将需要它。如果缺少的话,请创建它。没有它,你将无法在你的渲染器线程中使用Node.js的强大功能。
更多信息: 预加载脚本.
WARNING
你需要把所有Node.js的内容从你的渲染器线程(来自/src的UI代码)转移到预加载脚本中。通过contextBridge
提供同样的功能,如下图所示。
这是electron-preload.js
的默认内容:
/**
* This file is used specifically for security reasons.
* Here you can access Nodejs stuff and inject functionality into
* the renderer thread (accessible there through the "window" object)
*
* WARNING!
* If you import anything from node_modules, then make sure that the package is specified
* in package.json > dependencies and NOT in devDependencies
*
* Example (injects window.myAPI.doAThing() into renderer thread):
*
* const { contextBridge } = require('electron')
*
* contextBridge.exposeInMainWorld('myAPI', {
* doAThing: () => {}
* })
*/
Quasar.config.js更改
// 旧的方式
electron: {
// 现在已经不存在了(即将到来的上游破坏性改变)。
// 被前面记录的electron-main.js中的一个变化所取代
nodeIntegration: true, // 删除我!
// 改名为 chainWebpackMain
chainWebpack (chain) { /* ... */ },
// 改名为 extendWebpackMain
extendWebpack (cfg) { /* ... */ }
}
// 新方法
electron: {
// 是由chainWebpack()改名而来
chainWebpackMain (chain) {
// 其内容的例子(增加了linting)
chain.plugin('eslint-webpack-plugin')
.use(ESLintPlugin, [{ extensions: ['js'] }])
},
// 由extendWebpack()改名而来
extendWebpackMain (cfg) { /* ... */ },
// 新的!
chainWebpackPreload (chain) {
// 例子(增加提示功能)
chain.plugin('eslint-webpack-plugin')
.use(ESLintPlugin, [{ extensions: ['js'] }])
}
// 新的!
extendWebpackPreload (cfg) { /* ... */ }
}
渲染器线程 (/src)
$q对象不再包含electron
属性。你将需要使用预加载脚本来访问它,并将其提供给渲染器线程。
此外,openURL工具不能再接入Electron来打开一个新窗口。你将需要从预加载脚本中提供你自己的util。
WARNING
你将需要把所有Node.js的内容从你的渲染器线程(来自/src的UI代码)转移到preload脚本中。通过contextBridge
提供相同的功能,就像在上面的预加载脚本部分所看到的那样
浏览器Devtools
你可能还需要在你的electron-main.js中加入以下代码,以便在开发模式(或启用调试功能的prod)下自动打开devtools,并在生产构建(未启用调试功能)时禁用devtools。
function createWindow () {
mainWindow = new BrowserWindow({ /* ... */ })
if (process.env.DEBUGGING) {
// 如果在DEV或生产模式下启用了调试功能
mainWindow.webContents.openDevTools()
}
else {
// 我们在生产区,不能访问devtools。
mainWindow.webContents.on('devtools-opened', () => {
mainWindow.webContents.closeDevTools()
})
}
}