最近有个需求,一个项目里面分了很多模块,每个模块需要单独打包成不同的桌面应用,不同的应用放到不同的电脑里打开,最后还需要软件自启,听起来就有点麻烦~
思路
- 1、作为前端,我首选常用熟悉的vue框架作为开发框架
- 2、在vue中通过配置让每个模块独立打包起来,这样可以达到一个框架打包多个模块,也能统一各模块的样式和很多方法可以共用
- 3、通过electron插件打包成桌面应用
- 4、通过自启目录启动软件
用vue独立打包每个模块(入口配置)
- 创建配置入口文件
projectsConfig.js
yaml
const config = {
townSpace: {
pages: {
index: {
entry: 'src/module/townSpace/main.js',
template: 'public/index.html',
filename: 'index.html',
title: '城镇空间规划'
}
},
devServer: {
port: 8080 // 端口号
// host: "0.0.0.0",
// https: false, // https:{type:Boolean}
// open: false, //配置自动启动浏览器
// disableHostCheck: true,
// // 设置代理
// proxy: {
// "/": {
// target: "根据自己情况填写",
// changeOrigin: true,
// ws: false
// }
// }
}
},
}
module.exports = config
- 在
vue.config.js
中引入入口配置文件 - 想要输出每个包的名称对应需要到
package.json
配置,然后通过process.env.PROJECT_NAME
获取配置的name - vue.config.js配置如下:
arduino
const config = require('./config/projectsConfig.js')
let projectName = process.env.PROJECT_NAME
module.exports = {
...config[projectName],
// 输出文件目录
outputDir: 'dist/' + projectName + '/',
}
package.json配置如下:
json
"scripts": {
"dev:townSpace": "cross-env PROJECT_NAME=townSpace vue-cli-service serve",
"build:townSpace": "cross-env PROJECT_NAME=townSpace vue-cli-service build",
}
- 我的项目结构如图

引入electron插件(这个插件安装有难度,实在不行可以科学上网安装)
- 这里我用了
electron-packager
的插件打包,没用electron是因为安装不成功,老是报错 - 全局指令
yarn add electron -g yarn add electron-packager -g
- 我项目的版本
"electron": "^27.1.2", "electron-packager": "^17.1.2",
- electron配置指令(请注意,指令的./dist/townSpace、软件名称、icon=...、out=...这些都是自己根据实际修改的内容),下面指令包括了打包vue即
yarn build:townSpace
这样可以一步到位打包最新的桌面应用
less
"scripts": {
"app:townSpace": "yarn build:townSpace && electron-packager ./dist/townSpace 软件名称 --platform=win32 --arch=x64 --icon=./electron/icons/townSpace.ico --out=./out-electron --asar --app-version=1.0.0 --overwrite --extra-resource= --ignore=node_modules",
}
- electron配置文件有3个必须的
main.js preload.js package.json
也是这三个控制桌面应用 - main.js内容如下
javascript
const {
app,
protocol,
BrowserWindow,
globalShortcut,
ipcMain
} = require('electron')
// 需在当前文件内开头引入 Node.js 的 'path' 模块
const path = require('path')
// 引入打开exe文件
const { spawn } = require('child_process')
app.commandLine.appendSwitch('--ignore-certificate-errors', 'true')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
const createWindow = () => {
const win = new BrowserWindow({
// width: 3840,
// height: 2160,
// 默认全屏
fullscreen: true,
// 关闭顶部导航栏
frame: false,
// 顶部编辑栏内容
autoHideMenuBar: true,
// titleBarStyle: 'hidden',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
contextIsolation: false // 必须有,不然报错
},
icon: __dirname + '/favicon.ico'
})
win.setMenu(null)
if (app.isPackaged) {
win.loadURL(`file://${path.join(__dirname, './index.html')}`)
} else {
win.loadURL('http://localhost:8080/')
//win.loadURL('http://localhost:5173/')
win.webContents.openDevTools()
}
globalShortcut.register('CommandOrControl+Shift+i', function () {
win.webContents.openDevTools()
})
globalShortcut.register('Esc', function () {
app.quit()
})
globalShortcut.register('F11', function () {
win.setFullScreen(true)
})
}
// 执行关闭程序 自定义关闭
ipcMain.on('handelEsc', function (res) {
app.quit()
})
// 打开.exe程序
ipcMain.on('opendExeFile', function (res) {
const options = {
detached: true,
windowsHide: true,
stdio: 'ignore'
}
const child = spawn(
'C:/规划馆视频文件/基础设施规划(更新综合交通"十四五"规划电子书)/img/03.exe',
[],
options
)
// child.unref() // 让子进程独立运行,使其不受主进程关闭的影响
})
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
- package.json文件内容
json
{
"name": "project",
"version": "1.0.0",
"main": "./main.js"
}
- preload.js文件内容
javascript
// 所有的 Node.js API接口 都可以在 preload 进程中被调用.
// 它拥有与Chrome扩展一样的沙盒。
window.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 + R
,然后输入shell:startup
- 然后就会弹窗一个自启目录了,把需要自启的软件快捷方式复制进去就行了(注意复制的是软件快捷方式,不是直接把打包的.exe文件复制过去)

结束语
- 整个过程其实不难,配置好,有错改错就行
- 这里比较难的是electron插件的安装,有问题也可以去官网查看问题原因
- 软件的icon图标(logo),我这边配置很差不知道为什么,打开后在电脑底部的导航栏显示很模糊,有兴趣可以研究下# Custom App Icons,研究好了告诉我一声
创建不容易,喜欢就用下你的发财小手点个赞~