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這幾兆的話其實無所謂。

爲了減少安裝包體積,筆者真是無所不用其極。

若是你們有更好的打包方式,請評論回覆。

參考

相關文章
相關標籤/搜索