前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础进阶

  • 精选模块

    • 精选篇

      • 1 HTML模块
      • 2 CSS模块
      • 3 JS模块
      • 4 ES6模块
      • 5 浏览器模块
      • 6 React模块
      • 7 Vue模块
      • 8 Node模块
      • 9 前端工程相关
      • 10 移动多端开发
      • 11 小程序模块
      • 12 Uniapp模块
      • 13 前端安全模块
      • 14 性能优化相关
      • 15 HTTP模块
      • 16 常用设计模式
      • 17 框架通识
      • 18 排序算法
      • 19 计算机通识
      • 20 React Native模块
      • 21 桌面端模块
      • 22 Flutter模块
      • 23 Android模块
      • 24 iOS模块
    • 进阶篇

# 桌面端面试题精选 Electron 与 Tauri

本章以现代 Electron 与 Tauri 2.x 官方 API 为基线。重点不是背模块名,而是能说清运行时架构、权限收敛、故障恢复、性能预算与发布信任链。

# 阅读建议

  • 初级岗位先完成第 1~4 组,能独立写出安全的 preload 与 IPC。
  • 中高级岗位重点练第 5~20 组,回答时给出指标、失败路径和平台差异。
  • 带交互演示的题先切换正常/边界路径,再展开详细解析复述机制。

# 1 基础架构与选型

# Electron 到底是什么?它是怎么让一个网页变成桌面应用的?

30 秒速记

  • Electron = Chromium + Node.js + 一层原生桌面 API,三样东西一起打进安装包,是个运行时,不是「网页套壳打包工具」
  • 主进程跑 Node,管应用生命周期、窗口、菜单、托盘;每个窗口的页面跑在独立的渲染进程里
  • 页面要碰系统能力,走 preload + contextBridge 暴露的窄接口,再用 IPC 交给主进程做
  • 现在默认 nodeIntegration: false、contextIsolation: true、sandbox: true,页面里默认拿不到 require
  • 能复用的是界面和业务代码;签名、安装、自动更新、菜单这些平台行为还得分平台处理

Electron 本质上是把 Chromium 和 Node.js 塞进同一个应用里,再补一层原生桌面 API,你的网页跑在它自带的浏览器内核里。 启动时先起主进程,它是个 Node 环境,负责创建窗口、处理菜单和应用生命周期;每个窗口会拉起一个渲染进程去加载页面,跟 Chrome 开一个标签页差不多。页面想读文件、弹系统对话框,不能直接调 Node,而是通过 preload 暴露的几个方法发 IPC 给主进程去做。所以它不是把网页打成 exe,而是给网页配了一整套运行时,这也是包体大的原因。

# 三块拼起来的运行时

很多人第一次接触会以为 Electron 和「把 H5 打成 App」的套壳工具一样,其实差别很大。套壳工具一般借用系统自带的 WebView,而 Electron 是自己带了一份完整的 Chromium,再把 Node.js 编译进同一个进程里,两者共用一个 V8。所以不管用户的系统是 Windows 10 还是 macOS 14,你的页面看到的都是同一个版本的内核,前端兼容问题基本没有了,代价是每个应用都背着一个浏览器。

Electron 自己加的那一层是桌面 API:BrowserWindow、Menu、Tray、dialog、Notification、globalShortcut、autoUpdater 这些,大部分只能在主进程用。

# 一个最小应用长什么样

// main.js —— 主进程入口,package.json 里 "main": "main.js"
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
const path = require('node:path')

function createWindow() {
  const win = new BrowserWindow({
    width: 1000,
    height: 700,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      // 下面三项现在都是默认值,写出来是为了让人一眼看清安全边界
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    },
  })
  win.loadFile('index.html')
}

// 页面请求打开文件:只在主进程里碰系统能力
ipcMain.handle('dialog:openFile', async () => {
  const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openFile'] })
  return canceled ? null : filePaths[0]
})

app.whenReady().then(() => {
  createWindow()
  // macOS:点 Dock 图标且没有窗口时重新建一个
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Windows / Linux 关掉最后一个窗口就退出,macOS 习惯保留在 Dock
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
@前端进阶之旅: 代码已经复制到剪贴板
// preload.js —— 在页面脚本之前执行,跑在隔离的上下文里
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('desktop', {
  openFile: () => ipcRenderer.invoke('dialog:openFile'),
})
@前端进阶之旅: 代码已经复制到剪贴板
<!-- index.html -->
<button id="btn">打开文件</button>
<script>
  document.getElementById('btn').onclick = async () => {
    const file = await window.desktop.openFile()
    console.log('选中了', file)
  }
</script>
@前端进阶之旅: 代码已经复制到剪贴板

关键点在于页面里只有 window.desktop.openFile 这一个方法,拿不到 ipcRenderer 本身,更拿不到 fs。app.whenReady() 之前不能建窗口,window-all-closed 里按平台区分退出行为,这两处是新手最常漏的。

# 版本上要知道的几个变化

Electron 5 起 nodeIntegration 默认关,Electron 12 起 contextIsolation 默认开,Electron 20 起渲染进程默认进沙箱。网上很多老教程还在写 nodeIntegration: true 然后页面里直接 require('fs'),在新版本上要么跑不起来,要么就是在开安全口子。

面试官追问

追问 1页面里写 require('fs') 报 require is not defined,是 Electron 装坏了吗?
参考回答

没坏,是新版本默认关了 nodeIntegration、开了沙箱。正确做法是在 preload 里用 contextBridge 暴露需要的方法,别为了省事把 nodeIntegration 打开。

追问 2既然 Node 和 Chromium 在一起,渲染进程里能直接用 Node 吗?
参考回答

技术上能,开 nodeIntegration 就行,但页面一旦有 XSS 或者加载了第三方内容,攻击者就能直接执行系统命令。我会直接拦,系统能力一律走主进程。

追问 3为什么 macOS 上关掉所有窗口应用不退出?
参考回答

这是 macOS 的惯例,应用留在 Dock 里,点图标再开窗口。代码里靠 window-all-closed 判断 process.platform !== 'darwin' 才 quit,再配合 activate 事件重建窗口。

追问 4Electron 和 Cordova 这种套壳方案最大的区别是什么?
参考回答

Cordova 用系统 WebView,内核版本跟着系统走;Electron 自带固定版本的 Chromium,并且有完整的 Node 主进程。前者包小但兼容要自己扛,后者包大但环境完全可控。

追问 5主进程能不能直接操作页面的 DOM?
参考回答

不能,DOM 在渲染进程里。主进程只能通过 webContents.send 发消息、或者 executeJavaScript 注入脚本,后者尽量少用,等于绕开了 preload 定好的接口。

# 做桌面端,Electron、Tauri、NW.js 和原生你怎么选?

30 秒速记

  • 先问清楚:团队是不是前端为主、包体有没有硬指标、要多深的系统集成、要不要跨三端一致
  • Electron:自带 Chromium,渲染一致、生态最全(VS Code、Slack、飞书桌面端都是),代价是包大、内存高
  • Tauri:系统 WebView + Rust 后端,包体几 MB,但三端内核不一样,兼容问题回来了
  • NW.js:Node 和 DOM 在同一个上下文,上手快但安全隔离弱,社区比 Electron 小很多
  • 原生(Swift / C# / Qt):性能和系统集成最好,三端要写三份或学 C++,前端团队接不住

我会先看团队和硬约束,而不是先比谁包小。 前端团队做复杂业务界面、要求三端渲染一致,选 Electron 最稳,生态和踩坑资料最多。包体或内存有硬指标,界面也不算复杂,可以考虑 Tauri,但要接受 Windows 走 WebView2、macOS 走

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础进阶

  • 精选模块

    • 精选篇

      • 1 HTML模块
      • 2 CSS模块
      • 3 JS模块
      • 4 ES6模块
      • 5 浏览器模块
      • 6 React模块
      • 7 Vue模块
      • 8 Node模块
      • 9 前端工程相关
      • 10 移动多端开发
      • 11 小程序模块
      • 12 Uniapp模块
      • 13 前端安全模块
      • 14 性能优化相关
      • 15 HTTP模块
      • 16 常用设计模式
      • 17 框架通识
      • 18 排序算法
      • 19 计算机通识
      • 20 React Native模块
      • 21 桌面端模块
        • 阅读建议
        • 1 基础架构与选型
          • Electron 到底是什么?它是怎么让一个网页变成桌面应用的?
          • 做桌面端,Electron、Tauri、NW.js 和原生你怎么选?
          • Electron 为什么要用多进程架构?单进程不行吗?
          • 主进程、渲染进程和 preload 分别负责什么?
          • new BrowserWindow 之后,到页面显示出来,中间经历了什么?
          • Electron 里跑的页面和普通浏览器里跑的有哪些不一样?
          • Electron 的版本为什么和 Chromium、Node.js 绑得这么死?
          • Electron 应用为什么比 Web 应用占这么多磁盘和内存?能怎么降?
          • Electron 的事件循环是怎么同时处理 Node 的 I/O 和桌面窗口消息的?
          • 什么情况下你会劝团队别用 Electron?
        • 2 进程、线程与生命周期
        • 3 IPC 与数据流
        • 4 安全模型
        • 5 窗口、WebContents 与系统集成
        • 6 性能与资源治理
        • 7 打包、签名与自动更新
        • 8 数据、网络与协议
        • 9 测试、调试与可观测性
        • 10 架构与工程实战
        • 11 GPU、图形与多媒体
        • 12 权限、通知与操作系统能力
        • 13 跨平台兼容与可访问性
        • 14 生产故障与安全攻防
        • 15 高级架构与团队治理
        • 16 Tauri 与 Electron 架构对比
        • 17 Tauri 基础架构与 Rust Command
        • 18 Tauri IPC、事件与共享状态
        • 19 Tauri 安全、Capabilities 与插件
        • 20 Tauri 构建、更新、测试与生产实践
        • 参考资料
      • 22 Flutter模块
      • 23 Android模块
      • 24 iOS模块
    • 进阶篇

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

21-desktop

# 桌面端面试题精选 Electron 与 Tauri

本章以现代 Electron 与 Tauri 2.x 官方 API 为基线。重点不是背模块名,而是能说清运行时架构、权限收敛、故障恢复、性能预算与发布信任链。

# 阅读建议

  • 初级岗位先完成第 1~4 组,能独立写出安全的 preload 与 IPC。
  • 中高级岗位重点练第 5~20 组,回答时给出指标、失败路径和平台差异。
  • 带交互演示的题先切换正常/边界路径,再展开详细解析复述机制。

# 1 基础架构与选型

# Electron 到底是什么?它是怎么让一个网页变成桌面应用的?

30 秒速记

  • Electron = Chromium + Node.js + 一层原生桌面 API,三样东西一起打进安装包,是个运行时,不是「网页套壳打包工具」
  • 主进程跑 Node,管应用生命周期、窗口、菜单、托盘;每个窗口的页面跑在独立的渲染进程里
  • 页面要碰系统能力,走 preload + contextBridge 暴露的窄接口,再用 IPC 交给主进程做
  • 现在默认 nodeIntegration: false、contextIsolation: true、sandbox: true,页面里默认拿不到 require
  • 能复用的是界面和业务代码;签名、安装、自动更新、菜单这些平台行为还得分平台处理

Electron 本质上是把 Chromium 和 Node.js 塞进同一个应用里,再补一层原生桌面 API,你的网页跑在它自带的浏览器内核里。 启动时先起主进程,它是个 Node 环境,负责创建窗口、处理菜单和应用生命周期;每个窗口会拉起一个渲染进程去加载页面,跟 Chrome 开一个标签页差不多。页面想读文件、弹系统对话框,不能直接调 Node,而是通过 preload 暴露的几个方法发 IPC 给主进程去做。所以它不是把网页打成 exe,而是给网页配了一整套运行时,这也是包体大的原因。

# 三块拼起来的运行时

很多人第一次接触会以为 Electron 和「把 H5 打成 App」的套壳工具一样,其实差别很大。套壳工具一般借用系统自带的 WebView,而 Electron 是自己带了一份完整的 Chromium,再把 Node.js 编译进同一个进程里,两者共用一个 V8。所以不管用户的系统是 Windows 10 还是 macOS 14,你的页面看到的都是同一个版本的内核,前端兼容问题基本没有了,代价是每个应用都背着一个浏览器。

Electron 自己加的那一层是桌面 API:BrowserWindow、Menu、Tray、dialog、Notification、globalShortcut、autoUpdater 这些,大部分只能在主进程用。

# 一个最小应用长什么样

// main.js —— 主进程入口,package.json 里 "main": "main.js"
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
const path = require('node:path')

function createWindow() {
  const win = new BrowserWindow({
    width: 1000,
    height: 700,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      // 下面三项现在都是默认值,写出来是为了让人一眼看清安全边界
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    },
  })
  win.loadFile('index.html')
}

// 页面请求打开文件:只在主进程里碰系统能力
ipcMain.handle('dialog:openFile', async () => {
  const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openFile'] })
  return canceled ? null : filePaths[0]
})

app.whenReady().then(() => {
  createWindow()
  // macOS:点 Dock 图标且没有窗口时重新建一个
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Windows / Linux 关掉最后一个窗口就退出,macOS 习惯保留在 Dock
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
@前端进阶之旅: 代码已经复制到剪贴板
// preload.js —— 在页面脚本之前执行,跑在隔离的上下文里
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('desktop', {
  openFile: () => ipcRenderer.invoke('dialog:openFile'),
})
@前端进阶之旅: 代码已经复制到剪贴板
<!-- index.html -->
<button id="btn">打开文件</button>
<script>
  document.getElementById('btn').onclick = async () => {
    const file = await window.desktop.openFile()
    console.log('选中了', file)
  }
</script>
@前端进阶之旅: 代码已经复制到剪贴板

关键点在于页面里只有 window.desktop.openFile 这一个方法,拿不到 ipcRenderer 本身,更拿不到 fs。app.whenReady() 之前不能建窗口,window-all-closed 里按平台区分退出行为,这两处是新手最常漏的。

# 版本上要知道的几个变化

Electron 5 起 nodeIntegration 默认关,Electron 12 起 contextIsolation 默认开,Electron 20 起渲染进程默认进沙箱。网上很多老教程还在写 nodeIntegration: true 然后页面里直接 require('fs'),在新版本上要么跑不起来,要么就是在开安全口子。

面试官追问

追问 1页面里写 require('fs') 报 require is not defined,是 Electron 装坏了吗?
参考回答

没坏,是新版本默认关了 nodeIntegration、开了沙箱。正确做法是在 preload 里用 contextBridge 暴露需要的方法,别为了省事把 nodeIntegration 打开。

追问 2既然 Node 和 Chromium 在一起,渲染进程里能直接用 Node 吗?
参考回答

技术上能,开 nodeIntegration 就行,但页面一旦有 XSS 或者加载了第三方内容,攻击者就能直接执行系统命令。我会直接拦,系统能力一律走主进程。

追问 3为什么 macOS 上关掉所有窗口应用不退出?
参考回答

这是 macOS 的惯例,应用留在 Dock 里,点图标再开窗口。代码里靠 window-all-closed 判断 process.platform !== 'darwin' 才 quit,再配合 activate 事件重建窗口。

追问 4Electron 和 Cordova 这种套壳方案最大的区别是什么?
参考回答

Cordova 用系统 WebView,内核版本跟着系统走;Electron 自带固定版本的 Chromium,并且有完整的 Node 主进程。前者包小但兼容要自己扛,后者包大但环境完全可控。

追问 5主进程能不能直接操作页面的 DOM?
参考回答

不能,DOM 在渲染进程里。主进程只能通过 webContents.send 发消息、或者 executeJavaScript 注入脚本,后者尽量少用,等于绕开了 preload 定好的接口。

# 做桌面端,Electron、Tauri、NW.js 和原生你怎么选?

30 秒速记

  • 先问清楚:团队是不是前端为主、包体有没有硬指标、要多深的系统集成、要不要跨三端一致
  • Electron:自带 Chromium,渲染一致、生态最全(VS Code、Slack、飞书桌面端都是),代价是包大、内存高
  • Tauri:系统 WebView + Rust 后端,包体几 MB,但三端内核不一样,兼容问题回来了
  • NW.js:Node 和 DOM 在同一个上下文,上手快但安全隔离弱,社区比 Electron 小很多
  • 原生(Swift / C# / Qt):性能和系统集成最好,三端要写三份或学 C++,前端团队接不住

我会先看团队和硬约束,而不是先比谁包小。 前端团队做复杂业务界面、要求三端渲染一致,选 Electron 最稳,生态和踩坑资料最多。包体或内存有硬指标,界面也不算复杂,可以考虑 Tauri,但要接受 Windows 走 WebView2、macOS 走 WKWebView、Linux 走 WebKitGTK,同一段 CSS 在三个内核上可能表现不同,后端还得有人写 Rust。重图形、强实时或者深度系统集成,比如输入法、驱动级工具,就老老实实上原生。NW.js 现在新项目很少选了。

# 对比表

维度 Electron Tauri 2 NW.js 原生
渲染内核 自带 Chromium,三端一致 系统 WebView,三端不同 自带 Chromium 平台控件
后端语言 Node.js Rust Node.js Swift / C# / C++ 等
安装包 压缩后常见 80MB 以上 几 MB 到十几 MB 和 Electron 同一量级 最小
内存 多进程,偏高 比 Electron 低,但 WebView 本身也要内存 偏高 最低
安全模型 进程隔离 + contextIsolation + 沙箱 默认拒绝,按 capabilities 显式授权命令 Node 和页面同上下文,隔离弱 看实现
生态 最大,electron-builder、electron-updater 都很成熟 增长快,插件体系在完善 小 各平台各自的生态
适合 复杂业务界面、前端团队、要求一致 工具类、包体敏感、愿意写 Rust 老项目维护 性能和系统集成要求极高

# 几个容易被忽略的判断点

← 20 React Native模块22 Flutter模块 →

fe