筆者最近一直在使用 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這幾兆的話其實無所謂。
爲了減少安裝包體積,筆者真是無所不用其極。
若是你們有更好的打包方式,請評論回覆。