笔者最近一直在使用 electron 开发一个可视化工具 Nowa,里面的技术栈是css
webpack2node
babilireact
reactwebpack
electrongit
electron-builderes6
使用过 electron 的人都知道,打出来的包是很大的,由于electron 内置了 Node & Chromium, 因此啥都还没干,打出来的应用安装包就有几十兆了。github
没法在 electron 上作文章,那么只好在 webpack 打包程序代码的过程当中捣鼓了。之前打包应用的时候,程序里会有 node_modules
文件夹。此次任务就是干掉这个文件夹。web
你们会发现这里竟然有两个 package.json
!! 其实主要是由于 electron-builder 的 Two package.json Structure 的设置。把打包须要的依赖与开发依赖彻底分开,纯粹打包你想要的东西,因此设置了 app 文件夹放这些。chrome
electron-builder 只会对 app 文件夹进行打包,换句话说,这里面有多少东西就会打包多少内容。json
因此咱们能够想法设法减小没必要要的东西。好比这里没有任何依赖, node_modules
是空的!
结合 electron 的特殊环境,webpack 编译过程有不少文章能够作。
在 webpack 打包的时候,咱们抛弃低版本浏览器的那些兼容,由于咱们只用 Chromium,因此没必要要的会增长编译输出的 preset 就不要了,好比 loose
,和一些 shim。
并且高版本的 node 已经支持一些 es6 的属性了,咱们真的须要降级到 es5 么?固然不是的。
A、 修改 babel 配置
推荐使用 babel-preset-env
设置。这个 preset 主要能够设置项目当前的环境,适时进行引入新特性,若是对其没有其余配置,就至关于使用了 babel-preset-latest
。
// .babelrc { "presets": [ ["env", { "targets": { "electron": 1.6, }, "loose": false, "modules": false, "useBuiltIns": true }], "stage-2", "react" ], "plugins": [ ] }
demo 里面设置了 targets
是 electron 1.6 版本,若是不嫌麻烦的话,能够根据当前的 electron 的 node 和 chrome 版本进行分别设置。
好比:
"targets": { "node": 7.4, "chrome": 56 }
B、 更换压缩方案
一般咱们之前的打包方案是这样子的:
ES2015+ code -> Babel -> Babili/Uglify -> Minified ES5 Code
如今,咱们能够不用降级这么多,使用一个工具babili(不要当作bilibili),它是 babel 的压缩工具。
babili 的打包方案是这样的:
ES2015+ code -> Babili -> Minified ES2015+ Code
它不会编译成 es5 的版本,而是对当前版本进行压缩。这简直就是 electron 的绝配啊。
为了能在 webpack 中使用,咱们须要引入一个插件 babili-webpack-plugin
。 这个是使用于生产环境的,因此咱们 webpack 生产环境配置中能够这样引入:
// webpack.prod.config.js const BabiliPlugin = require('babili-webpack-plugin'); module.exports = { ..., plugins: [ ..., new BabiliPlugin() ] }
一般咱们可能不对 main 端进行打包,我以前作的项目就没打包,main 端的依赖所有都合入安装包去了。若是 main 端依赖很大的话,那真是灾难。
实际上 main 端也能进行打包,与 renderer 端同样,输出到 app
目录,这样 node_modules 就空了。
然而,若是有引入第三方的 native node 模块的话,笔者没有尝试过是否能行得通,猜想极可能仍是要放到 node_modules
里面保险。有尝试过的看官请留言。
对 main & renderer 端打包代码的时候,要注意设置 webpack 的 target
字段。
// renderer.webpack.config { target: 'electron-renderer' } // main.webpack.config { target: 'electron-main' }
webpack 的 target 默认是 web
。若是你没有进行更改的话,renderer 端就没法使用 node 模块了。
对 main 端打包的条件是有些条件的。
若是说您使用了remote.require(xxx)
的方式在 renderer 端引入了 main 端须要的模块,那么您须要在 app 目录下放该模块。
若是在 main 端调用了 child_process
的方法去执行放在 app 文件夹里面的js文件,而这些脚本依赖了非 node 原生模块的时候,请把这些模块安装到 app 里面的 node_modules 里面。
main 端打包容易碰到以下问题:
依赖中出现 #!/usr/bin/env node
这样的语句或者包含了 *.node
的脚本,这个使用您须要使用一些特殊的 loader 进行处理。
{ test: /\.js$/, include: /node_modules/, loader: 'shebang-loader' }, { test: /\.node$/, include: /node_modules/, loader: 'node-loader' }
笔者在renderer 端构建采用了 DLL(动态连接库)方案, 也是 webpack 官方比较推荐的方案。它能够快速的提高构建速度,特别是明显的提高第一次启动的速度。在生产环境就不要使用它了,由于 dll 文件的体积比较大。
css 要使用 ExtractTextPlugin
与 js 代码分离开来,不要合并,不要合并,由于文件体积一样比较大。
使用新的 electron 版本打包出来的安装包会比旧版本大几兆,其实很容易理解。
使用不一样版本的 electron-builder 打包出来的也不一样。大于 13.* 版本的打包出来的安装包一样大几兆。
几兆究竟是几兆呢? demo 的例子实测是 3~5 MB。若是你们不care这几兆的话其实无所谓。
为了减少安装包体积,笔者真是无所不用其极。
若是你们有更好的打包方式,请评论回复。