您好,登錄后才能下訂單哦!
這篇文章主要介紹了JS加載性能Tree Shaking優化的方法是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇JS加載性能Tree Shaking優化的方法是什么文章都會有所收獲,下面我們一起來看看吧。
您可以將應用程序想象成一棵樹。您實際使用的源代碼和庫表示樹中綠色的活葉子,死代碼表示秋天時樹上棕色的枯葉,為了除掉枯葉,你必須搖動樹,讓它們掉下。Tree Shaking 是指消除死代碼,下面通過一個應用程序演示了這個概念。使用 ES6 靜態模塊語法導入依賴項:
// 在這里導入了所有的數組處理方法 import arrayUtils from "array-utils";
在應用最初的時候,依賴項可能很少,隨著功能逐漸增加,依賴項也會增加,更糟糕的是,舊的依賴項不再使用,但可能不會從代碼庫中刪除,最終的結果是,應用程序帶有大量未使用的 JS 代碼,Tree Shaking 解決了這個問題,它通過分析我們在文件中使用的 ES6 靜態模塊語句來分析哪些模塊被導入了:
// 只導入部分方法 import { unique, implode, explode } from "array-utils";
這個導入示例與前一個示例的區別在于,本示例只導入模塊的特定部分,而不是從“array-utils”模塊導入所有內容。
為了便于說明,這里有一個使用 webpack 的單頁應用程序示例來演示 Tree Shaking 是如何工作的。界面如下:
這個程序打包之后的代碼被分為兩文件,如下:
在任何應用程序中,你需要從靜態導入語句尋找 Tree Shaking 的機會,在示例程序中(FilterablePedalList.js)你將看到這樣一行導入語句:
import * as utils from "../../utils/utils";
在文件中這樣的導入語句應該引起你的注意,它的意思是:從 utils 模塊導入所有內容。問題是:你真的用到所有的內容了嗎?現在我們來檢查 FilterablePedalList.js 中究竟使用了 utils 模塊中的那些方法,通過檢索發現只使用了 utils.simpleSort:
if (this.state.sortBy === "model") { // Simple sort gets used here... json = utils.simpleSort(json, "model", this.state.sortOrder); } else if (this.state.sortBy === "type") { // ..and here... json = utils.simpleSort(json, "type", this.state.sortOrder); } else { // ..and here. json = utils.simpleSort(json, "manufacturer", this.state.sortOrder); }
我們現在開始做 Tree Shaking 優化
在大型應用中 Babel 是不可或缺的工具,但是它會讓 Tree Shaking 變得困難。如果你正在使用 babel-preset-env,它會自動為你將 ES6 模塊轉換為更廣泛兼容的 CommonJS 模塊,即:用 require 代替 import。對于 CommonJS 模塊而言做 Tree Shaking 優化非常困難,這是因為 CommonJS 模塊是動態的,在構建階段 bundlers 不容易分析出 CommonJS 模塊導出了什么和導入了什么。為了避免 babel-preset-env 將 ES6 模塊轉換成 CommonJS 模塊,我們可以這么做:
{ "presets": [ ["env", { "modules": false }] ] }
在你的 Babel -preset-env 配置中簡單指定"modules": false 就可以讓 Babel 按照我們想要的方式運行,這允許 webpack 分析你的依賴樹并擺脫那些未使用的依賴。
當函數修改了它作用域之外的內容,我們就認為這個函數有 side effects。side effects 也適用于ES6模塊,在你做 Tree Shaking 的時候你需要留意你的模塊是否有 side effects(副作用),如果模塊接受可預測的輸入,并輸出同樣可預測的輸出,而不修改其自身范圍之外的任何內容,我們就認為這個模塊沒有 side effects,對于沒有 side effects 的模塊你可以放心的做 Tree Shaking。在這里我舉兩個 side effects 例子:
import './index.module.scss'; import './assets/shoot.svg';
如果在某個模塊中出現了上面這樣的 import 語句,則認為這個模塊有 side effects,這時在做 Tree Shaking 的時候你需要小心一些。默認情況下,webpack 在做 Tree Shaking 的時候,會認為 index.module.scss 與 assets/shoot.svg 沒有被用到,所以它們會被移除,如果不想被移除,可以告訴 webpack 它們是 side effects:
{ "name": "webpack-tree-shaking-example", "version": "1.0.0", "sideEffects": [ "./index.module.scss", "./assets/shoot.svg" ] }
在項目的 package.json 中配置 sideEffects 字段。sideEffects 字段也能為 false,這表示項目中不存在有 side effects 的模塊。
現在我們已經告訴 babel 不要將 ES6 模塊轉成 CommonJS 模塊,現在我們需要對導入語法做一點微調,只從 utils 模塊中引入我們需要的函數嗎,在本指南的例子中,我們只需要 simpleSort:
import { simpleSort } from "../../utils/utils"; if (this.state.sortBy === "model") { json = simpleSort(json, "model", this.state.sortOrder); } else if (this.state.sortBy === "type") { json = simpleSort(json, "type", this.state.sortOrder); } else { json = simpleSort(json, "manufacturer", this.state.sortOrder); }
現在我們已經完成了 Tree Shaking 的工作,下面是 Tree Shaking 之前 webpack 打包生成的 js 包大小:
Asset Size Chunks Chunk Names js/vendors.16262743.js 37.1 KiB 0 [emitted] vendors js/main.797ebb8b.js 20.8 KiB 1 [emitted] main
下面是 Tree Shaking 之后 webpack 打包生成的 js 包大小:
Asset Size Chunks Chunk Names js/vendors.45ce9b64.js 36.9 KiB 0 [emitted] vendors js/main.559652be.js 8.46 KiB 1 [emitted] main
main 的文件大小下降比較明顯,這是因為 webpack 移除了不需要的 utils 方法。
在有些情況你按照上面的步驟進行 Tree Shaking,但是 webpack 還是將模塊的所有內容都打包到最終的 Chunk 中了,例如:lodash。
// 仍然會導入所有的內容 import { sortBy } from "lodash"; // 這只會導入 sortBy import sortBy from "lodash/sortBy";
如果你想要使用第一種寫法,那么你還需要安裝 babel-plugin-lodash。如果你使用了第三方庫,你可以看一下這個庫的導出是否使用了 ES6 語法,如果它的導出用的是 CommonJS 語法,例如:module.exports,那么 webpack 不能對它進行 Tree Shaking 優化。有些插件,例如:webpack-common-shake,提供了對 CommonJS 模塊進行 Tree Shaking 的能力,但是它有一些限制。
關于“JS加載性能Tree Shaking優化的方法是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“JS加載性能Tree Shaking優化的方法是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。