如何有效提升快應用(Webpack)編譯速度

背景

在開發快應用時,少不了構建操作:npm run build(官方 IDE 集成了這些操作,本質上也是調用同樣方法)。這是因為快應用有自己的 DSL 語法,直接寫出來,在底層不能識別,需要把業務代碼編譯成底層能運行的代碼(感興趣的同學,可在 build 文件夾查看編譯后的代碼產物)。整個過程就跟 Vue 和 React 工程的打包一樣。等待的過程總是漫長,當項目越來越大的時候,難免還要花上點時間。可誰不希望這個過程越快越好呢?本篇就在于探討,如何有效提升快應用(Webpack)編譯速度。

快應用工程是基于 hap-toolkit 編譯打包的。而它的功能,部分是基于 Webpack 開發。所以下面跟大家分享的,關于提升快應用編譯速度的方法,同樣也適用于基于 Webpack 構建的 Web 應用。

本文原本首發于 vivo 快應用官方博客。

基于插件

不過畢竟是 Webpack 上的封裝,所以不是所有方法都可以用上。現在 hap-toolkit 支持一些自定義配置了,可以使用部分 loader 和 plugin。詳情請查看 ToolKit 項目配置 里面有自定義 webpack plugin 的代碼示例。我們這里要講的就是使用 hard-source-webpack-plugin 插件來為編譯加速。

對于做過 Webpack 性能優化的同學,可能有用到過 HardSourceWebpackPlugin 插件,用于為模塊提供中間緩存步驟。它能明顯提升第二次構建速度:

HardSourceWebpackPlugin is a plugin for webpack to provide an intermediate caching step for modules. In order to see results, you'll need to run webpack twice with this plugin: the first build will take the normal amount of time. The second build will be significantly faster.

安裝

yarn add --dev hard-source-webpack-plugin
// OR
npm i hard-source-webpack-plugin --save-dev

使用

在項目根目錄下增加 quickapp.config.js 文件,做如下代碼配置:

const HardSourceWebpackPlugin = require("hard-source-webpack-plugin");
module.exports = {
  webpack: {
    plugins: [new HardSourceWebpackPlugin()],
  },
};

如上,一點簡單的配置,即可輕松使用。當然,也可以通過添加參數,來“量身”定制。下面拿快應用官方 Sample 來看一下。

參數介紹

首先,完全的第一次編譯,會花費較長時間。這是因為編譯過程需要依賴到 babel 模塊,在 webpack 里它化身為 babel-loader,編譯過程需要解析成 AST,再轉換成我們要的輸出格式(對該部分知識感興趣的同學可自行查閱)。這一過程極為耗時,所以作為一個有擔當的依賴,它也應該有自己的緩存。
這一配置已經在 hap-toolkit 寫好了。可以在項目目錄下node_modules/.cache/babel-loader看到 babel 緩存。

使用 hard-source-webpack-plugin 插件,編譯速度會有顯著提高。
在上述存放緩存的地點,可以發現多了個 hard-source 的文件夾,里面正是存放著插件生成的緩存。再看看一些參數的介紹,我們直接在代碼上以注釋的形式展示:

new HardSourceWebpackPlugin({
  // 緩存存放的地址,以 webpack 的執行目錄加該字段拼接而成,一般都是存放于項目目錄下
  // 也可以寫成絕對路徑,存放到別的地方
  cacheDirectory: "node_modules/.cache/hard-source/[confighash]",
  // 緩存文件夾的名字生成方式,這里的值對于上方的 configHash
  configHash: function (webpackConfig) {
    return require("node-object-hash")({ sort: false }).hash(webpackConfig);
  },
  // 環境hash,其實就是監聽依賴有沒有更改,有的話也更新緩存
  // 一般 files 填一個 package-lock.json 也夠了
  environmentHash: {
    root: process.cwd(),
    directories: [],
    files: ["package-lock.json", "yarn.lock"],
  },
  cachePrune: {
    // 緩存的存在時間,默認為兩天
    maxAge: 2 * 24 * 60 * 60 * 1000,
    // 緩存的最大容量,默認為 50 MB
    sizeThreshold: 50 * 1024 * 1024,
  },
});

需要注意下,如果用官方 IDE 來打開項目,由于 IDE 的運行路徑,與項目路徑不一致,會導致報錯,需要設置 environmentHash 來修正:

new HardSourceWebpackPlugin({
  environmentHash: {
    root: __dirname,
  },
});

基于文件操作

一 移除 source-map

source-map,簡而言之,就是編譯后的代碼與源代碼的一個映射。在進行代碼調試時候,執行環境運行的是編譯后的代碼,但可以看到對應的源代碼;最常見的就是瀏覽器中,通過打斷點,定位到源代碼去,這樣就可以發現源代碼出現的問題。

通過閱讀 Webpack Devtool 文檔,可以知道,source-map 構建也需要時間;且跟還原度也有關系,越精確越耗時間,尤其是值為 source-map 模式。

hap-toolkit 默認設置,release 就是設置為 “none”;debug 模式由于要考慮到還原度,選擇了 “cheap-eval-source-map”。那么,如果平時無需 source-map,可以直接將其設置為 “none”,即可進一步加快速度。同時,也會帶來問題,即調試之時,無法精確對應源代碼。您可以有兩種方式,來關閉 source-map

  1. 通過修改 quickapp.config.js 配置:
module.exports = {
  cli: {
    devtool: "none",
  },
};
  1. 通過命令行
// 此方法,在 IDE 中不適用
npm run build -- --devtool none

這個對于速度有小幅提升。這個雖然效果不如緩存提升得那么明顯,但是勝在作用于每次打包,對于首次打包也是有效的。

二 減少編譯代碼

我們知道,編譯速度跟代碼量也有關系,那么減少“需要編譯的文件”,當然就可以加快速度。開發時候,通常都是一個或者幾個相關頁面來開發。所以開發過程中可以只編譯當前需要的頁面。
hap-toolkit 收集頁面是通過 manifest.json 的 router.page 配置,而不是通過工程的 src 下具體文件。所以可以先去掉不相干的頁面配置,而不需要去除實際文件。
最簡單情況可以只留下單個頁面,對比起好幾個甚至十幾個頁面的編譯速度,提速效果還是相當明顯的。

三 加快文件搜索

代碼量對編譯速度有影響,自然的,尋找需要編譯的文件也要花時間的。
我們在代碼中對文件的引用,寫了很多相對路徑,而且也習慣不寫文件后綴。webpack 沒有那么神可以洞察開發者內心的訴求,而是根據配置好的搜索條件,不斷地循環查找。
webpack 的 resolve 配置就是干這個活的。

我們摘取其中實用的來說,先上代碼,在快應用中 quickapp.config.js 配置:

const path = require("path");
module.exports = {
  webpack: {
    resolve: {
      alias: {
        "@src": path.resolve(__dirname, "src"),
      },
      modules: ["./src/components"],
    },
  },
};

1、resolve.modules:配置 Webpack 去哪些目錄下尋找第三方模塊,默認配置是去 node_modules 目錄下尋找。
有時做了一個公用組件庫,給不同的地方調用。在不同地方的引入,就有可能導致這個路徑會很長,如 import '../../../components/button'。這時可以利用 modules 配置項優化,假如組件庫在 ./src/components 目錄下,就可以給 modules 增加'./src/components'這樣一個地址,供 webpack 快速命中資源位置。

2、resolve.alias: 給路徑起別名。當代碼中使用了眾多相對路徑,不僅我們去找這個文件費勁,webpack 也是需要時間去解析。所以直接配置好絕對路徑,在代碼中用別名代替冗長的路徑。于編譯解析,于代碼書寫,都是利好,兩開花!

3、resolve.extensions: 則是告知 webpack 獲取哪些類型的文件。比如:['js', 'ux'],當我們引用文件是這樣寫 import util from './util',在定位到目錄之后,就開始按照 util.js -> util.ux 的順序去尋找該文件。
也就是這個字段配置作用是方便了代碼的書寫,但是增加 webpack 的搜索時間(故此字段僅為介紹,無需增加配置)。所以如果代碼中精確到完整文件名,在大工程多引用文件數的情況下,也是能節省一筆可觀的時間消耗喲。

隨著工具的升級,及開放自定義程度的提高,整體編譯速度也會不斷提升,敬請期待。

您可能會感興趣的文章

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,238評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,430評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,134評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,893評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,653評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,136評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,212評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,372評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,888評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,738評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,482評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,179評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,588評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,829評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,610評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,916評論 2 372