{T}

开发环境搭建

## 前言 工欲善其事必先利其器,在进行实战开发的时候,我们最终的步骤是搞好一个舒服的开发环境,目前支持 VueElectron 工程化工具主要有 electron-vueVue CLI Plugin Electron Builderelectron-vite

electron-vue 已经年久失修了,暂时就不介绍了,有兴趣的小伙伴可以去看看它的官网试着玩玩。

接下来我们将分别介绍基于 Vue CLI Plugin Electron Builderelectron-vite 的开发环境搭建。

vue-cli-plugin-electron-builder

vue-cli-plugin-electron-builder 是一个基于 VueCli 的插件工具,它是一个 npm 包,能够为 Vue CLI 创建的项目添加 Electron 构建的能力。

1. 创建一个 VueCli 项目

既然它是一个基于 VueCli 的插件工具,所以首先需要确保你的本地环境中已经安装好了 VueCli 工具,如果还未安装,可以使用以下命令进行安装:

sh
npm install -g @vue/cli
# OR
yarn global add @vue/cli

安装好 CLI 工具后,我们需要使用 CLI 创建一个 Vue 项目:

sh
vue create electron-vue

这里,我们选择 Vue 3 + babel + eslint 的模式:

创好了后,一起来看一下我们的大致目录结构:

sh
.
├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── App.vue
│   ├── assets
│   ├── components
│   └── main.js
├── README.md
├── babel.config.js
├── jsconfig.json
├── package.json
├── vue.config.js
└── yarn.lock

2. 安装 vue-cli-plugin-electron-builder

既然 vue-cli-plugin-electron-builder 是个 VueCli 插件,那么就可以使用 CLI 命令 vue add 的方式进行插件安装:

sh
# 安装并调用 vue-cli-plugin-electron-builder
vue add electron-builder

在安装的时候,只提供了 Electron v11、v12、v13 这 3 个版本选择,这里我们先选 v13。后面我们再进行升级。

安装完成后,我们再看一下我们的目录结构:

sh
.
├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── App.vue
│   ├── assets
│   ├── background.js
│   ├── components
│   └── main.js
├── README.md
├── babel.config.js
├── jsconfig.json
├── package.json
├── vue.config.js
└── yarn.lock

接下来,我们将再详细介绍一下一些核心文件的作用:

  1. package.json:这个文件通过 main 字段定义了编译后的主入口文件路径,并且通过 script 字段定义了应用程序的启动、编译等脚本程序。
  2. src/background.js:这个文件就是 Electron 的主进程的入口文件,它是应用程序的入口点,负责管理整个应用的生命周期、创建窗口、原生 API 调用等。
  3. src/main.js 是渲染进程的入口文件,就是我们通常写的 Vue 前端代码的入口。

3. 目录结构优化

为了更好地开发体验降低心智负担的理解成本,我们需要对整体目录进行一下优化。优化的目标是为了更容易区分主进程和渲染进程:

sh
.
├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── main
│   │   └── index.js
│   └── renderer
│       ├── App.vue
│       ├── assets
│       ├── components
│       └── main.js
├── README.md
├── babel.config.js
├── jsconfig.json
├── package.json
├── vue.config.js
└── yarn.lock

这里,我们新建了 mainrenderer 目录,并将之前的 src/background.js 迁移到了 main 目录下,且重命名为 index.js。然后再把之前和 Vue 相关的渲染进程的文件以及文件夹全部迁移到了 renderer 目录下。

这样在开发的时候,就可以一眼看明白哪些属于渲染进程、哪些属于主进程。

因为我们做了目录的调整,所以我们需要重新修改一下 vue.config.js 的编译配置:

js
// vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  pages: {
    index: {
      // 修改渲染进程入口文件的位置
      entry: 'src/renderer/main.js',
    },
  },
  pluginOptions: {
    electronBuilder: {
      nodeIntegration: true,
      // 修改主进程的入口文件位置
      mainProcessFile: 'src/main/index.js',
      // 设置主进程的修改监听,当主进程发生变更时,可以及时热更
      mainProcessWatch: ['src/main'],
    },
  },
})

最后,也要记得修改 package.json 里面的 main 配置:

json
{
  ...
  "main": "index.js",
  ...
}

4. 升级 electron

目前最新 stable 版本的 Electronv27.1.3

那我们可以直接升级到这个版本:

sh
yarn add electron@latest.1.3 -D

如果在安装过程中遇到了网络错误:

可以添加一个 .npmrc 文件代理 Electron 的安装源,指向 taobao

bash
electron_mirror=https://npmmirror.com/mirrors/electron/

修改完成后,我们运行一下启动本地服务:

sh
npm run electron:serve

大工告成!🎉🎉

electron-vite

electron-vite 是一个新型 Electron 开发构建工具,旨在为 Electron 提供更快、更精简的开发体验,它是基于 vite 构建 Electron 应用的。

我们可以使用 @quick-start/electron 工具快速创建一个 electron-vite 的应用:

sh
npm create @quick-start/electron

然后按照提示进行下一步即可:

bash
 Project name: <electron-app>
 Select a framework: vue
 Add TypeScript? No / Yes
 Add Electron updater plugin? No / Yes
 Enable Electron download mirror proxy? No / Yes
 
Scaffolding project in ./<electron-app>...
Done.

新建完成后,一起来看一下 electron-vite 为我们创建的项目结构:

bash
.
├── build
│   ├── entitlements.mac.plist
│   ├── icon.icns
│   ├── icon.ico
│   └── icon.png
├── resources
│   └── icon.png
├── src
│   ├── main
│   │   └── index.js
│   ├── preload
│   │   └── index.js
│   └── renderer
│       ├── index.html
│       └── src
├── README.md
├── electron-builder.yml
├── electron.vite.config.js
├── package.json
└── yarn.lock

可以看到整体目录结构还是比较规范和清晰的,我们几乎不需要进行任何调整就可以直接使用了。

接着,在我们安装好相关的依赖后,我们运行:

sh
npm run dev

就可以直接看到运行结果:

不过这里使用的 Electron 版本是 v25.9.7,使用的是最新发布 stable 下的较低版本。如果你想要升级到最新版本,可以按照之前的做法一样来进行升级。

大工告成!🎉🎉

主进程启动项目

不管是通过 vue-cli-plugin-electron-builder 创建还是通过 electron-vite 创建的项目,都需要通过唯一的主进程进行应用程序的启动。

我们之前在《Electron 的基础概念》中介绍了 Electron 的 app 模块管理者应用程序的生命周期来说,主进程的第一步操作就是监听 app ready 事件,来创建窗口:

js
// main/index.js
app.whenReady().then(() => {
  // 创建窗口。
  createWindow()
})

接下来,我们需要通过 createWindow 函数构造一个简单的窗口:

js
// main/index.js
function createWindow() {
  // 创建窗口
  const mainWindow = new BrowserWindow({
    width: 900,
    height: 670,
    show: false,
    autoHideMenuBar: true,
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  })
 
  mainWindow.on('ready-to-show', () => {
    mainWindow.show()
  })
 
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
   // 开发环境,通过 loadURL 加载 devServer
   mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    // 生产环境,加载构建后的文件
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }
}

需要注意的是,我们在窗口初始化时,指定了 show: false 的参数,意味着窗口创建完成后不会立即显示。然后通过监听 mainWindow.on('ready-to-show') 的事件触发后再通过 mainWindow.show() 方法来显示窗口。

这样做是因为 Electron 中的 ready-to-show 事件表示窗口内容已经加载完成且应用程序准备好显示给用户。在等待 ready-to-show 事件触发后再调用 window.show(),可以确保用户看到的是完全加载并准备好的界面,避免了展示未完成的内容。

最后,通过监听 app.on('window-all-close') 事件,来处理非 macOS 下的所有窗口关闭后的逻辑:退出整个 electron 应用。

js
// main/index.js
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

这是因为在 windows 平台上,通常我们把应用的窗口都关了之后也就默认把这个应用给退出了。而如果在 macOS 系统上却不是这样。我们把应用的窗口关闭了,但是并非完全退出这个应用。

我们已经在《Electron 跨平台兼容性措施》章节为大家详细介绍了更多的一些跨平台兼容性实现。

总结

整体看来,使用 vue-cli-plugin-electron-builder 来构建 Electron 应用的话,需要自己做更多的配置工作;而 electron-vite 本身就是一个基于 vite + electron 脚手架工具,相对而言已经有一套约定俗称的目录和配置规范,所以对于新手开发者而言会更加友好。

其实一个最简单的 Electron 应用的目录结构大致如下:

text
.
├── index.html
├── main.js
├── renderer.js
├── preload.js
└── package.json

而所谓的构建工具就是为了生成这样的目录内容: