Quasar CLI with Vite - @quasar/app-vite
Electron升级指南

升级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, // 删除我!

  // 移除:
  chainWebpack (chain) { /* ... */ },

  // 移除:
  extendWebpack (cfg) { /* ... */ }
}

// 新方式
electron: {
  // 新!
  inspectPort: 5858,

  // 新!
  extendElectronMainConf (cfg) {
    // do something with Esbuild config
    // for the Electron Main thread
  },

  // 新!
  extendElectronPreloadConf (cfg) {
    // do something with Esbuild config
    // for the Electron Preload thread
  }
}

渲染器线程 (/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()
    })
  }
}