Electron+VueCli构建桌面app
electron+vue-cli学习笔记
[TOC]
说在前面
本人也是纯小白一个,接触Electron也不久。这篇文章主要是用来记录笔记,有些东西长时间不用就容易忘记,这里做好笔记在之后也会节省很多时间。另外也想分享一下自己的学习过程还有一些踩过的坑,希望帮助到有需要的人!
本篇文章面向有一定前端基础的小白(HTML、CSS、JS…),vue2和vue-cli,其实vue倒是可有可无,如果你只想创建一个简单的electron应用程序,有前端三件套的知识就够了。文章主要介绍electron的基础使用、electron的打包、以及在vue-cli开发环境中如何使用electron去打包出一个桌面端应用程序(win & Mac)。
所用到的语言以及工具。
- Vue.js (vue2) —基础语言
- Vue-Cli —用于创建vue脚手架
- Electron —用于将项目打桌面应用程序
- node.js —基础语言工具(自带npm)
- nodemon —实时刷新重启服务插件
- Vue CLI Plugin Electron Builder —在vue-cli状态下使用(Vue插件)
- electron-icon-builder —将图片打包成安装程序图标icon(不用也行)
- VS Code —基础开发工具啦,你可以选择自己喜欢的(顺便提一句,我们强大的vscode就是使用Electron开发的呢!)
Electron是什么?
Copy一段来自官网的介绍:Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS和Linux——不需要本地开发 经验。
基础Electron部分
**注意:如果你只想看vue-cli篇,请自行跳转到Vue-cli篇,这部分安装的electron与vue-cli篇部分安装的不一样。
安装node.js
正如Electron官网所说:在使用Electron进行开发之前,您需要安装**Node.js。**
在node.js的环境中自带有npm,在之后的开发插件安装中,几乎都离不开npm来安装一些依赖和库(也可以使用yarn和pnpm…)
1. 下载node.js安装包(自行安装v14.17.5以上版本)
- [Node.js官网]:https://code.visualstudio.com
- 注意:需要使用Electron的话请安装node版本超过v14.17.5
- 这里推荐各位小伙伴们可以使用nvm-windows去合理的控制自己的node版本哦!这里附上nvm详细安装步骤以及使用(window10系统)
2. 配置Node.js环境变量
- 将安装的目录配置到系统环境变量和用户变量中
3. 测试Node.js是否安装成功
在cmd
或者vscode终端中输入以下命令
1 |
|
如果显示node和npm版本这表示安装Node.js以及配置环境变量成功!
安装Electron
在安装好Node.js的前提下,接下来我们来安装 Electron
1. 初始化一个Node.js项目
在安装electron之前我们需要先创建一个文件夹,并初始化它为一个新的Node.js项目。
首先我们创建一个文件夹
使用cmd或者vscode终端进入该文件夹
输入一下命令将文件夹初始化为一个Node.js项目
1
npm init
按
Enter
在输入了描述、作者等信息后,这时候你会发现你的文件夹中出现了package.json文件package.json
文件大致是这样的:1
2
3
4
5
6
7
8
9
10
11
12{
"name": "my-electron-test",
"version": "1.0.0",
"description": "xxxx",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
},
"author": "VGhunter",
"license": "ISC",
"dependencies": {
}
}这个文件里面的参数我们后面会一点点添加和修改。
到这里你成功初始化了一个Node.js项目文件。
2. 使用npm命令安装Electron
好了,现在可以安装Electron了。
在
cmd
或者vscode终端下输入一下命令1
2npm install electron --save-dev #在当前项目中安装electron
npm install -g electron #在全局安装electron注意:这里本人建议使用全局安装,因为这里有一个大坑。
在安装过程中,electron 模块会通过 electron-download 为您的平台下载 Electron 的预编译二进制文件。
这个是官方原话。没错,它会在安装之后下载所谓的预编译二进制文件,这点我问过chatGPT,它回答我说,这里的预编译文件大概80m左右,但是它真的要下特别特别久,没有耐心的朋友可能就中途就退出了。所以建议大家全局安装,就不用每次安装了。这一点我也不是特别理解是什么东西。如果有朋友们有什么解决办法,或者更好的办法麻烦可以评论区说一下。
下载完成之后 测试一下是否安装成功了
1
2npm list --depth=0 //查看已经安装的项目依赖
npm list -g --depth=0 //查看已经安装的全局依赖如果都看到了
electron@22.0.0
则代表安装成功了
这时在看你的项目文件夹,发现多了一个node_modules
文件夹,不用管他,里面就装着一些相关依赖啦!
再看我们的package.json
文件:
如果你是使用npm install electron --save-dev
安装的话,你的文件里面应该多出了一个devDependencies
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15{
"name": "my-electron-test",
"version": "1.0.0",
"description": "xxxx",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
},
"author": "VGhunter",
"license": "ISC",
"dependencies": {
},
"devDependencies": {
"electron": "^22.0.0", //刚刚安装的electron依赖显示在这
},
}如果你使用的
npm install -g electron
,那么electron就安装在全局,这样在任何项目都可以使用electron啦!
创建一个Electron应用
1. 编辑package.json文件
在package.json中添加main程序入口和scripts程序启动命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"name": "my-electron-test",
"version": "1.0.0",
"description": "xxxx",
"main": "main.js", //Electron程序入口文件
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "electron ." //Electron程序启动命令
},
"author": "VGhunter",
"license": "ISC",
"dependencies": {
}
}
2. 创建main.js入口文件
在文件根目录创建main.js文件
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41// main.js
// 引入app和BrowserWindow
const { app, BrowserWindow } = require('electron')
const path = require('path')
const createWindow = () => {
// 创建一个窗口,长为800宽为600
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: { // 预加载脚本
preload: path.join(__dirname, 'preload.js')
}
})
// 加载 index.html,就是你想展示的界面也可以使用
mainWindow.loadFile('index.html')
// 打开开发工具
// mainWindow.webContents.openDevTools()
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
// code. 也可以拆分成几个文件,然后用 require 导入。
3. 创建index.html文件
在根目录创建你想暂时的index.html文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
<!-- 您也可以此进程中运行其他文件 -->
<script src="./renderer.js"></script>
</body>
</html>这个时候你在终端输入
npm run start
,就可以启动Electron程序了
不出意外应该会弹出一个窗口,而窗口的内容就是你的index.html
中编写的内容
4. 创建预加载脚本preload.js(可有可无)
同样在项目根目录创建一个名为
preload.js
的文件 作为预加载脚本文件1
2
3
4
5
6
7
8
9
10window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 window 和 document) 和 Node.js 环境。
这个文件的代码大概作用就是在程序加载之前,通过这个文件去修改index.html的DOM元素,将版本号输出到index.html中,具体的我也不是很懂。总之这个文件如果不创建也是不影响的!!
到了这里,一个超级基础的Electron应用程序就算创建完成了。
使用npm run start
来启动你的程序,你见看到一个windows窗口弹出,而里面是你创建index页面。
如果你想让你的应用变得更加丰富,请修改你的main.js
文件,来让你的应用程序有更完善的功能。
更多的教程还请浏览**Electron官网开发指南**
5. 安装nodemon实时刷新插件
到这里你已经已经可以使用npm run start
去开启你的Electron程序了
但是我们来优化一个在开发中遇到的问题
每次我们使用npm run start
打开应用查看之后,如果我们修改了内容,页面不会实时刷新,需要Ctrl+C
关闭程序在重新启动!
我们优化这个问题,使用 nodemon
在全局安装nodemon
1
npm install -g nodemon
修改Electron启动命令
进入根目录的package.json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15{
"name": "my-electron-test",
"version": "1.0.0",
"description": "xxxx",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon --exec electron ." //添加nodemon启动方式
},
"author": "VGhunter",
"license": "ISC",
"dependencies": {
"nodemon": "^2.0.20"
}
}现在你再使用
npm run start
启动,然后修改main.js文件的内容,程序将自动重启刷新内容。
Electron + Vue-Cli部分
- 知道了基础的Electron使用方法之后,我们开始结合Vue-Cli来创建一个Electron应用。
- 这里我们使用的插件是 Vue CLI Plugin Electron Builder 来实现在脚手架创建Electron应用
- 此外你还可以使用Electron-vue脚手架来直接创建一个基于vue的electon项目
1. 初始化一个vue-cli项目
安装vue-cli脚手架
1
2
3npm install -g @vue/cli
# OR
yarn global add @vue/cli安装完成之后 你可以在终端使用
vue --version
查看是否安装成功创建一个vue-cli项目
切换到你想创建项目的目录 执行一下指令1
vue create my-vue-cli
选择你需要创建的vue版本,这里我们使用vue2来举例
启动vue-cli项目
切换到你创建的vue脚手架项目内部 使用一下命令启动服务1
npm run serve
在加载完成之后 默认情况使用
https://localhost:8080
就能看到界面了
这样就创建好了一个vue脚手架项目,具体的vue-cli脚手架使用方法,还请浏览Vue CLI官网
2. 安装Vue CLI Plugin Electron Builder
Vue CLI Plugin Electron Builder是一个基于Vue的插件 所以我们使用一下命令来安装
1
vue add electron-builder
稍等片刻后…
额没错,你会发现等了很久,因为使用这个命令安装同样是需要下载electron-13版本的二进制预编译包的,现在我也没有找到其他办法,貌似只有等待。但是好像在下载了一遍之后,在其他新建的项目中就不会再下载了,可能是缓存到了本地,对此我也不是很懂,如果有懂的大佬麻烦评论区留言,谢谢!!漫长的等待之后 我们来查看一下package.json文件
如果你的package.json文件和这个差不多 而且安装没有报错 就算是安装成功了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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55{
"name": "electron-app",
"version": "0.1.0",
"description": "electron-app",
"author": "VGhunter",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"electron:build": "vue-cli-service electron:build",
"electron:serve": "vue-cli-service electron:serve",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps",
},
"main": "background.js",
"dependencies": {
"core-js": "^3.8.3",
"electron-icon-builder": "^2.0.1",
"vue": "^2.6.14"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"electron": "13.0.0",
"electron-devtools-installer": "^3.1.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"nodemon": "^2.0.20",
"vue-cli-plugin-electron-builder": "^2.1.1",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}我们使用
npm run electron:serve
来看看是否能够启动应用1
npm run electron:serve
这个命令会自动先启动一遍vue-cli的服务在在启动electron服务
如果启动成功 则会出现一个window窗口 里面就是你的vue界面 代表插件安装正常
3. 程序入口background.js文件
在vue-electron-builder插件中,我们的electron的入口文件被放在
src
目录中 名为background.js
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82'use strict'
import { app, protocol, BrowserWindow } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
async function createWindow() {
// Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
win.removeMenu()
}
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}这里主要的逻辑写在
createWindow()
这个函数中 其中BrowserWindow({...})
是创建一个windows窗口,你也可以自行new一个新的窗口在合适的时候弹出。width
和height
分别是设置窗口的长和宽,这里还有一些简单的属性,比如:show:true
是否在程序启动时显示这个窗口。frame:false
是否显示窗口边框alwaysOnTop:true
窗口是否总是显示在最前面
…
更多的请浏览Electron官网API-BrowserWindow
在
if (process.env.WEBPACK_DEV_SERVER_URL)
模块中,我们对窗口执行一些操作,比如win.loadRUL(url)
是将url连接加载到win
这个窗口中,而上面代码就是加载vue-cli服务的https://loaclhost:8080
这个地址。使用win.loadFile(path)
则是使用文件路径加载文件。注意:关于这个地方有个坑:请跳 这里
app.on('window-all-closed', () => {...}
意思是在所有窗口都关闭的时候,关闭程序。下面是几个简单常用的:win.show()
展示窗口并聚焦到顶部win.destroy()
销毁窗口win.focus()
聚焦窗口
其他还有更多内容请浏览 Electron官网 应用程序开发Api
4. 在窗口加载本地html文件
由于在服务启动之后,你没有办法直接用路径去加载一个本地文件。
这里vue-electron-builder给出了一个全局变量__static
,我们使用path.json
方法创建一个路径,方法如下:- 将你想加载的html文件放到
public
文件目录中. - 使用
path.json
来创建路径,并使用win.loadFile()
来加载html文件。
1
2const fileLocation = path.join(__static, 'preload.html')
win.loadFile(fileLocation);这样 你就能在background.js中创建一个加载本地文件的窗口了…
- 将你想加载的html文件放到
5. 去除窗口默认菜单栏
在一个应用程序项目中 我们不可能去使用electron的默认菜单栏 怎么去除呢?有下面几种方法:
- 引入
Menu
方法,在app.on('ready',()=>{...})
中添加Menu.setApplicationMenu(null)
:
1
2
3
4
5
6
7
8
9
10
11
12app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
Menu.setApplicationMenu(null); //去除默认菜单栏
})- 使用
win.setMenu(null);
1
2
3app.on('browser-window-created', function (event, window) {
window.setMenu(null);
});也可以直接在
createWindow()
函数对所需要操作的窗口使用。- 使用
win.removeMenu()
,直接在createWindow()
函数中对所需要的窗口使用
1
2
3
4
5
6
7
8
9
10
11...
const load = new BrowserWindow({
width: 550,
height: 300,
show:true,
frame:false,
// resizable: true //用于可调整窗口大小(貌似没用)
alwaysOnTop:true,
})
...
load.removeMenu() //移除load窗口的默认菜单栏当然如果你先创建自己的菜单栏也是可以的,请浏览 Menu
- 引入
6. 打包应用程序
注意:在打包之前这里要讲一个我自己遇到的坑!在background.js文件夹中,我们在开发阶段测试时的代码都时写在
if (process.env.WEBPACK_DEV_SERVER_URL) {...}
中的,这时如果你打包,会发现写的任何逻辑都无效了。因为这个模块里面是写开发时的逻辑的,而如果不是开发时的代码要写在下面的else
模块中!!巨坑呀,我也是没有注意到有英文提示,整了我好久…没想到是写错位置了/(ㄒoㄒ)/~~
使用
npm run electron:build
来将项目打包成桌面程序
打包成功之后 根目录会出现新的文件夹dist_electron
,里面就是打包好的应用程序。修改打包设置,图标、安装路径等…
先将图片裁剪成正确的大小和格式,使用 electron-icon-builder
安装插件:1
npm install -g electron-icon-builder
在
package.json
文件中的script
中添加命令:1
"build-icon": "electron-icon-builder --input=./public/logo.jpg --output=build --flatten"
其中
--input
为你需要裁剪的图片路径,--output
为你的图片出路径
使用插件:1
npm run build-icon
在根目录原有的
vue.config.js
文件中添加配置: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
27
28
29
30
31
32
33
34
35const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
pluginOptions: {
electronBuilder: {
builderOptions: {
appId: "184789",
productName: "electronApp", //项目名,也是生成的安装文件名,即aDemo.exe
copyright: "nicnic © 2022", //版权信息
directories: {
output: "./dist" //输出文件路径
},
win: {
//win相关配置
icon: "./build/icons/icon.ico", //图标,当前图标在根目录下,注意这里有两个坑
target: [
{
target: "nsis", //利用nsis制作安装程序,打包文件的后缀为exe
arch: [
"x64", //64位
"ia32" //32位
]
}
]
},
nsis: {
oneClick: false, //一键安装
language: "2052", //安装语言
perMachine: true, //应用所有用户
allowToChangeInstallationDirectory: true //用户可以选择路径
}
}
}
}
})这时候我们再使用
npm run electron:build
,就会dist
文件夹中出现已经打包好的应用程序文件夹和应哟安装程序了,而且图标和选择安装路径功能都实现了!
更多的配置请自行研究electron-builder
最后
到这里关于electron+vue-cli的简单分享就完成了,因为第一次认真写文章,废话也有点多,还请见谅!如果你也成功的创建了一个electron应用,请留言评论告诉我吧,如果在文章中有哪里有问题,欢迎到评论区提出!!!