Overview
基于 Electron
+ Vite
开发一款日常使用工具软件.
基于 Electron + Webpack + React 开发一款日常使用工具软件
技术方案
脚手架模板
基于 Vite + React 的模板方案,GitHub - electron-vite/electron-vite-react: Electron + Vite + React + Sass boilerplate.
原因是模板内容比较少,没有复杂的设计,方便后期技术迭代,同时也想体验下 Vite
跨线程共享 Redux
使用 electron-redux 来实现应用的 Redux Store 跨线程共享,具体看这里Electron Redux 状态共享.
替换 Vite 使用 Webpack 开发
🎯 基于 electron-react-boilerplate
项目配置
Main 使用 ES Module
electron 依然不支持直接使用 ESM,但是一些依赖包在逐渐放弃 CommonJs 改为使用纯 ESM 包,例如 get-port
、google/zx
等,为了在主进程中能够使用 ESM,在electron-react-boilerplate
样板的基础上针对main.ts
添加
webpack 打包,将 ESM 打包为 Commonjs 使用
主进程热重载
electronmon
监听主进程文件变化,对主进程代码进行热更新,类似于nodemon
,使用方式是在package script 替换electron .
来启动应用。
为 main 添加 webpack 打包之后,原来的 electronmon 监听 main.ts
修改并热重载应用的方式就不适用了,之前的 main.ts使用的是 ts-node进行构建的,需要修改electronmon
的使用方式,改为启动 weboack 构建之后的文件,并监听。
需要注意的是main
和preload
一样,需要在单独的进程中去启动监听,否则webpack watch 会阻塞后续任务的执行。
electronmon
在使用时有可能出现 main watch
进程没有杀死的情况,导致多个进程存在,当输出文件变动时,会唤起多个 app 实例,有时候会出现这种情况,可选则替代方案 webpack-electron-reload
;
webpack-electron-reload
方案:
在 webpack.main.dev.ts
中添加一下代码:
preload 文件热更新
通过 webpack
的 watch
模式监听 preload.ts
文件,当文件发生变化时,watch
模式下的preload.ts
文件会实时更新主进程的 preload.js
文件,触发electronmon
更新主进程。
dev script
ts-node ./.erb/scripts/check-port-in-use.js && npm run dev:renderer
执行端口检查脚本,和 dev:renderer
package
-
registry-js: windows 读取注册表信息
-
electron-redux:electron main 和 renderer 共享 redux
-
@reduxjs/toolkit:redux 工具包
工程类: -
BundleAnalyzerPlugin
打包分析 -
detect-port
检查端口 -
@pmmmwh/react-refresh-webpack-plugin
用于为React
组件启用“快速刷新”(也称为热重载) -
concurrently
同步运行command
-
electron-builder
打包electron
应用 -
husky git钩子
项目工程
- 添加 package-lock.json、yarn-lock.json gitgnore,仅使用 pnpm
- 梳理 package.json 配置,移除无用的配置
- 梳理 webpack 配置,移除无用的配置
- 删除项目自带 Eslint Config,配置自己的规则,package.json 中的相关依赖需要移除
- electron main进程中通过webpack或者其他方式支持 alias → issues
- 通过
tsconfig-paths-webpack-plugin
、tsconfig-paths
插件自动同步tsconfig.json paths
至webpack alias
→ link
Xtrem
使用 Xtrem实现终端功能
FAQ
- dependencies vs devDependencies
- Using C/C++ native addons in Electron-Renderer
- Node.js ESM packages (e.g.
execa
node-fetch
) - 脚手架地址
- 渲染进程中使用 NodeJs/Electorn API 问题
- electron-vite-react
- vite-plugin-electron-renderer
- electron-renderer
- 处理 Electron 中无法使用 ESM 模块的问题(有问题,但是没解决成功)
- StrictMode 模式下react-devtools-backend扩展自动输出console.log问题
- Why is console.log() showing react_devtools_backend.js:4049 instead of the file and line number?
- [DevTools] Console logging and StrictMode double rendering
- Console log shows the wrong destination file
- 添加 webpack main dev 之后主进程无法 reload
- electron-react-boilerplate是如何实现的
FAQ
如何在主线程和渲染线程中使用 NodeJs/Electron API
正常来说在渲染线程中是没有办法使用 NodeJs API的,因为渲染线程属于浏览器环境,一般的做法是通过 Electron Preload
将 Electron
API 注入到渲染进程在渲染进程中使用 window.xxx
来使用,具体的方法为:
- 在
new BrowserWindow()
是配置webPreferences
参数
nodeIntegration
: 是否启用Node integration, 如果想要在渲染进程中使用NodeJs/Electorn模块contextIsolation
: 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本.默认为 true
- 在
preload
文件中加入下面代码
或者
如果使用Typescript
的话需要加入 Global
类型:
在渲染进程中使用:
相关iuess
:
- Error while importing electron in react | import { ipcRenderer } from ‘electron’ · Issue #9920 · electron/electron · GitHub
- Error while importing electron in react | import { ipcRenderer } from ‘electron’ · Issue #9920 · electron/electron · GitHub
- require is not defined · Issue #50 · electron-vite/electron-vite-react · GitHub
如果想直接在渲染进程中使用NodeJs、Electron API
,也是可以的,但是需要注意
这样做并不安全。
因为使用的是 electron-vite-react
模板,它提供了更便捷的方式让我们在渲染进程中使用Node
,这里需要安装两个个包:
- 在主线程 main.ts 中配置
- 配置vite.config.ts
- 在渲染进程中使用
测试代码:
相关 iuess
:
无法在主线程中使用 ESM 包
官方关于 Electron支持ESM的讨论:Support Node’s ES Modules · Issue #21457 · electron/electron · GitHub
在 Electron 中无法直接使用 ESM模块的包,例如get-port
这个包,它的package.json 下标明了这个包是一个 esm 包:
在使用的时候会报错
没找到比较好的办法来实现在Electron 中使用 ESM模块,最简单的就是“换个包”或者使用支持CommonJS
的老版本。
因为使用的是 vite-electron-react
这个模板,所以找了下发现作者似乎提供了将 ESM
转 CommonJS
模块的功能:
需要下载安装这个包,vite-plugin-esmodule,然后根据文档配置,但是经过测试,发现并没有生效,但是在.vite-plugin-esmodule
文件夹下已经有了转换后的模块。其中 index.js 是 CommonJS模块,render是给渲染进程用的ESM模块,
但是主进程依然使用不了,打包出来的代码,引用的还是 node_modules/get-potr
下的index,并没有引用 .vite-plugin-esmodule
下的 index
, 看了下 vite-plugin-esmodule 源码,发现环境判断有点问题
isElectronRendererServe
的值为 true
,会设置 replacement
为 renderid
, 也就是 ESM
模块,尝试将 isElectronRendererServe
手动设置为 false
,依然会有问题,不知道是不是跟 pnpm
有关系。
目前还没找到比较好的方法,可以看下这个资料:
- 如何在Electron中导入 ESM
- 官方关于 Electron支持ESM的讨论:Support Node’s ES Modules · Issue #21457 · electron/electron · GitHub
- 将ES模块转换为用于Electron和Node的Commonjs · Issue #2652 · vitejs/vite · GitHub
Vite
是基于ESM
优先的,并且建立在ESM
的基础上,Vite
也在重点推动ESM
的使用,所在在Vite
中支持这个功能不太可能,有一些成功的实现- GitHub - cawa-93/vite-electron-builder: Secure boilerplate for Electron app based on Vite. TypeScript + Vue/React/Angular/Svelte/Vanilla
- Transforming ES modules to Commonjs for Electron and Node · Issue #2652 · vitejs/vite · GitHub
算鸟,Vite开发Electron坑太多了,还是去用Webpack吧
Node spawn 执行Shell失败问题
使用 node spawn 执行 exe 文件时,有一些程序会直接报错 -4092
上面两行代码,第二行能够正常执行,打开app,第一行运行时会报错,解决办法是给 spawn
方法的 options
参数添加 shell 配置,但是为啥这样写可以运行,没弄明白..
shell
配置的含义