Vue 转 EXE 基础教程

lishihuan大约 5 分钟

Vue 转 EXE 基础教程

📖 概述

本文档详细介绍如何将 Vue.js 项目转换为 Windows EXE 可执行文件,使用 Electron 技术栈实现跨平台桌面应用。这是一个通用的基础教程,适用于任何需要将 Web 应用转换为桌面应用的项目。

🛠️ 技术栈

  • Vue.js 2/3 - 前端框架
  • Electron - 桌面应用框架
  • Electron Builder - 打包工具
  • Vue CLI Plugin Electron Builder - Vue 集成插件

🚀 项目初始化

1. 现有 Vue 项目添加 Electron

如果你已有 Vue 项目,执行以下命令添加 Electron 支持:

# 安装 Vue CLI Electron Builder 插件
vue add electron-builder

# 选择 Electron 版本(推荐最新稳定版)
# 选择是否使用 TypeScript(根据项目需要)

2. 全新项目创建

# 创建 Vue 项目
vue create my-electron-app
cd my-electron-app

# 添加 Electron 支持
vue add electron-builder

3. 项目结构

添加 Electron 后的项目结构:

my-electron-app/
├── src/                    # Vue 源码
│   ├── components/
│   ├── views/
│   ├── App.vue
│   └── main.js
├── electron/               # Electron 相关文件
│   ├── main.js            # 主进程文件
│   ├── preload.js         # 预加载脚本
│   └── icon.ico           # 应用图标
├── dist_electron/         # 打包输出目录
├── package.json
└── vue.config.js

⚙️ 核心配置

1. package.json 配置

{
  "name": "my-electron-app",
  "version": "1.0.0",
  "private": true,
  "main": "electron/main.js",
  "homepage": "./",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "electron:serve": "vue-cli-service electron:serve",
    "electron:build": "vue-cli-service electron:build",
    "electron:dev": "vue-cli-service electron:serve"
  },
  "dependencies": {
    "vue": "^2.6.14",
    "vue-router": "^3.5.1",
    "vuex": "^3.6.2"
  },
  "devDependencies": {
    "electron": "^13.0.0",
    "vue-cli-plugin-electron-builder": "^2.1.1"
  }
}

2. vue.config.js 配置

const { defineConfig } = require('@vue/cli-service')

module.exports = defineConfig({
  transpileDependencies: true,
  
  // Electron 配置
  pluginOptions: {
    electronBuilder: {
      // 主进程文件
      mainProcessFile: 'electron/main.js',
      
      // 预加载脚本
      preload: 'electron/preload.js',
      
      // 打包配置
      builderOptions: {
        appId: 'com.yourcompany.yourapp',
        productName: 'Your App Name',
        
        // 应用图标
        icon: 'electron/icon.ico',
        
        // Windows 配置
        win: {
          target: [
            {
              target: 'nsis',
              arch: ['x64', 'ia32']
            }
          ],
          icon: 'electron/icon.ico'
        },
        
        // NSIS 安装器配置
        nsis: {
          oneClick: false,
          allowToChangeInstallationDirectory: true,
          createDesktopShortcut: true,
          createStartMenuShortcut: true
        },
        
        // 文件包含/排除
        files: [
          'dist/**/*',
          'node_modules/**/*',
          'electron/main.js',
          'electron/preload.js'
        ]
      }
    }
  },
  
  // 开发服务器配置
  devServer: {
    port: 8080,
    host: 'localhost'
  }
})

🔧 主进程开发

1. electron/main.js - 基础主进程文件

const { app, BrowserWindow, Menu } = require('electron')
const path = require('path')
const isDevelopment = process.env.NODE_ENV !== 'production'

let mainWindow = null

// 创建主窗口
function createWindow() {
  // 获取屏幕尺寸
  const { screen } = require('electron')
  const primaryDisplay = screen.getPrimaryDisplay()
  const { width, height } = primaryDisplay.workAreaSize

  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
      webSecurity: true
    },
    icon: path.join(__dirname, 'icon.ico') // 应用图标
  })

  // 加载应用
  if (isDevelopment) {
    // 开发模式:加载开发服务器
    mainWindow.loadURL('http://localhost:8080')
    // 打开开发者工具
    mainWindow.webContents.openDevTools()
  } else {
    // 生产模式:加载打包后的文件
    mainWindow.loadFile(path.join(__dirname, '../dist/index.html'))
  }

  // 设置菜单
  Menu.setApplicationMenu(null) // 隐藏菜单栏
  
  // 窗口关闭事件
  mainWindow.on('closed', () => {
    mainWindow = null
  })
}

// 应用就绪时创建窗口
app.whenReady().then(async () => {
  createWindow()
})

// 所有窗口关闭时退出应用
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

// 应用激活时重新创建窗口
app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})

2. electron/preload.js - 预加载脚本

const { contextBridge, ipcRenderer } = require('electron')

// 暴露安全的 API 给渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
  // 获取平台信息
  platform: process.platform,
  
  // 标识这是 Electron 环境
  isElectron: true,
  
  // 版本信息
  versions: {
    node: process.versions.node,
    chrome: process.versions.chrome,
    electron: process.versions.electron
  }
})

🎨 Vue 组件集成

1. 检测 Electron 环境

// 在 Vue 组件中检测 Electron 环境
export default {
  data() {
    return {
      isElectron: false
    }
  },
  
  mounted() {
    this.checkEnvironment()
  },
  
  methods: {
    checkEnvironment() {
      // 检测是否在 Electron 环境中运行
      this.isElectron = window.electronAPI && window.electronAPI.isElectron
      
      if (this.isElectron) {
        console.log('运行在 Electron 环境')
        console.log('版本信息:', window.electronAPI.versions)
      } else {
        console.log('运行在浏览器环境')
      }
    }
  }
}

2. 基础窗口控制组件

<template>
  <div class="app-info" v-if="isElectron">
    <p>运行环境: Electron</p>
    <p>Node.js: {{ versions.node }}</p>
    <p>Chrome: {{ versions.chrome }}</p>
    <p>Electron: {{ versions.electron }}</p>
  </div>
</template>

<script>
export default {
  name: 'AppInfo',
  
  data() {
    return {
      isElectron: false,
      versions: {}
    }
  },
  
  mounted() {
    if (window.electronAPI && window.electronAPI.isElectron) {
      this.isElectron = true
      this.versions = window.electronAPI.versions
    }
  }
}
</script>

📦 打包部署

1. 开发模式运行

# 启动开发模式(热重载)
npm run electron:dev

# 或者
npm run electron:serve

2. 生产环境打包

# 构建生产版本
npm run electron:build

# 指定平台打包
npm run electron:build -- --win
npm run electron:build -- --mac
npm run electron:build -- --linux

3. 打包输出

打包完成后,输出文件位于 dist_electron/ 目录:

dist_electron/
├── win-unpacked/          # Windows 未打包版本
├── Your App Setup.exe     # Windows 安装程序
├── Your App.exe          # Windows 可执行文件
└── latest.yml            # 更新配置文件

🔧 常见问题解决

1. 白屏问题

问题:打包后的应用启动显示白屏

解决方案

// 在 vue.config.js 中设置 publicPath
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
  
  pluginOptions: {
    electronBuilder: {
      builderOptions: {
        // 确保文件路径正确
        files: [
          'dist/**/*',
          'node_modules/**/*'
        ]
      }
    }
  }
}

2. 路由问题

问题:使用 Vue Router 时,刷新页面出现 404

解决方案

// router/index.js - 使用 hash 模式
const router = new VueRouter({
  mode: 'hash', // 使用 hash 模式而不是 history 模式
  base: process.env.BASE_URL,
  routes
})

3. 资源加载问题

问题:图片、字体等静态资源无法加载

解决方案

/* 使用相对路径 */
/* 错误写法 */
background-image: url('/assets/images/bg.jpg');

/* 正确写法 */
background-image: url('./assets/images/bg.jpg');
/* 或者 */
background-image: url('~@/assets/images/bg.jpg');

4. 开发者工具问题

问题:生产环境中意外打开了开发者工具

解决方案

// electron/main.js
if (isDevelopment) {
  // 只在开发模式下打开开发者工具
  mainWindow.webContents.openDevTools()
}

// 禁用右键菜单(可选)
mainWindow.webContents.on('context-menu', (e) => {
  if (!isDevelopment) {
    e.preventDefault()
  }
})

🚀 性能优化

1. 减小包体积

// vue.config.js - 排除不必要的文件
builderOptions: {
  files: [
    'dist/**/*',
    'node_modules/**/*',
    '!node_modules/**/{README.md,CHANGELOG.md,LICENSE}',
    '!node_modules/**/test/**/*',
    '!node_modules/**/*.d.ts'
  ]
}

2. 启用代码分割

// vue.config.js
module.exports = {
  configureWebpack: {
    optimization: {
      splitChunks: {
        chunks: 'all'
      }
    }
  }
}

📋 部署清单

开发阶段

打包阶段

部署阶段

📚 扩展资源


总结:这是一个通用的 Vue 转 EXE 基础教程,涵盖了从项目初始化到打包部署的完整流程。掌握这些基础知识后,就可以根据具体需求进行定制化开发,比如添加 Kiosk 模式等高级功能。