electron与vite的运行原理的探究
最近要做electron的项目,网上搜了一下,现在已经有electron+vite的框架了。但是为了能够更好的搭建项目,就探究了一下其运行原理。
electron
electron是一个用来创建桌面应用的框架,能够利用html,css,js来创建桌面应用。但准确来说,electron这个包仅支持在线预览的功能,即只需要一个index.html作为入口文件,一个main.js作为主进程,即可在线预览桌面应用的效果。
但其本身不具备将项目打包成exe可执行的功能,如果需要打包成exe,则需要借助打包工具来打包。以前是用electron-package这个包来打包的,但是由于electron-package的种种问题后面出了electron-builder,现在就统一用electron-builder这个包来打包。
electron-builder
要将html,js,css文件都打包成exe文件,则需要用到electron-builder这个包,它可以将html,js,css打包成exe文件。
可以在script中配置打包命令"build": "electron-builder --win --x64"
,然后在package.json中配置build参数,在打包时会自动识别到这个配置,并且打包成相应的exe文件。
electron-builder打包的时候,会把Chromium浏览器内核和nodejs都打包进去,所以即使什么内容都不写,一个包的体积都会达到130M。
vite
vite是最新推出的前端打包工具,也是现在最流行的打包工具。首先要弄懂两个问题——1.为什么vite会这么快?以及由于vite在开发环境下不打包,2.那么为什么浏览器能够识别.vue, .jsx文件?
1.vite是用esbuild构建的打包工具,而esbuild是用go语言写的,构建速度比webpack这种用js构建的打包工具要快10-100倍,耗时也只有webpack的2%~3%。
2.vite利用了浏览器天然支持import语法的方式,是天然的按需加载,并将需要加载的依赖都交给浏览器去处理,也就是把压力扔给浏览器,从而达到项目启动速度快的效果。
3. 浏览器并不能识别.vue文件,所以vite其实是在启动的时候做了预编译,将那些浏览器不能识别的代码编译成js, html, css文件。虽然这个过程和打包很像,但是由于以上的优点,所以vite依旧是比webpack快。
vite的运行原理
vite的运行原理是用koa搭建一个web服务器,然后托管入口index.html文件。当有用户请求“/”路径的时候,web服务器会返回给index.html静态文件。又因为里面有main.js入口文件,所以会返回入口文件的内容,以及挂载的App.vue组件。又因为浏览器不能识别import vue from 'vue'
这种裸模块,所以当vite发现里面的js文件需要请求裸模块的时候,会给它添加一个/@module/vue开头变成绝对路径,然后再进一步解析,找到该包的位置,并且借助这个包的解释器,把代码变成浏览器能够识别的html, css, js文件。
electron+vite
知道vite的工作原理后,我们可以看出github上的electron+vite项目搭建,都是从vite中导出vite的服务器,然后自己创建一个新的服务器,然后再借助vite预编译的能力,将vue转成electron能够识别的html, css, js文件,并返回给electron加载。
electron+nodejs
electron是把nodejs也打包进去,所以包含了node环境。electron分成main主进程和renderer渲染进程,也就是可以在main主进程中使用nodejs模块,renderer要使用nodejs模块则需要开启nodeIntegration: true, contextIsolation: false
配置。但是自从electron@9.x开始,electron就不推荐这种做法了。而是将main和renderer上下文隔离起来,不允许在renderer中使用nodejs模块。虽然开启上下文配置也可以在renderer中调用nodejs模块,但是electron提供了另一个方法在renderer中调用nodejs模块。使用 exposeInMainWorld
将nodejs的API暴露给renderer,这样renderer也能使用nodejs的模块。
Native Addon
一个 Native Addon 在 Nodejs 的环境里就是一个二进制文件, 这个文件是由低级语言, 比如 C 或 C++实现, 我们可以像调用其他模块一样 require() 导入 Native Addon
Native Module
Native Addon 与其他.js 的结尾的一样, 会暴露出 module.exports 或者 exports 对象, 这些被封装到 node 模块中的文件也被成为 Native Module(原生模块).
node module
node模块。
serialport
从serialport的包目录我们可以看到,serialport有一部分是用C++实现的,所以serialport是一个标准的native module,而在electron中,不能直接使用native module,所以需要用electron-rebuild,将serialport编译成electron能够识别的文件。
目前推荐使用v10.0.0版本
electron-rebuild
实际上electron-rebuild是借助了node-gyp这个工具来编译的。
node-gyp
需要全局安装node-gyp,GYP 全称是 Generate Your Project,是一个用 Python 写成的工具,所以需要python3.x和visual studio 2017或2019的C++工作环境(目前暂不支持2022)。安装完后,就有能将C/C++编译成Native Addon或者动态库的能力了。只需要在使用包时node-gyp build
,就能根据当前的系统生成只能为当前系统使用的bindings.node文件,然后在nodejs中用require导入这个文件,就能使用包中的C++部分了。
electron-vite-serialport(native module)
根据上面electron-vite的运行原理,以及serialport(native module)的概念可知,如果想要在main主进程或者是preload里面使用serialport(native module),只需要electron-rebuild一下就行了。但是如果想要在renderer中使用serialport(native module),则需要通过exposeInMainWorld
将serialport(native module)里面的方法暴露给renderer,再使用。
打包构建
由于vite本身只能处理ESModule,所以所有关于node模块都需要external出去,不需要vite打包。
但是由于electron-builder的特性,会去自动识别package.json中的依赖,并且从node_nodule中拉取打包,所以打包后的文件里面依旧包含这个模块。
作者:天平
链接:https://juejin.cn/post/7054455207719092238