创建Electron35 + vue3 + electron-builder项目,有很过坑,记录过程

环境: node v20.18.0 npm 11.1.0
用到的所有依赖:
  "dependencies": {
    "core-js": "^3.8.3",
    "vue": "^3.2.13",
    "vue-router": "^4.5.0"
  },
  "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",
    "cross-env": "^7.0.3",
    "dotenv-webpack": "^8.1.0",
    "electron": "^35.0.0",
    "electron-builder": "^25.1.8",
    "eslint": "^7.32.0",
    "eslint-plugin-vue": "^8.0.3"
  },

安装@vue/cli

// 已经安装可以忽略
npm install -g @vue/cli

创建一个新的 Vue 项目

vue create my-electron-vue-app
进入项目目录
cd my-electron-vue-app
修改vue.config.js
// 加上这个,vue build后,发布的页面不会出现白板
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? './' : '/'
};

添加Electron镜像地址

添加.npmrc文件,里面加上。不配置这个会有很多electron相关的文件下载不了。

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

安装 Electron

npm install electron --save-dev
创建Electron入口文件main.js
mkdir electron
touch electron/main.js

// electron/main.js
// app 模块,它控制应用程序的事件生命周期。
// BrowserWindow 模块,它创建和管理应用程序 窗口。
const { app, BrowserWindow, ipcMain } = require('electron')
// 部引入 Node.js 中的 path 模块
const path = require('path')

const process = require('process')

// 添加一个createWindow()方法来将index.html加载进一个新的BrowserWindow实例
function createWindow () {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      //预加载
      // __dirname 字符串指向当前正在执行脚本的路径 (本项目,指向项目的根文件夹)。
      // path.join API 将多个路径段联结在一起,创建一个跨平台的组合路径字符串。
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  if (process.env.NODE_ENV === 'development') {
    mainWindow.loadURL('http://localhost:8080');
  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
  } else {
    mainWindow.loadFile(path.join(__dirname, '../dist/index.html'));
  }

}

// 在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。 
// 您可以通过使用 app.whenReady() API来监听此事件。 
// 在whenReady()成功后调用createWindow()。
app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    // 在macOS上,当单击dock图标并且没有其他窗口打开时,通常会在应用程序中重新创建一个窗口
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// 在Windows和Linux上,关闭所有窗口通常会完全退出一个应用程序。
// 为了实现这一点,监听 app 模块的 'window-all-closed' 事件,
// 并在用户不是在 macOS (darwin) 上运行时调用 [app.quit()][app-quit]
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
创建Electron预加载文件preload.js
touch electron/preload.js

// electron/preload.js
/**
 * 预加载
 * 预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 window 和 document) 和 Node.js 环境(例如 process)
 */ 
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])
  }
})
修改package.json
// package.json
{
  ...
  // 加入"main": "electron/main.js"
  "main": "electron/main.js",
  "scripts": {
    ...
    // 本地启动命令electron:serve
    "electron:serve": "set NODE_ENV=development&& electron ."
  },
  ...
}

安装Electron打包程序electron-builder

npm install electron-builder --save-dev
修改package.json添加命令及build配置
// package.json
{
  ...
  "scripts": {
    ...
    "electron:build": "set NODE_ENV=production&& electron-builder"
  },
  // electron打包配置
  "build": {
    "appId": "com.example.yourapp",
    "productName": "YourApp",
    "directories": {
      "output": "dist_electron"
    },
    "files": [
      "dist/**/*",
      "electron/*"
    ],
    "win": {
      "target": "nsis",
      "icon": "build/icon.ico"
    },
    "mac": {
      "target": "dmg",
      "icon": "build/icon.icns"
    },
    "linux": {
      "target": "AppImage",
      "icon": "build/icon.png"
    }
  },
  ...
}
也可以把electron打包配置到单独的electron-builder.yml文件。好处是可以注释。
appId: com.example.yourapp
productName: YourApp
copyright: Copyright © 2025 MyApp
directories:
  output: dist_electron
files:
  - "dist/**/*"
  - "electron/*"
asar: true
win:
  target: nsis
  icon: build/icon.ico
mac:
  target: dmg
  icon: build/icon.icns
linux:
  target: AppImage
  icon: build/icon.png
nsis:
  oneClick: false # 是否一键安装
  #allowElevation: true # 允许请求提升权限
  allowToChangeInstallationDirectory: true # 允许修改安装目录
  createDesktopShortcut: true # 创建桌面快捷方式
  createStartMenuShortcut: true # 创建开始菜单快捷方式

安装配置env环境变量

安装 dotenv-webpack dotenv-flow
npm install dotenv-webpack dotenv-flow --save-dev
修改vue.config.js
const Dotenv = require('dotenv-webpack');
const DotenvFlow = require('dotenv-flow');

module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
  transpileDependencies: true,
  configureWebpack: {
    plugins: [
      new Dotenv({
        defaults: true, // 加载 .env 文件中的默认值
        systemvars: true, // 加载系统环境变量
        expand: true, // 支持变量扩展(如 ${VAR})
        ...DotenvFlow.config().parsed // 使用 dotenv-flow 加载 .env 文件
      })
    ]
  }
};
安装cross-env
npm install cross-env --save-dev
修改package.json 启动配置
{
  ...
  "scripts": {
    // "serve": "vue-cli-service serve",
    "serve": "cross-env NODE_ENV=development vue-cli-service serve",
    // "build": "vue-cli-service build",
    "build": "cross-env NODE_ENV=production vue-cli-service build",
    ...
  },
 }
创建 .env 文件
touch .env
touch .env.development
touch .env.production

// .env 通用配置
API_URL=https://api.example.com

// .env.development
API_URL=https://dev.api.example.com

// .env.production
API_URL=https://pro.api.example.com

安装vue-router配置

npm install vue-router

// src/router/index.js
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router';
import HelloWorld from '../components/HelloWorld.vue';

const routes = [
  { path: '/', component: HelloWorld }
];

const router = createRouter({
  // electron打包用createWebHashHistory,如果用createWebHistory,页面会出现白板。
  history: process.env.NODE_ENV === 'production'
    ? createWebHashHistory(process.env.BASE_URL)
    : createWebHistory(process.env.BASE_URL),
  routes,
});

执行命令

electron本地启动
npm run electron:serve
electron打包
// 先执行vue的打包
npm run build
// 再执行electron的打包
npm run electron:build
相关推荐
谈谈叭1 天前
代码优化——基于element-plus封装组件:表单封装
开发语言·前端·javascript·性能优化·vue3·vite·element-plus
David+Zhao3 天前
vue-cli3+vue2+elementUI+avue升级到vite+vue3+elementPlus+avue总结
elementui·vue3·vite·elementplus·vue-cli·avue·vue2升级
iiismobi4 天前
前端数据模拟 Mock.js 学习笔记
前端·javascript·vue3·mock.js
Hopebearer_9 天前
Vue3生命周期以及与Vue2的区别
前端·javascript·vue.js·前端框架·vue3
码农研究僧11 天前
UniApp 中封装 HTTP 请求与 Token 管理(附Demo)
vue3·uniapp·js·token·request
猫猫村晨总15 天前
基于TensorFlow.js与Web Worker的智能证件照生成方案
前端·tensorflow·vue3
字节颤抖20 天前
vite+vue3开发uni-app时低版本浏览器不支持es6语法的问题排坑笔记
前端·uni-app·es6·vue3·vite·babel·兼容
前端熊猫22 天前
Vue 3 生命周期和生命周期函数
前端·javascript·vue.js·vue3·生命周期函数
西门吹雪~23 天前
【前端面试】在Vue3中,beforeMount和mounted钩子函数有什么区别?
前端·javascript·vue.js·前端框架·vue3