前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版

Electron 构建跨平台桌面应用实战笔记 mac/windows/linux

首页2019-01-06 17:40:43Front-End
ElectronNode桌面应用

把一个已经跑在浏览器里的后台系统做成能装在电脑上的客户端,同时支持 mac 和 windows,还得有托盘图标、右键菜单、断网提醒这些「像个真软件」的细节,这活儿交给只会写前端的人能不能干?我为了搞清楚这个问题,从头到尾用 Electron 做了一个舆情监控的桌面端出来,源码在文末。结论是能干,这些原生能力 Electron 基本都包好了,剩下的还是写 HTML 和 JavaScript。

这篇是我边做边记的完整笔记,从环境搭建一路到多平台打包,中间卡住过的地方也一并留着。读完你能拿到一条从 electron . 跑起第一个窗口,到把应用打成 .dmg 和 .exe 的完整路径。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • Electron 是什么,它凭什么能把网页变成桌面软件
  • 四种搭项目的方式,以及主进程和渲染进程到底怎么分工
  • 自定义顶部菜单和右键菜单
  • 主进程与渲染进程、渲染进程之间的四种通信姿势
  • shell、webview、dialog 这些和系统打交道的模块
  • 系统托盘、图标闪烁、消息通知、监听网络变化
  • 全局快捷键、剪贴板与 nativeImage
  • 结合 electron-vue 做一个完整的舆情监控系统并打包上线
  • 2019 年的写法放到今天该怎么改(安全模型变了,这块单独讲)

先说一句放在最前面的提醒:这篇笔记写于 2019 年初,那会儿 Electron 还允许渲染进程直接 require('electron')、直接读文件,remote 模块也还在核心里。现在的官方安全基线已经变成 contextIsolation: true + nodeIntegration: false,能力统一由 preload 脚本通过 contextBridge 往外暴露,remote 也早就从核心移出去了。原文的写法我一个字没删,因为它能帮你理解这套模型是怎么演进过来的;但每个涉及安全边界的地方,我都另起了一小段写现在该怎么做。要直接抄进新项目的话,请照着新写法来。

# 一、前言

  • NW.js 和 Electron 都可以用前端的知识来开发桌面应用。NW.js 和 Electron 起初是同一 个作者开发。后来种种原因分为两个产品。一个命名为 NW.js(英特尔公司提供技术支持)、 另一命名为 Electron(Github 公司提供技术支持)。
  • NW.js 和 Electron 可以用 Nodejs 中几乎所有的模块。NW.js 和 Electron 不仅可以把 html 写的 web 页面打包成跨平台可以安装到电脑上面的软件,也可以通过 javascript 访问操作 系统原生的 UI 和 Api(控制窗口、添加菜单项目、托盘应用菜单、读写文件、访问剪贴板)。

github 的 atom 编辑器、微软的 vscode 编辑器,包括阿里内部的一些 软件也是用 electron 开发的

你每天在用的 VS Code 就是 Electron 写的。这一点对我当时的说服力比任何文档都强,一个前端能写出来的东西,可以是编辑器这种量级的产品,那我做个后台客户端总归没问题。

顺着上面聊,NW.js 和 Electron 的分家其实是个挺有意思的历史。它们的入口哲学不一样:NW.js 是以页面为入口,直接指一个 html 文件就能跑;Electron 是以脚本为入口,先起一个 Node 进程(主进程),再由这个进程去开窗口装页面。这个差别看着小,但它决定了后面整篇笔记的所有内容,因为「主进程和渲染进程分工」这件事就是从这儿来的。

下面这几个问题是我当时给自己列的自查清单,搞清楚了再动手。

1. Electron 是由谁开发的?

Electron 是由 Github 开发

2. Electron 是什么?

Electron 是一个用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库

3. Electron 把 HTML,CSS 和 JavaScript 组合的程序构建为跨平台桌面应用程序的原理 是什么?

原理为 Electron 通过将 Chromium 和 Node.js 合并到同一个运行时环境中,并将其打包为 Mac,Windows 和 Linux 系统下的应用来实现这一目的。

4. Electron 何时出现的,为什么会出现?

Electron 于 2013 年作为构建 Atom 的框架而被开发出来。这两个项目在 2014 春季开源。 (Atom:为 Github 上可编程的文本编辑器)

一些历史:

  • 2013 年 4 月 Atom Shell 项目启动 。
  • 2014 年 5 月 Atom Shell 被开源 。
  • 2015 年 4 月 Atom Shell 被重命名为 Electron
  • 2016 年 5 月 Electron 发布了 v1.0.0 版本

5. Electron 当前流行程度?

目前 Electron 已成为开源开发者、初创企业和老牌公司常用的开发工具。

6. Electron 当前由那些人在维护支持?

Electron 当前由 Github 上的一支团队和一群活跃的贡献者维护。有些贡献者是独立开发者,有些则在用 Electron 构建应用的大型公司里工作。

7. Electron 新版本多久发布一次?

Electron 的版本发布相当频繁。每当 Chromium、Node.js 有重要的 bug 修复,新 API 或是版本更新时 Electron 会发布新版本。

  • 一般 Chromium 发行新的稳定版后的一到两周之内,Electron 中 Chromium 的版本会对其进行更新,具体时间根据升级所需的工作量而定。 一般 Node.js 发行新的稳定版一个月后,Electron 中 Node.js 的版本会对其进行更新,具 体时间根据升级所需的工作量而定。

8. Electron 的核心理念是什么?

Electron 的核心理念是:保持 Electron 的体积小和可持续性开发。 如:为了保持 Electron 的小巧 (文件体积) 和可持续性开发 (以防依赖库和 API 的泛滥) , Electron 限制了所使用的核心项目的数量。 比如 Electron 只用了 Chromium 的渲染库而不是其全部组件。这使得升级 Chromium 更加容易,但也意味着 Electron 缺少了 Google Chrome 里的一些浏览器相关的特性。 添加到 Electron 的新功能应该主要是原生 API。 如果可以的话,一个功能应该尽可能的成 为一个 Node.js 模块。

9. Electron 当前的最新版本为多少?

Electron 当前的最新版本为 4.0.1 (当前时间为 2019 年 1 月 6 号)

这个 4.0.1 是我写这篇笔记那天的版本,现在早就翻了好几倍了,具体多少以官方 releases 页面为准。我不写死数字,因为 Electron 的发版节奏是跟着 Chromium 走的,你今天看到的数字过两周就不对了。真正需要记住的是它的支持策略:只有最近几个 major 版本会拿到安全补丁,老版本用着用着就等于把一个不再打补丁的 Chromium 装进了用户电脑。所以选版本这件事,别挑「我熟悉的那个」,挑还在支持窗口里的那个。

回到我们要解决的问题。搞明白 Electron 是「Chromium 渲染 + Node 运行时」这一个合体,后面所有 API 的位置就都好理解了:跟界面有关的走 Chromium 那一半,跟系统有关的走 Node 那一半,两半之间靠进程通信连起来。

# 二、环境搭建

搭环境这块有四条路,从「一条命令跑起来」到「一个文件一个文件手搓」都有。我建议第一次学的时候走手搓那条,因为只有自己写一遍 main.js,你才知道那个窗口是谁创建的、什么时候创建的。等你熟了,做真实项目再用脚手架。

1. 安装 electron

npm install -g electron
@前端进阶之旅: 代码已经复制到剪贴板

全局装是为了能在任意目录直接敲 electron .,方便试手。真实项目里我更推荐装成项目的 devDependencies,理由很实在:Electron 的版本号决定了你的 Chromium 和 Node 版本,全局装的话每个项目共用同一个运行时,一旦你同时维护两个不同版本的项目就会互相打架,而且报出来的错和版本八竿子打不着,很难往这个方向想。

2. 克隆一个仓库、快速启动一个项目

# 克隆示例项目的仓库
git clone https://github.com/electron/electron-quick-start

# 进入这个仓库
cd electron-quick-start

# 安装依赖并运行
npm install && npm start
@前端进阶之旅: 代码已经复制到剪贴板

electron-quick-start 是官方维护的最小样板,main.js 加 index.html 加 package.json 三个文件,看完不超过五分钟。想快速确认自己机器上的环境没问题,跑它最快。

3. 手动搭建一个 electron 项目

  1. 新建一个项目目录 例如: electrondemo01
  2. 在 electrondemo01 目录下面新建三个文件: index.html、main.js 、package.json
  3. index.html 里面用 css 进行布局(以前怎么写现在还是怎么写)
  4. 在 main.js 中写如下代码

这段代码是整个 Electron 应用的起点,它就干三件事:等 Electron 初始化完成、创建一个 800x600 的窗口把 index.html 装进去、在窗口关掉时把引用置空。package.json 里的 main 字段要指向这个文件,Electron 启动时先跑的就是它。

var electron = require('electron'); // electron 对象的引用
const app = electron.app;           // 控制应用生命周期
const BrowserWindow = electron.BrowserWindow; // BrowserWindow 类的引用

let mainWindow = null;

// 监听应用准备完成的事件
app.on('ready', function () {
    // 创建窗口
    mainWindow = new BrowserWindow({ width: 800, height: 600 });
    mainWindow.loadFile('index.html');

    mainWindow.on('closed', function () {
        mainWindow = null;
    });
});

// 监听所有窗口关闭的事件
app.on('window-all-closed', function () {
    // On OS X it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
        app.quit();
    }
});
@前端进阶之旅: 代码已经复制到剪贴板

有两个点特别容易被跳过去,但它们都是有原因的。

let mainWindow = null 为什么要放在函数外面?因为 BrowserWindow 对象一旦被 JavaScript 垃圾回收,对应的原生窗口就跟着关了。如果你写成 app.on('ready', function () { let win = new BrowserWindow(...) }),窗口有时候会莫名其妙自己消失。放到模块作用域顶层,就是为了留一个全局引用把它拴住。

fe
  • 一、前言
  • 二、环境搭建
  • 三、Electron 运行流程
    • 3.1 Electron 运行的流程
    • 3.2 Electron 主进程和渲染进程
    • 3.3 Electron 渲染进程中通过 Nodejs 读取本地文件
    • 3.4 Electron 开启调试模式
  • 四、Electron 模块介绍
    • 4.1 Electron 主进程和渲染进程中的模块
    • 4.2 Electron remote 模块
    • 4.3 通过BrowserWindow 打开新窗口
  • 五、自定义顶部菜单/右键菜单
    • 5.1 主进程中调用Menu模块-自定义软件顶部菜单
    • 5.2 渲染进程中调用Menu模块
    • 5.3 渲染进程中自定义右键菜单
  • 六、进程通信
    • 6.1 主进程与渲染进程之间的通信
      • 6.1.1 渲染进程给主进程发送异步消息
      • 6.1.2 渲染进程发送消息,主进程接收消息并反馈
      • 6.1.3 渲染进程给主进程发送同步消息
      • 6.1.4 渲染进程广播通知主进程打开窗口
    • 6.2 渲染进程与渲染进程之间的通信
      • 6.2.1 localstorage传值
      • 6.2.2 BrowserWindow和webContents方式实现
  • 七、Electron Shell 模块
    • 7.1 Shell 模块使用
    • 7.2 Electron DOM <webview> 标签
    • 7.3 shell模块<webview>结合Menu模块使用案例
  • 八、Electron dialog 弹出框
  • 九、实现一个类似EditPlus的简易记事本代码编辑器
  • 十、系统托盘、托盘右键菜单、托盘图标闪烁
  • 十一、消息通知、监听网络变 化、网络变化弹出通知框
    • 11.1 消息通知
    • 11.2 监听网络变化
  • 十二、注册全局快捷键/剪切板事件/nativeImage 模块
    • 12.1 注册全局快捷键
    • 12.2 剪切板clipboard、nativeImage 模块
  • 十三、结合electron-vue
    • 13.1 electron-vue 的使用
    • 13.2 electron-vue 中使用 sass/ElementUi
    • 13.3 electron-vue 中隐藏顶部菜单隐藏
    • 13.4 使用electron-vue开发舆情监控系统
      • 13.4.1 配置开发环境
      • 13.4.2 主进程配置
      • 13.4.3 渲染进程配置
      • 13.4.4 多平台打包
        • 13.4.4.1 打包介绍
        • 13.4.4.2 修改应用信息
        • 13.4.4.3 打包遇到的问题
  • 十四、更多参考
  • 总结
  • 参考

← Angular7 入门总结 从环境搭建到路由的完整笔记浏览器缓存原理总结 强缓存与协商缓存的判定顺序 →