Electron 桌面应用开发系列文章 - 减少应用的打包体积

前言

笔者最近一直在使用 electron 开发一个可视化工具 Nowa,里面的技术栈是css

  • webpack2node

  • babilireact

  • reactwebpack

  • electrongit

  • electron-builderes6

使用过 electron 的人都知道,打出来的包是很大的,由于electron 内置了 Node & Chromium, 因此啥都还没干,打出来的应用安装包就有几十兆了。github

没法在 electron 上作文章,那么只好在 webpack 打包程序代码的过程当中捣鼓了。之前打包应用的时候,程序里会有 node_modules 文件夹。此次任务就是干掉这个文件夹。web

目录结构

ele0

你们会发现这里竟然有两个 package.json !! 其实主要是由于 electron-builder 的 Two package.json Structure 的设置。把打包须要的依赖与开发依赖彻底分开,纯粹打包你想要的东西,因此设置了 app 文件夹放这些。chrome

electron-builder 只会对 app 文件夹进行打包,换句话说,这里面有多少东西就会打包多少内容。json

因此咱们能够想法设法减小没必要要的东西。好比这里没有任何依赖, node_modules 是空的!

打包过程干货

结合 electron 的特殊环境,webpack 编译过程有不少文章能够作。

一、 考虑 electron 的 Chromium & Node 版本

在 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 端依赖很大的话,那真是灾难。

实际上 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 端注意事项

对 main 端打包的条件是有些条件的。

  • 若是说您使用了remote.require(xxx) 的方式在 renderer 端引入了 main 端须要的模块,那么您须要在 app 目录下放该模块。

  • 若是在 main 端调用了 child_process 的方法去执行放在 app 文件夹里面的js文件,而这些脚本依赖了非 node 原生模块的时候,请把这些模块安装到 app 里面的 node_modules 里面。

main 端遇到的问题

main 端打包容易碰到以下问题:

依赖中出现 #!/usr/bin/env node 这样的语句或者包含了 *.node 的脚本,这个使用您须要使用一些特殊的 loader 进行处理。

{
 test: /\.js$/,
 include: /node_modules/,
 loader: 'shebang-loader'
},
{
   test: /\.node$/,
   include: /node_modules/,
   loader: 'node-loader'
}

三、合适的renderer 端构建方案

笔者在renderer 端构建采用了 DLL(动态连接库)方案, 也是 webpack 官方比较推荐的方案。它能够快速的提高构建速度,特别是明显的提高第一次启动的速度。在生产环境就不要使用它了,由于 dll 文件的体积比较大。
css 要使用 ExtractTextPlugin 与 js 代码分离开来,不要合并,不要合并,由于文件体积一样比较大。

四、 注意 electron 版本号 和 electron-builder 版本号

使用新的 electron 版本打包出来的安装包会比旧版本大几兆,其实很容易理解。

使用不一样版本的 electron-builder 打包出来的也不一样。大于 13.* 版本的打包出来的安装包一样大几兆。

几兆究竟是几兆呢? demo 的例子实测是 3~5 MB。若是你们不care这几兆的话其实无所谓。

为了减少安装包体积,笔者真是无所不用其极。

若是你们有更好的打包方式,请评论回复。

参考

相关文章
相关标签/搜索