Day 2:10 分钟搭 Electron + Vite + Vue 3——AnchorChat 的第一个窗口

手把手搭 AnchorChat 空壳:Vite 双入口、主进程开窗口、Vue 3 挂载。让你 npm start 看见第一个 Electron 窗。


开场:白板上的框,得先能弹出来

Day 1 我们在白板上画好了三栏:左账号、中聊天、右工具。老王问:「啥时候能跑?」我说:「明天。」------然后 Day 2 真的来了,发现 Electron 项目不是 create-react-app 一行命令就完事

AnchorChat 要同时跑三个世界:

  • 主进程(Node):开窗口、注册 IPC、以后管 SQLite
  • 预加载(preload):/renderer 和主进程之间的安检通道
  • 渲染进程(Vue):你看得见的 UI

今天目标很克制:不搞登录、不搞 webview、不搞翻译 。只要 npm start 之后,屏幕上出现一个能点的 Electron 窗口,里面 Vue 能挂载------就像婴儿迈出第一步,丑没关系,能站住就行。

今天做什么:从 0 到 npm start

1. 目录先摆对

我们用的是 Vite 渲染 + vite-plugin-electron 编主进程 的方案,根目录大致这样:

text 复制代码
anchor-chat-client/
├── electron/
│   ├── main.ts          # 主进程入口
│   └── preload.ts       # 预加载
├── src/
│   ├── index.ts         # Vue 入口
│   ├── App.vue
│   └── router/          # 路由(今天只 做到登录页占位)
├── index.html           # Vite 挂载点
├── vite.config.ts
└── package.json

别被「三个入口」吓到------开发时你只敲一条命令 ,插件帮你把 main/preload 编译进 dist-electron/

2. package.json:告诉 Electron 主文件在哪

Electron 启动时会读 package.jsonmain 字段。开发模式下 Vite 插件会把 electron/main.ts 编译到 dist-electron/main.js,所以脚本长这样:

json 复制代码
{
  "name": "anchor-chat",
  "type": "module",
  "scripts": {
    "start": "vite",
    "build": "vite build && electron-builder"
  },
  "main": "dist-electron/main.js",
  "devDependencies": {
    "electron": "^29.4.6",
    "vite": "^5.1.6",
    "vite-plugin-electron": "^0.28.6",
    "vue": "^3.4.21"
  }
}

npm start 本质是跑 Vite dev server,同时插件 watch 编译主进程,编译完自动拉起 Electron------热更新双轨并行,比老 webpack 时代省心一截。

3. vite.config.ts:双入口一条线串起来

核心就一段 electron() 插件配置:

typescript 复制代码
import { defineConfig } from 'vite'
import path from 'node:path'
import electron from 'vite-plugin-electron/simple'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    vue(),
    electron({
      main: {
        entry: 'electron/main.ts',
      },
      preload: {
        input: path.join(__dirname, 'electron/preload.ts'),
      },
    }),
  ],
  resolve: {
    alias: [{ find: '@', replacement: path.resolve('src') }],
  },
})

这里发生了三件事:

  1. Vue 插件 处理 src/index.html(渲染进程)
  2. main.entryelectron/main.ts 打成 dist-electron/main.js
  3. preload.input 把 preload 打成 dist-electron/preload.mjs

4. electron/main.ts:主进程只干一件事------开窗

Day 2 的 main.ts 可以瘦到只剩骨架(托盘、单实例、IPC 都是 Day 3 起的活):

typescript 复制代码
import { app, BrowserWindow } from 'electron'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
process.env.APP_ROOT = path.join(__dirname, '..')

const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL']
const RENDERER_DIST = path.join(process.env.APP_ROOT, 'dist')

let win: BrowserWindow | null = null

function createWindow() {
  win = new BrowserWindow({
    width: 1250,
    height: 690,
    autoHideMenuBar: true,
    minWidth: 900,
    minHeight: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.mjs'),
      contextIsolation: true,
      nodeIntegration: false,
    },
  })

  // 开发:加载 Vite 地址;打包:加载 dist/index.html
  if (VITE_DEV_SERVER_URL) {
    win.loadURL(VITE_DEV_SERVER_URL)
  } else {
    win.loadFile(path.join(RENDERER_DIST, 'index.html'))
  }
}

app.whenReady().then(() => {
  createWindow()
})

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

两个分支很重要:

  • 开发VITE_DEV_SERVER_URL 由插件注入,走 HMR,改 Vue 秒刷新
  • 生产loadFile 读打包后的 dist/index.html

contextIsolation: true + nodeIntegration: false 是 Electron 12+ 的默认安全姿势------渲染进程不能直接 require('fs'),以后走 preload + IPC。

5. 渲染进程:src/index.ts 挂上 Vue

typescript 复制代码
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'

createApp(App)
  .use(ElementPlus)
  .use(router)
  .mount('#app')

App.vue 里一个 <router-view /> 就够。路由默认 //login,所以今天窗口里大概率是 登录页占位------别慌,今天看见登录框说明链路通了。

跑通后的目录产物:

  • dist/ --- 渲染进程打包结果(开发时走 dev server,不一定落盘)
  • dist-electron/main.jspreload.mjs --- 主进程与 preload

踩坑与思考

  • main 路径不对 → Electron 启动即崩 。一定要等 Vite 插件先把 main.ts 编译完;第一次 npm start 多等几秒是正常的。
  • 白屏但无报错 :多半是 loadURL 的端口和 Vite 不一致,或 index.html#app 写错。DevTools 里看 Network 最快。
  • 安全默认值别省 。为了赶进度开 nodeIntegration: true 能省半小时,以后 preload 重构能省你三天------Trust me bro(别 trust)。

你们 Electron 项目用的是 Vite 还是 webpack?第一次 npm start 卡了多久?评论区报时------Day 3 见。

相关推荐
阿里云云原生1 天前
破局 Electron 监控盲区:基于 WASM 与 IPC 桥接的零侵入可观测 SDK 设计
electron
TrisighT2 天前
Electron 跑在鸿蒙 PC 上,单窗口和多窗口内存差 800MB?我抓了 5 组数据
性能优化·electron·harmonyos
程序员老刘5 天前
跨平台开发地图 | 2026年6月
flutter·ai编程·客户端
怕浪猫6 天前
Electron 开发实战(十六):总结与展望|生态现状、框架对比、行业趋势与学习指南
前端·javascript·electron
古德new7 天前
鸿蒙PC使用electron迁移:Joplin Electron 桌面适配全记录
华为·electron·harmonyos
三声三视7 天前
Electron 在鸿蒙 PC 上跑 webview,我是怎么把首屏从 4.2s 干到 1.1s 的
华为·electron·harmonyos·鸿蒙
「、皓子~8 天前
海狸IM 2.0 正式发布:六端齐发,开源 IM 迈入新阶段
flutter·electron·开源软件·ai编程·交友·im
JOJO数据科学8 天前
JupyterLab Electron 鸿蒙 PC 适配全记录:从 Python 原生崩溃到 node-static 本地工作台
python·electron·harmonyos
悟空瞎说8 天前
深度排查:Electron MAS 包播放 HDR 视频引发界面卡死问题全解析
electron