electron构建跨平台混合应用

1,644 阅读5分钟

一、前言

  • 因为公司有部分项目应用在window系统上,需要构建不同平台的应用程序,最后决定使用electron。
  • 本篇主要给没使用过electron的,和需要简单构建应用程序的同学参考。

说明:为了避免因版本问题出现的API,或者其他错误,文中使用的版本,也是最新版本是 v9.1.1 官网

1. Electron 什么?

electron是一个结合前端的HTML,CSS,JavaScript等Web技术构建多平台的混合应用开发的github开源库。于2014年开源使用。

2.Electron 构建原理?

Electron 结合了 Chromium,Nodejs,和调用本地操作系统API,构建 Mac,window,和Linux应用程序。

Electron的更新频率大概为2-4周。也会经常修复发现的bug,有新的API, 版本升级都会进行更新发布。

二、必备环境搭建

1. 检查node,npm环境

➜ ~ node -v 
v10.16.0 
➜ ~ npm -v 
6.9.0 

2. 安装electron

npm install electron -g

3. 创建一个项目 / 或者克隆一个仓库

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

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

# 安装依赖并运行
npm install && npm start
  • 手动创建项目
  • 新建一个项目目录,新建main.js,在命令行中打开当前目录
  • 你也可以新建一个index.html文件,也可以不用新建,直接在后面引入你想要的页面
# 生产配置文件 package.json
npm init
  • 打开main.js 配置写入如下代码
const { app, BrowserWindow } = require("electron");  // nodejs 语法,引入electron
const path = require("path");

function createWindow() {  // 创建窗口函数
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 500,
    // frame: false, // 无边框模式,默认为true
  });

  mainWindow.loadFile("./Calculator/index.html");    // 打开本地文件
  // mainWindow.loadURL("https://www.baidu.com");  //打开地址

  // 开发者模式,打开调试
  // mainWindow.webContents.openDevTools()
}

// 准本加载函数
app.whenReady().then(() => {
  createWindow();

  app.on("activate", function() { // 这里主要是当窗口被激活时,如果没有窗口就创建一个窗口
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

// 窗口关闭时
app.on("window-all-closed", function() {
  if (process.platform !== "darwin") app.quit();
});

  • 运行

electron . <---这里是有一个 ‘ . ’的

4. 你也可以使用electron-forge创建一个electron项目

npm install electron-forge -g

electron-forge init my-electron

cd my-electron

npm start

三、进程与线程

1.介绍

进程:正在执行的计算机程序,cpu总是运行一个进程,其他进程处于等待,一个进程中有多个线程工作。

线程:线程是操作系统运算调度的最小单位,js的运行环境一般是单线程的

我们知道JS是单线程的,而electron是底层是基于Chromium开发的,是多线程的,所以electron也是多线程的,主要分为主进程和渲染进程。

主进程:Electron 运行 package.jsonmain 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。一个Electron应用总是有且只有一个主进程。

渲染进程: 由于 Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到。 每个 Electron 中的 web 页面运行在它的叫渲染进程的进程中。

普通的浏览器中运行的web页面是无法访问操作系统的原生资源的,然而Electron可以支持用户在Nodejs的API支持下对操作系统进行一些底层的交互。

2. 主进程和渲染进程之间的关系

  • 主进程使用 BrowserWindow 实例创建页面。 每个 BrowserWindow 实例都在自己的渲染进程里运行页面。 当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。
  • 主进程下每个web页面,和他们关联的渲染进程都是相互独立的。

3.主进程和渲染进程直接的通行

Electron 为主进程( main process)和渲染器进程(renderer processes)通信提供了多种实现方式,常见的通信方式有下面这些

  • ipcRenderer 用于渲染进程
    • ipcRenderer.on(channel, listener) --> channel 为事件频道,listener为触发回调函数, 用于相应webContent.send()
    • ipcRenderer.send(channel, data) --> 概念同上面一样,用于向ipcMain 发送一步信息
  • ipcMain 用于主进程,响应渲染进程中发送的信息
    • ipcMain.on(channel, listener) -->响应从 ipcRender 中相同 channel
  • event.sender: 主进程监听到渲染进程发送的信息,在响应事件回调函数中使用event.send()方法可以向渲染进程发送消息
  • webContentipcMain 本身是无法直接发送事件的,只能通过响应事件回调函数的event来发送,如果我们想让主进程发送消息就可以使用 webContent, webContentBrowserWindow 实例中的方法。
    • webContent.send(channel, data) --> 主进程向渲染进程发送消息

4. 不同渲染进程之间共享数据

  • 可以简单使用HTML5中的API来实现,例如 localStorage 和 sessionStorage
  • 在 electron 中,我们可以在主进程中讲一个对象存储为全局的变量,在渲染进程中通过模块 remote 进行操作
  • 示例
// 在主进程中.
global.sharedObject = {
  someProperty: 'default value'
}
// 页面 1
require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'

// 页面 2.
console.log(require('electron').remote.getGlobal('sharedObject').someProperty)

四、打包

这里介绍两种打包方式

1. 正式打包,打包成一个应用程序

electron-packager <应用目录> < 应用名称> --platform=<打包平台> --out=<输出目录> ---arch=<架构> --app-version=<应用版本> --icon=<应用图标> --overwrite (是否覆盖)

  • win打包:平台 --paltform=win32 | 架构 --arch=x64 | 图标 --icon=**.ico
  • mac打包:平台 --paltform=drawin | 架构 --arch=x64 | 图标 --icon=**.ico

示例:

electron-packager ./ app --platform=win32 --out=./dist --arch=x64 --app-version=1.0.0 --icon=./image/icon.ico --overwite

2. 打包为安装包

下载:npm install electron-builder -g

  • 配置启动脚本: 打开package.json, 可以不用全部配置

{
...
"script": {
    ...
    "builderwin": "electron-builder -win",  // 启动脚本    "buildermac": "electron-builder -mac"    ...
},
 build: {
    "appId": "com.itcast.app",  // 包名称
    "directories": {
        "app": "/", // 应用目录
        "output": "dist" // 输出目录
    },
    "productName": "计算器", // 项目名称 xxx.exe
    "dmg": {  // 这里主要用于mac下的配置
        "icon": "./xxx/mac.icns",  // 图标路径
        "window": {  // 窗口设置
        "x": "200",
        "y": "150""width": 500,
        "height": 400
        }
    },
    "mac": { "icon": "./images/mac.icns" },
    "win": { 
        "icon": "./images/icon.ico", // 图标路径
        "extraResource": {   // 拷贝dll等静态文件到指定位置
            "from": "./app-update.yml",
            "to": "./b.txt"
        },
    },
    "asar": false, // asar打包
    "extraResource": {   // 拷贝dll等静态文件到指定位置
        "from": "./app-update.yml",
        "to": "./b.txt"
    },
    "nsis": {
    "oneClick": false, // 一件安装
    "guid": "xxxx", //注册表名字,不推荐使用
    "perMachine": true, // 是否开启安装史权限限制
    "allowElevation": true, // 允许请求提升。如果为false,用户必须使用提升的权限重新启动安装程序        "allowToChangeInstallationDirectory": true, // 允许修改安装目录        "installerIcon": "./build/icons/aaa.ico", // 安装图标        "uninstallerIcon": "./build/icons/bbb.ico", // 卸载图标        "installerHeaderIcon": "./build/icons/aaa.ico", // 安装时头部图标        "createDesktopShortcut": true, // 创建桌面图标        "createStartMenuShortcut": true, // 创建开始菜单图标        "shortcutName": "xxxx" // 图标名称
    }
 }
...
}