基于Electron的桌面端应用开发和实践

news2024/11/23 15:43:59

引言

如果开发跨桌面端的应用开发的话,我相信,electron目前绝对是不可避免的技术方案。web应用大家都知道,通过浏览器访问的应用就是web应用,那什么是桌面端?桌面端有两个重要特点:

  1. 具备独立运行于操作系统上的能力(可以理解为桌面客户端只是PC,通常指的是windows、MacOS、linux这几个主流PC操作系统)
  2. 具有自己的GUI(用户图形界面 graphical user interface)

有人会问?web应用也有自己的GUI,但是它必须在浏览器中执行,因此不是桌面客户端。浏览器能直接运行在操作系统上,而且有自己的GUI,因此浏览器是桌面客户端。

这样大家就理解web应用和桌面端的区别了。

Electron是什么

先简单介绍一下electron。electron是由Github开发的开源框架,现在由OpenJS基金会维护的一个开源项目。它允许开发者使用 HTML、CSS 和 JavaScript 来构建跨平台的桌面应用,而且构建出来的应用,可以很好地兼容 Mac、Windows 和 Linux 这些主流的操作系统。

相对于web开发和传统的桌面端,它集合了一些自己的特点:

● 自动更新 —— 支持应用自动更新,相对于传统的桌面端更加快捷
● 原生菜单和通知 —— 可以创建原生应用菜单和上下文菜单,还有原生的交互通知
● Windows installer —— 可以快速便捷地创建安装包,兼容Mac、windows。
● 调试和分析 —— Chrominum 的内容模块可以发现性能瓶颈和缓慢的操作。你也可以在应用中使用自己喜欢的 Chrome 开发者工具。
● 应用崩溃报告 —— 可以将崩溃报告提交到远程服务器

所以目前来看,虽然是使用了web技术进行开发,但是和web开发稍许有些不同的。

为什么选择Electron

  • 首先,为了跨端,兼容多个平台,不仅仅是操作系统,还有浏览器的内核;
  • 其次,可以快速构建一个桌面应用,可用于快速试错;
  • 然后,也适用于一些效率工具应用,比如有道云笔记,vscode,截屏软件;
  • 最重要的是,省钱,因为原生开发效率低,可以降本增效;

其实,大部分选择 Electron 框架的动机也都是差不多的,无非就是省钱,尤其是在夹缝中生存的微小型企业。

🈶️很多优秀的应用都是使用electron开发的,比如,vscode,atom,github桌面版,语雀桌面版,postman桌面版,支付宝小程序开发工具等等。

Electron架构

Electron的架构可以理解为由三部分构成, 即chromium + nodejs + 原生api

Electron的架构
其中,

Chromium提供强大的UI能力,允许我们在不考虑浏览器兼容性的前提下,利用完整的web生态开发页面。

NodeJS让Electron具备了底层操作能力,比如文件读写、加解密、集成C++模块,支持引用npm包等;

Native API 解决了跨平台的问题,提供了统一的原生界面,比如窗口、托盘,其次是系统能力,比如Notification,最后是应用的基础能力,比如软件更新、系统监控等;

Chromium架构

Chromium架构

这张图来源于chromium官网,比较清晰的表达了Chromium的多进程架构。

我们从几个方面,分析一下Chromium的多进程模式
● 浏览器端(Browser)
● 渲染器端(Render)
● 浏览器和渲染器间的通信方式(IPC)

图上,有Browser,有Render。Browser浏览器端直观上来说,就是打开Chrome后,浏览器的主体(顶级浏览器窗口)。它对应一个单独的进程,Browser进程。该进程一旦挂掉,整个浏览器就会崩溃。一个Render进程,可以看成一个标签页。每个标签页,都对应着自己的Render进程。即使一个标签页挂掉,其他标签页也可以正常运作。

1、Browser
Browser进程可以看成一个指挥调度中心。它负责运行UI和管理标签页(Render)。如消息的派发,IO处理等等。
Browser进程为每个Render的每个RenderView,维护对应的RenderViewHost,管理浏览器状态、渲染器交互。
Browser进程为每个Render维护一个RenderProcessHost,用其来管理对应的RenderViewHost

2、Render
每个Render进程,持有一个Webkit(现在为Blink)内核对象。持有一个RenderProcess对象。这个对象,与Browser端的RenderProcessHost对应。同样,每个Render持有一个或多个RenderView,它于Browser端的RenderViewHost对应。
RenderProcess管理与浏览器进程间的通信,维护标签页状态。
RenderView代表网页的内容。它的唯一标识为,RenderProcessHost+ViewID。

3、Browser与Render间的通信
Browser与Render间通过IPC通信。
Browser端通过RenderViewHost与特定标签页中的特定内容交互。
RenderViewHost -> RenderProcessHost -> IPC -> RenderProcess -> RenderView

Native API

Electron 分别在主进程和渲染进程提供了大量 API,这里先不用管什么是进程。关于Native API我们需要知道的是,可以通过require语句方便的把这些 API 包含在当前模块使用。

对于NodeJS 上提供的 API,同样也只需要简单的require一下。但是 Electron 提供的 API 只能用于指定进程类型,即某些 API 只能用于渲染进程,而某些只能用于主进程。

例如,app,BrowserWindow就只能用于主进程,ipcRenderer、remote这些只能用于渲染进程。

Native API

另外,图中间的4个 Native api在两个进程中都可以使用,其中深色模块是工作中常用的模块:

● app 模块: 管理应用的生命周期,同时也可以设置app本身的一些属性,如Dock;
● BrowserWindow模块:管理我们的窗口;
● ipcMain 模块:与 ipcRender 进行IPC通信;
● Notification 模块:进行可交互的通知;
● webContents 模块:用来加载具体的页面;
● autoUpdater 模块:更新模块;
● globalShortcut 模块:设置全局的一个快捷键;
● clipboard 模块:读写剪切板;
● cashReporter 模块:监控主进程和渲染进程是否有崩溃;
● remote 模块:可以调用主进程的模块,但不建议使用(注:remote本质上是在基于IPC的一个同步的进程间消息,同步IPC会影响UI渲染。每次get和set操作都会触发,写得不好性能会卡,甚至UI hang掉);
● desktopCapture 模块:捕获桌面流,通过这个模块可以拿到像系统的截图、屏幕的视频流;

Electron进程

Electron进程
在electron中,进程区分为主进程和渲染进程。

electron 运行 package.json 中的 main 指定的入口脚本的进程称为主进程,一个应用只能有一个主进程。主进程负责的工作主要有:

负责创建、管理渲染进程、控制整个应用的生命周期、启动一个串口、加载index.html等本地文件、应用程序关闭后回收资源、退出程序等工作。

展示 Web 页面的进程被称为渲染进程,一个应用可以有多个渲染进程。渲染进程负责的工作主要有:

负责渲染显示界面、控制用户的交互逻辑、响应用户的交互等工作。也就是说,一个BrowserWindow实例就代表一个渲染进程。如果使用electron做普通的单页应用,你可以理解为就一个渲染进程。而且,当BrowserWindow实例被销毁后,该渲染进程也会跟着销毁。

另外,需要知道的是,在浏览器中 Web 页面是运行在沙盒环境中,无法访问操作系统的原生资源。而 Electron 可以让我们在每一个渲染进程中,使用 Node.js来去访问系统底层。

主进程

一个常见的主进程文件例子,

// main.js文件
const { app, BrowserWindow } = require("electron"); //引入 electron的app和BrowserWindow模块 
let mainWindow;

app.on("ready", () => {
  mainWindow = new BrowserWindow({ width: 800, height: 500 }); // 设置屏幕宽高

  mainWindow.setMenu(null); // 隐藏Chromium菜单
  mainWindow.loadFile("index.html"); // 加载index.html文件
  mainWindow.on("closed", () => {
    mainWindow = null;
  });
});

app.on("window-all-closed", () => {
  /* 在Mac系统用户通过Cmd+Q显式退出之前,保持应用程序和菜单栏处于激活状态。*/
  if (process.platform !== "darwin") {
    app.quit();
  }
});

app.on("activate", () => {
  /* 当dock图标被点击并且不会有其它窗口被打开的时候,在Mac系统上重新建立一个应用内的window。*/
  if (mainWindow === null) {
    createWindow();
  }
});

electron app 中常用的事件时机:

  • ready:即当electron初始化时被触发;
  • window-all-closed:所有窗口被关闭时触发;
  • before-quit:应用程序开始关闭窗口之前触发;
  • will-quit:当所有窗口都已关闭并且应用程序将退出时触发;
  • quit:当应用程序退出时触发;
  • active:当应用被激活时发出;

进程通信:主进程和渲染进程

在Electron中,主进程和渲染进程的通讯可以说是互相关联,也可以说不关联,是处于分支型。非常类似react 组件之间的通信。

进程通信

主进程和渲染进程的通信主要通过 ipcMainipcRenderer 这两个Native Api。

// 主进程中
ipcMain.on('message', (event,arg)=>{
  	event.sender.send('getMessage', '发送给渲染线程的消息')
})

// 渲染线程中
ipcRenderer.on(getMessage,(event, arg)=>{
  	console.log(arg);
})

进程通信:渲染进程和渲染进程

渲染进程之间是无法直接进行通信的,不过可以通过主进程来间接发送,是不是很像react的子组件之间的状态传递?

// 渲染进程 setting window
const { ipcRenderer } = require('electron')	// 引入ipc
ipcRenderer.send('setting window message', '发送给主线程的消息')



// 主线程中
ipcMain.on('setting window message', (event, arg)=>{
  	console.log(arg);
  	// 指定另一个渲染进程接收 ,这里的目标进程:mainWindow 
	mainWindow.webContents.send('main window message', arg) // 返回一个'顶你个肺'
})



// 渲染进程 main window 
const { ipcRenderer } = require('electron')	// 引入ipc
ipcRenderer.on('main window message', (event, arg)=>{
	// 接收到Main进程返回的消息
	console.log(arg);
})

Electron 安装

在项目中,我们可以直接通过yarn或者npm等包管理工具来安装electron,然后可以通过 -v 查看是否安装成功。

打包的话,我们需要用到另外一个包,electron-builder

yarn add electron -dev

electron -v  // 查看是否安装成功

yarn add electron-builder -dev

一般,我们可以指定 arch=ia32 来安装32位的electron,这样在 Windows 平台打包都应该要基于32位来打,这样打出来的包在32位和64位都可以用,只需维护一套即可。

yarn add --arch=ia32 --platform=win32 electron

React + Electron

我使用的前端脚手架是基于umi来搭建的,所以我在此基础之上进行了拓展。

umi 脚手架似乎没有官方内置的 electron 插件,因此使用了umi-plugin-electron-builder来快捷配置 electron。这个插件会自动帮你生成模板配置,十分方便。

⚠️需要注意的是,这个插件仅支持umi3版本。

$ yarn add umi-plugin-electron-builder --dev

安装插件之后,执行 umi dev electron 会生成相关文件,主进程文件 src/main/main.ts,然后会在package.json中增加入口配置。

打包配置,则需要我们手动在 .umirc.ts文件中配置,

  electronBuilder: {
    routerMode: 'hash', // 路由 只能是hash或memory
    outputDir: 'dist_electron', // 默认打包目录
    externals: [], // 不配置的无法使用
    rendererTarget: 'electron-renderer', // 构建目标electron-renderer 或 web
    builderOptions: {
      productName: 'electron-react-demo', // 项目名,也是生成的安装文件名,即electron-react-demo.exe
      appId: 'cc.yichen.electron-react-demo', // 包名
      copyright: 'Copyright © 2022-present 逸尘', // 版权信息
      nsis: {
        // https://www.electron.build/configuration/nsis
        oneClick: false, // 是否一键安装
        allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
        allowToChangeInstallationDirectory: true, // 允许修改安装目录
        installerIcon: './build/icons/icon.ico', // 安装图标
        uninstallerIcon: './build/icons/icon.ico', // 卸载图标
        installerHeaderIcon: './build/icons/icon.ico', // 安装时头部图标
        createDesktopShortcut: true, // 创建桌面图标
        createStartMenuShortcut: true, // 创建开始菜单图标
        shortcutName: 'electron-react-demo', // 图标名称
      },
      win: {
        // win exe 相关配置,
        icon: './build/icons/icon.ico',
        artifactName: '${productName}-v${version}-win32-setup.${ext}',
        target: [
          {
            target: 'nsis', // 利用nsis制作安装程序
            arch: [
              // 这个意思是打出来32 bit + 64 bit的包,但是要注意:这样打包出来的安装包体积比较大,所以建议直接打32的安装包。
              // "x64",
              'ia32',
            ],
          },
        ],
      },
      mac: {
        // mac pkg 配置项
        icon: './build/icons/icon.icns',
        artifactName: '${productName}-v${version}-mac.${ext}',
      },
      dmg: {
        // macOS dmg镜像 配置项,https://www.electron.build/configuration/dmg
        contents: [
          // 自定义图标位置。x 和 y坐标是指图标中心的位置(1x比例),不考虑标签
          {
            x: 410,
            y: 150,
            type: 'link',
            path: '/Applications',
          },
          {
            x: 130,
            y: 150,
            type: 'file',
          },
        ],
      },
      linux: {
        icon: './build/icons',
        artifactName: '${productName}-v${version}-linux.${ext}',
      },
      publish: [
        {
          provider: 'generic',
          url: '',
        },
      ],
    },
  },

关于项目打包,可以配置如下命令:

# windows
umi build electron --win

# mac
umi build electron --mac

# linux
umi build electron --linux

# windows 按平台打包
umi build electron --win --ia32    //32位
umi build electron --win --x64     //64位
umi build electron --win --armv7l  //arm32位
umi build electron --win --arm64   //arm64位

Vue + Electron

首先需要下载安装electron 和 vue-cli-plugin-electron-builder

yarn add electron --dev

yarn add vue-cli-plugin-electron-builder --dev

然后,这个插件我们需要手动去配置修改package.json,加入主进程文件background.js。以及,在 package.json 中配置启动项命令和打包命令,

    "electron:build": "vue-cli-service electron:build",
    "electron:build:mac": "vue-cli-service electron:build --macos",
    "electron:build:win64": "vue-cli-service electron:build --windows --x64",
    "electron:build:win32": "vue-cli-service electron:build --windows --ia32",
    "electron:serve": "vue-cli-service electron:serve",

打包配置,则需要我们手动在 vue.config.js文件中配置,


  pluginOptions: {
    electronBuilder: {
      // electron 构建配置
      builderOptions: {
        productName: 'electron-vue-demo', // 项目名,也是生成的安装文件名,即electron-vue-demo.exe
        appId: 'cc.yichen.electron-vue-demo', // 包名
        copyright: 'Copyright © 2022-present Yichen', // 版权
        nsis: {
          oneClick: false, // 是否一键安装
          allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
          allowToChangeInstallationDirectory: true, // 允许修改安装目录
          installerIcon: './build/icons/icon.ico', // 安装图标
          uninstallerIcon: './build/icons/icon.ico', // 卸载图标
          installerHeaderIcon: './build/icons/icon.ico', // 安装时头部图标
          createDesktopShortcut: true, // 创建桌面图标
          createStartMenuShortcut: true, // 创建开始菜单图标
          shortcutName: 'electron-vue-demo' // 图标名称
        },
        dmg: {
          // macOSdmg
          contents: [
            {
              x: 410,
              y: 150,
              type: 'link',
              path: '/Applications'
            },
            {
              x: 130,
              y: 150,
              type: 'file'
            }
          ]
        },
        mac: {
          // mac
          icon: './build/icons/icon.icns',
          artifactName: '${productName}-v${version}-mac.${ext}'
        },
        win: {
          // win 相关配置
          icon: './build/icons/icon.ico',
          artifactName: '${productName}-v${version}-win32-setup.${ext}',
          target: [
            {
              target: 'nsis', // 利用nsis制作安装程序
              arch: [
                // 这个意思是打出来32 bit + 64 bit的包,但是要注意:这样打包出来的安装包体积比较大,所以建议直接打32的安装包。
                // 'x64', // 64位
                'ia32' // 32位
              ]
            }
          ]
        }
      }
    }
  }

Electron & web 开发

ok,到这里,稍微总结一下,Electron相对于web开发的区别,主要体现在四个方面:

  • 第一,主进程与渲染进程;
  • 第二,进程间的通信;
  • 第三,需要用到很多原生能力;
  • 第四,可以较大程度上释放前端的想象里,跳出浏览器的一些限制,能做的事情更多;

解决跨域问题的三种方式:

  1. 关闭web安全性,webSecurity
  2. 使用NodeJS发送请求;
  3. 使用Electron net API发送请求;

这些都不会被浏览器的跨域请求所影响,而且可以做到请求的时候少一个option请求,也不会被浏览器同域名6个请求所限制住。

问题与挑战

除了上述的一些优势,electron也带来了一些问题和挑战。

  1. 应用端开发有一个很重要特点,就是它的发布频率更低,我们又有非常多的 Web 业务要集成,对代码质量要求会更高;
  2. 其次,要面对渲染进程和主进程的交互,以及非常多的系统交互,排查问题的链路更长;
  3. 最后,因为包是在用户的系统上,我们也会面临更多的安全性要求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/66237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习压力容器中卡箍快开结构的强度计算

导读:压力容器的设计一定要考虑安全性、经济性、环保及健康问题。首先安全是核心问题,在保证安全的前提下尽可能的再做到经济合理。 本文从强度计算软件SW6-2011 V3.1补丁二(单机版)和(网络版)所解决的问题&#xff0…

Redis 性能问题优化方案

Redis性能问题&优化方案前言Redis真的变慢了吗?使用复杂度过高的命令操作bigkey集中过期实例内存达到上限fork耗时严重开启内存大页开启AOF绑定CPU使用Swap碎片整理网络带宽过载其他原因频繁短连接运维监控其它程序争抢资源总结前言 Redis 作为优秀的内存数据库…

Java高效率复习-MySQL上篇[MySQL]

前言 本文章是用于总结尚硅谷MySQL教学视频的记录文章,主要用于复习,非商用 原视频连接:https://www.bilibili.com/video/BV1iq4y1u7vj/?p21&spm_id_frompageDriver&vd_sourcec4ecde834521bad789baa9ee29af1f6c https://www.bilib…

Spring Boot 项目优化和 JVM 调优,亲测!真实有效。。

三、Jvm调优实战 1、未设置JVM参数的情况 我现在有一个项目,默认情况下,没有设置任何Jvm参数。 下面我来启动看一下。 看一下堆栈分配: 很明显默认的最大堆内存分配了8个G。很明显的不合理嘛。 2、下面我们来设置下Jvm参数 例如要配置JVM…

vue2 ElementUI 表单标签、表格表头添加问号图标提示

文章目录1. 问题背景2. element-ui悬浮提示定义3. 基础4. 延申5. 参考1. 问题背景 使用element-ui有时候需要对表格的表头、表单的标签进行自定义,添加问号的悬浮提示。 要达到的效果,如图所示: 2. element-ui悬浮提示定义 https://elemen…

【菜菜的sklearn课堂笔记】聚类算法Kmeans-基于轮廓系数来选择n_clusters

视频作者:菜菜TsaiTsai 链接:【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili 我们通常会绘制轮廓系数分布图和聚类后的数据分布图来选择我们的最佳n_clusters from sklearn.metrics import silhouette_samples,silhouette_s…

c++还原简单的vector

文章目录vectorvecotor的介绍vector的模拟实现类的框架成员变量迭代器构造函数析构函数size()capacity()operator[]重载扩容resize()尾插验证是否为空尾删clear 清除swap交换insert插入erase删除迭代器区间初始化构造函数拷贝构造赋值运算符重载n个val构造函数再谈构造函数vect…

数仓日记 - 数仓理论

寒刃尽断处,吾心作剑霜作锋🏂 目录 一、数仓简介 二、关系建模与维度建模 1. 关系建模   2. 维度建模    • 三种模型    • 事实表    • 维度表   3. 事实表的分类    • 事务型事实表    • 周期型快照事实表    • 累积型快照事实表…

Python操作Excel表格

本文介绍如何通过轻量级、零依赖(仅使用标准库)的 pylightxl 库操作Excel表格。 官网:Welcome to pylightxl documentation — pylightxl 2019 documentation 目录 一、入门 1. 读写CSV文件 2. 读Excel文件 3. 获取工作表和单元格数据 3…

前端css实现特殊日期网页变灰功能

前端变灰效果在网页实际使用过程中使用的比较少,但有时候又缺一不可,一般在大型哀悼日或纪念日的时候使用,使用后的网站页面会变成灰色(黑白色)。 我们先看下各大网站是怎么实现的: 1.csdn实现方式 2.淘宝 3.人民网 4.京东 5.掘…

Unity【Multiplayer 多人在线】服务端、客户端通用架构的使用指南

文章目录🚩 Import🚀 protogen使用方法🪐 客户端接口🌈 服务端接口🧭 数据处理🎨 Example🚩 Import 下载SKFramework框架,导入到Unity中; 在框架Package Manager中搜索并…

osgEarth示例分析——osgearth_colorfilter

前言 osgearth_colorfilter颜色过滤器示例。本示例中,主要展示了6种颜色过滤器的使用,分别是:HSLColorFilter、RGBColorFilter、CMYKColorFilter、BrightnessContrastColorFilter、GammaColorFilter、ChromaKeyColorFilter。 执行命令 // 一条命令是一…

Docker日常运维小技巧

一、故障定位 1、查看容器内部 https 请求响应时间 docker exec -t $(docker ps -f nameblog_web -q) curl -H X-Forwarded-Proto:https \-w %{time_total} -o /dev/null -s localhost 2、查看容器日志 docker logs --tail 50 --follow --timestamps mediawiki_web_1 3、删…

深圳SMT贴片行业MES系统解决方案~MES系统服务商~先达智控

随着我国工业的迅速发展,所有电子行业都离不开SMT贴片生产,SMT贴片生产是电子行业的至关重要的一道工业环节,我国作为一个工业制造大国,有着完备的SMT现代产业体系。SMT贴片领域是我国支柱性产业其一,SMT贴片产品涵盖工…

【JavaWeb开发-Servlet】day01-使用TomCat实现本地web部署

目录 1、准备java web开发环境 (1)下载javaJDK(推荐使用JDK1.8,企业常用且稳定) (2)下载TomCat服务器 2、创建web服务器TomCat (1)创建一个项目文件夹 (2)在文件夹中新建一个记事本并编以下…

算法大神左程云耗尽5年心血分享程序员代码面试指南第2版文档

前言 学习是一种基础性的能力。然而,“吾生也有涯,而知也无涯。”,如果学习不注意方法,则会“以有涯随无涯,殆矣”。 学习就像吃饭睡觉一样,是人的一种本能,人人都有学习的能力。我们在刚出生…

移动WEB开发之rem布局--苏宁首页案例制作(技术方案1)

案例:苏宁网移动端首页 访问地址:苏宁易购(Suning.com)-家电家装成套购,专注服务省心购! 1. 技术选型 方案:我们采取单独制作移动页面方案 技术:布局采取rem适配布局(less rem 媒体查询&am…

用 TensorFlow.js 在浏览器中训练一个计算机视觉模型(手写数字分类器)

文章目录Building a CNN in JavaScriptUsing Callbacks for VisualizationTraining with the MNIST DatasetRunning Inference on Images in TensorFlow.jsReferences我们在《在浏览器中运行 TensorFlow.js 来训练模型并给出预测结果(Iris 数据集)》中已…

数字源表如何测试MOS管?

MOSFET(金属—氧化物半导体场效应晶体管)是 一种利用电场效应来控制其电流大小的常见半导体器件,可 以 广 泛 应 用 在 模 拟 电 路 和 数 字 电 路 当 中 。 MOSFET可以由硅制作,也可以由石墨烯,碳纳米管 等材料制作,是材料及器件…

集成电路模拟版图入门-转行模拟版图基础学习笔记(二)

在众多IC岗位中,模拟版图确实属于容易入门,吸引来很多想要转行IC行业的朋友,但需要掌握的知识点和技巧并不比设计少,属于门槛简单,上手不易,想要自学模拟版图似乎比较困难。 之前为大家分享过移知学员的模…