init vue
This commit is contained in:
@@ -0,0 +1,332 @@
|
|||||||
|
# Electron + Vue3 + TypeScript 项目
|
||||||
|
|
||||||
|
基于 [electron-vite](https://electron-vite.org/) 构建的现代化 Electron 应用模板。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
| 领域 | 技术 |
|
||||||
|
|------|------|
|
||||||
|
| 构建工具 | [electron-vite](https://electron-vite.org/) |
|
||||||
|
| 前端框架 | Vue 3 (Composition API) |
|
||||||
|
| 语言 | TypeScript |
|
||||||
|
| UI | 原生 HTML/CSS + Vue 组件 |
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
├── electron.vite.config.ts # Vite 配置(electron-vite 专用)
|
||||||
|
├── tsconfig*.json # TypeScript 配置
|
||||||
|
├── src/
|
||||||
|
│ ├── main/ # 主进程(Node.js 环境)
|
||||||
|
│ │ └── index.ts
|
||||||
|
│ ├── preload/ # 预加载脚本(桥接层)
|
||||||
|
│ │ ├── index.ts
|
||||||
|
│ │ └── index.d.ts # 类型声明
|
||||||
|
│ └── renderer/ # 渲染进程(浏览器环境)
|
||||||
|
│ ├── index.html
|
||||||
|
│ └── src/
|
||||||
|
│ ├── main.ts # Vue 入口
|
||||||
|
│ ├── App.vue
|
||||||
|
│ └── components/
|
||||||
|
│ └── Counter.vue
|
||||||
|
├── out/ # 构建输出目录
|
||||||
|
└── package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 核心概念
|
||||||
|
|
||||||
|
### 1. 三进程架构
|
||||||
|
|
||||||
|
Electron 有三个独立的进程:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ Main Process │
|
||||||
|
│ (Node.js) - 创建窗口、管理应用生命周期 │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌───────────────────────────────────────────┐ │
|
||||||
|
│ │ Preload Script │ │
|
||||||
|
│ │ (上下文桥接,安全暴露 API 到渲染进程) │ │
|
||||||
|
│ └───────────────────────────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌───────────────────────────────────────────┐ │
|
||||||
|
│ │ Renderer Process │ │
|
||||||
|
│ │ (Chromium) - Vue 应用运行,DOM 操作 │ │
|
||||||
|
│ └───────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**主进程 (main)**:运行 Node.js,负责窗口管理、应用生命周期、系统 API 调用
|
||||||
|
|
||||||
|
**预加载脚本 (preload)**:运行在渲染进程中,但能访问 Node.js API,通过 `contextBridge` 安全暴露有限 API
|
||||||
|
|
||||||
|
**渲染进程 (renderer)**:运行 Web 内容,Vue/React 应用在此执行,只能通过 IPC 与主进程通信
|
||||||
|
|
||||||
|
### 2. 上下文隔离 (Context Isolation)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// main.js - 窗口配置
|
||||||
|
webPreferences: {
|
||||||
|
contextIsolation: true, // 启用上下文隔离
|
||||||
|
nodeIntegration: false, // 禁用 Node.js 访问
|
||||||
|
preload: 'preload.js' // 加载预加载脚本
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `contextIsolation: true` 防止渲染进程直接访问 Node.js,防止 XSS 攻击
|
||||||
|
- 渲染进程只能通过 `window.electron` 或 `window.api` 访问预暴露的 API
|
||||||
|
|
||||||
|
### 3. IPC 通信模式
|
||||||
|
|
||||||
|
```
|
||||||
|
Renderer Main
|
||||||
|
│ │
|
||||||
|
│ ipcRenderer.invoke('xxx') │
|
||||||
|
│ ─────────────────────────────►│
|
||||||
|
│ │ ipcMain.handle('xxx', ...)
|
||||||
|
│ Promise<Result> │
|
||||||
|
│ ◄─────────────────────────────│
|
||||||
|
▼ ▼
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// preload - 暴露 IPC 通道
|
||||||
|
contextBridge.exposeInMainWorld('api', {
|
||||||
|
getData: () => ipcRenderer.invoke('get-data')
|
||||||
|
})
|
||||||
|
|
||||||
|
// renderer - 调用
|
||||||
|
const data = await window.api.getData()
|
||||||
|
|
||||||
|
// main - 处理
|
||||||
|
ipcMain.handle('get-data', () => {
|
||||||
|
return { message: 'Hello from main!' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. electron-vite 构建流程
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ electron-vite dev │
|
||||||
|
├─────────────────────────────────────────────────────────┤
|
||||||
|
│ main │ Vite (SSR) → out/main/index.js │
|
||||||
|
│ preload │ Vite (ESM) → out/preload/index.mjs │
|
||||||
|
│ renderer│ Vite + Vue → http://localhost:5173 │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ electron-vite build │
|
||||||
|
├─────────────────────────────────────────────────────────┤
|
||||||
|
│ main │ Vite (SSR) → out/main/index.js │
|
||||||
|
│ preload │ Vite (ESM) → out/preload/index.mjs │
|
||||||
|
│ renderer│ Vite + Vue → out/renderer/ │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
electron-vite 自动处理:
|
||||||
|
- 主进程和预加载脚本的 CommonJS/ESM 兼容
|
||||||
|
- 渲染进程的热模块替换 (HMR)
|
||||||
|
- 路径别名、依赖打包等
|
||||||
|
|
||||||
|
### 5. Vue 组件生命周期
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onUnmounted } from 'vue'
|
||||||
|
|
||||||
|
const count = ref(0)
|
||||||
|
let timer: ReturnType<typeof setTimeout> | null = null
|
||||||
|
|
||||||
|
function updateCounter(): void {
|
||||||
|
count.value++
|
||||||
|
timer = setTimeout(updateCounter, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateCounter()
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timer) clearTimeout(timer)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
- `onMounted` - 组件挂载时启动定时器
|
||||||
|
- `onUnmounted` - 组件卸载时清理定时器,防止内存泄漏
|
||||||
|
|
||||||
|
## 命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 开发模式(热重载)
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# 生产构建
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 运行已构建的应用
|
||||||
|
npm start
|
||||||
|
|
||||||
|
# 打包为可执行文件
|
||||||
|
npm run package
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发建议
|
||||||
|
|
||||||
|
1. **IPC 优先**:渲染进程不直接操作系统 API,通过 IPC 委托给主进程
|
||||||
|
2. **类型安全**:preload 的 API 声明在 `.d.ts` 文件中,renderer 可获得智能提示
|
||||||
|
3. **组件化**:UI 逻辑封装在 Vue 组件中,主进程只负责业务无关的系统操作
|
||||||
|
4. **清理资源**:组件卸载时务必清理定时器、事件监听器等
|
||||||
|
|
||||||
|
## TypeScript 配置
|
||||||
|
|
||||||
|
项目有 3 个 TypeScript 配置文件:
|
||||||
|
|
||||||
|
### tsconfig.json(根配置/入口)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.node.json" },
|
||||||
|
{ "path": "./tsconfig.web.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**作用**:项目总入口,本身不编译代码,通过 `references` 引用其他两个配置。
|
||||||
|
|
||||||
|
### tsconfig.node.json(Node.js 环境)
|
||||||
|
**对应**:`src/main/` + `src/preload/` + `electron.vite.config.ts`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lib": ["ES2022"],
|
||||||
|
"include": ["src/main/**/*", "src/preload/**/*", "electron.vite/**/*"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**作用**:为主进程和预加载脚本提供类型检查,这两个运行在 Node.js 环境,需要 Node.js 内置类型(如 `process`、`path`、`fs`)。
|
||||||
|
|
||||||
|
### tsconfig.web.json(浏览器环境)
|
||||||
|
**对应**:`src/renderer/`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
|
"jsx": "preserve",
|
||||||
|
"jsxImportSource": "vue",
|
||||||
|
"include": ["src/renderer/**/*"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**作用**:为渲染进程(Vue 应用)提供类型检查,需要 DOM 类型(如 `window`、`document`、`HTMLElement`)和 Vue JSX 支持。
|
||||||
|
|
||||||
|
### 为什么分开?
|
||||||
|
```
|
||||||
|
┌─────────────────┐
|
||||||
|
│ tsconfig.json │ ← 根配置,定义整体规则
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
references
|
||||||
|
│
|
||||||
|
┌────┴────┐
|
||||||
|
▼ ▼
|
||||||
|
┌───────┐ ┌───────┐
|
||||||
|
│ node │ │ web │ ← 分别针对不同运行环境
|
||||||
|
│ .json │ │ .json │
|
||||||
|
└───┬───┘ └───┬───┘
|
||||||
|
│ │
|
||||||
|
Node.js 浏览器
|
||||||
|
API 类型 DOM 类型
|
||||||
|
```
|
||||||
|
|
||||||
|
不同运行环境有不同的全局 API,分开配置可以:
|
||||||
|
- 避免类型冲突(Node.js 的 `global` vs 浏览器的 `window`)
|
||||||
|
- 按需引入类型库,减小检查范围
|
||||||
|
- IDE 根据当前文件路径自动选择对应配置
|
||||||
|
|
||||||
|
## 全部文件清单
|
||||||
|
|
||||||
|
| 文件 | 作用 |
|
||||||
|
|------|------|
|
||||||
|
| `package.json` | 项目配置:依赖、脚本、electron-builder 设置 |
|
||||||
|
| **`electron.vite.config.ts`** | **构建入口**:定义三个进程的入口路径、插件、别名 |
|
||||||
|
| `tsconfig.json` | TS 总入口,引用其他两个配置 |
|
||||||
|
| `tsconfig.node.json` | Node.js 环境配置(主进程、预加载) |
|
||||||
|
| `tsconfig.web.json` | 浏览器环境配置(渲染进程、Vue) |
|
||||||
|
| `src/main/index.ts` | Electron 主进程:创建窗口、管理应用生命周期、处理 IPC |
|
||||||
|
| `src/preload/index.ts` | 预加载脚本:通过 contextBridge 暴露安全 API |
|
||||||
|
| `src/preload/index.d.ts` | 预加载 API 的 TypeScript 类型声明 |
|
||||||
|
| `src/renderer/index.html` | 渲染进程 HTML 入口 |
|
||||||
|
| `src/renderer/src/main.ts` | Vue 应用入口 |
|
||||||
|
| `src/renderer/src/App.vue` | Vue 根组件 |
|
||||||
|
| `src/renderer/src/components/Counter.vue` | 计数器业务组件 |
|
||||||
|
| `out/` | 构建输出目录(`.gitignore` 忽略) |
|
||||||
|
|
||||||
|
## electron.vite.config.ts 详解
|
||||||
|
|
||||||
|
这是 electron-vite 的核心配置文件,作用类似普通 Vite 项目的 `vite.config.ts`,但需要为三个进程分别配置:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
// ── 主进程配置 ──
|
||||||
|
main: {
|
||||||
|
plugins: [externalizeDepsPlugin()], // 依赖外置,不打包进输出
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
input: { index: 'src/main/index.ts' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ── 预加载脚本配置 ──
|
||||||
|
preload: {
|
||||||
|
plugins: [externalizeDepsPlugin()],
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
input: { index: 'src/preload/index.ts' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ── 渲染进程配置 ──
|
||||||
|
renderer: {
|
||||||
|
root: 'src/renderer', // HTML 所在目录
|
||||||
|
plugins: [vue()], // Vue 插件
|
||||||
|
resolve: {
|
||||||
|
alias: { '@': 'src/renderer/src' } // 路径别名
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
input: 'src/renderer/index.html' // HTML 入口
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 关键点
|
||||||
|
|
||||||
|
| 配置项 | 作用 |
|
||||||
|
|--------|------|
|
||||||
|
| `externalizeDepsPlugin()` | 将 `node_modules` 中的依赖转为 `require()` 引用,减小包体积 |
|
||||||
|
| `root: 'src/renderer'` | 告诉 Vite 渲染进程的 HTML 在哪个目录 |
|
||||||
|
| `plugins: [vue()]` | 在渲染进程启用 Vue 插件,处理 `.vue` 文件 |
|
||||||
|
| `resolve.alias` | 设置 `@` 指向 `src/renderer/src`,简化导入路径 |
|
||||||
|
| `build.rollupOptions.input` | 指定每个进程的入口文件 |
|
||||||
|
|
||||||
|
### 构建后输出
|
||||||
|
|
||||||
|
```
|
||||||
|
electron-vite build
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────────────────────────────┐
|
||||||
|
│ out/main/index.js (主进程) │
|
||||||
|
│ out/preload/index.mjs (预加载) │
|
||||||
|
│ out/renderer/index.html (渲染进程) │
|
||||||
|
│ out/renderer/assets/* (JS/CSS) │
|
||||||
|
└──────────────────────────────────────────┘
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user