欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS?加載性能Tree?Shaking優(yōu)化詳解

 更新時(shí)間:2022年11月14日 11:38:54   作者:何遇er  
這篇文章主要為大家介紹了JS?加載性能Tree?Shaking優(yōu)化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

隨著 web 應(yīng)用復(fù)雜性增加,JS 代碼文件的大小也在不斷的攀升,截住 2021年9月,在 httparchive 上有統(tǒng)計(jì)顯示——在移動(dòng)設(shè)備上 JS 傳輸大小大約為 447 KB,桌面端 JS 傳輸大小大約為 495 KB,注意這僅僅是在網(wǎng)絡(luò)中傳輸?shù)?JS 文件大小,JS 的實(shí)際大小要比傳輸大小大很多。

上圖是下載和運(yùn)行JavaScript的過(guò)程。

即使 JS 的傳輸大小被壓縮為 300 KB,但仍然有 900 KB 的 JS 代碼需要被瀏覽器解析、編譯和執(zhí)行。圖像一旦被下載,瀏覽器只需要花費(fèi)相對(duì)瑣碎的解碼時(shí)間,與圖像不同的是,JS 必須被解析、編譯,最終執(zhí)行,這使得處理 JS 比處理其他類型的資源更耗時(shí)。

上圖是瀏覽器解析/編譯 170 KB的 JS 的處理成本與同等大小的 JPEG 的解碼時(shí)間。JS 引擎的性能在不斷被改進(jìn),改進(jìn)網(wǎng)站 JS 性能也是開(kāi)發(fā)者要做的事情。Code Splitting 是優(yōu)化 JS 性能的技術(shù)之一,但是它不能減少應(yīng)用程序的 JS 代碼的總大小,在這里我們使用 Tree Shaking 來(lái)減小 js 代碼的大小。

什么是 Tree Shaking

您可以將應(yīng)用程序想象成一棵樹(shù)。您實(shí)際使用的源代碼和庫(kù)表示樹(shù)中綠色的活葉子,死代碼表示秋天時(shí)樹(shù)上棕色的枯葉,為了除掉枯葉,你必須搖動(dòng)樹(shù),讓它們掉下。Tree Shaking 是指消除死代碼,下面通過(guò)一個(gè)應(yīng)用程序演示了這個(gè)概念。使用 ES6 靜態(tài)模塊語(yǔ)法導(dǎo)入依賴項(xiàng):

// 在這里導(dǎo)入了所有的數(shù)組處理方法
import arrayUtils from "array-utils";

在應(yīng)用最初的時(shí)候,依賴項(xiàng)可能很少,隨著功能逐漸增加,依賴項(xiàng)也會(huì)增加,更糟糕的是,舊的依賴項(xiàng)不再使用,但可能不會(huì)從代碼庫(kù)中刪除,最終的結(jié)果是,應(yīng)用程序帶有大量未使用的 JS 代碼,Tree Shaking 解決了這個(gè)問(wèn)題,它通過(guò)分析我們?cè)谖募惺褂玫?ES6 靜態(tài)模塊語(yǔ)句來(lái)分析哪些模塊被導(dǎo)入了:

// 只導(dǎo)入部分方法
import { unique, implode, explode } from "array-utils";

這個(gè)導(dǎo)入示例與前一個(gè)示例的區(qū)別在于,本示例只導(dǎo)入模塊的特定部分,而不是從“array-utils”模塊導(dǎo)入所有內(nèi)容。

尋找 Tree Shaking 的機(jī)會(huì)

為了便于說(shuō)明,這里有一個(gè)使用 webpack 的單頁(yè)應(yīng)用程序示例來(lái)演示 Tree Shaking 是如何工作的。界面如下:

這個(gè)程序打包之后的代碼被分為兩文件,如下:

在任何應(yīng)用程序中,你需要從靜態(tài)導(dǎo)入語(yǔ)句尋找 Tree Shaking 的機(jī)會(huì),在示例程序中(FilterablePedalList.js)你將看到這樣一行導(dǎo)入語(yǔ)句:

import * as utils from "../../utils/utils";

在文件中這樣的導(dǎo)入語(yǔ)句應(yīng)該引起你的注意,它的意思是:從 utils 模塊導(dǎo)入所有內(nèi)容。問(wèn)題是:你真的用到所有的內(nèi)容了嗎?現(xiàn)在我們來(lái)檢查 FilterablePedalList.js 中究竟使用了 utils 模塊中的那些方法,通過(guò)檢索發(fā)現(xiàn)只使用了 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);
}

我們現(xiàn)在開(kāi)始做 Tree Shaking 優(yōu)化

防止 Babel 將 ES6 模塊轉(zhuǎn)換為 CommonJS 模塊

在大型應(yīng)用中 Babel 是不可或缺的工具,但是它會(huì)讓 Tree Shaking 變得困難。如果你正在使用 babel-preset-env,它會(huì)自動(dòng)為你將 ES6 模塊轉(zhuǎn)換為更廣泛兼容的 CommonJS 模塊,即:用 require 代替 import。對(duì)于 CommonJS 模塊而言做 Tree Shaking 優(yōu)化非常困難,這是因?yàn)?CommonJS 模塊是動(dòng)態(tài)的,在構(gòu)建階段 bundlers 不容易分析出 CommonJS 模塊導(dǎo)出了什么和導(dǎo)入了什么。為了避免 babel-preset-env 將 ES6 模塊轉(zhuǎn)換成 CommonJS 模塊,我們可以這么做:

{
  "presets": [
    ["env", {
      "modules": false
    }]
  ]
}

在你的 Babel -preset-env 配置中簡(jiǎn)單指定"modules": false 就可以讓 Babel 按照我們想要的方式運(yùn)行,這允許 webpack 分析你的依賴樹(shù)并擺脫那些未使用的依賴。

留意 side effects

當(dāng)函數(shù)修改了它作用域之外的內(nèi)容,我們就認(rèn)為這個(gè)函數(shù)有 side effects。side effects 也適用于ES6模塊,在你做 Tree Shaking 的時(shí)候你需要留意你的模塊是否有 side effects(副作用),如果模塊接受可預(yù)測(cè)的輸入,并輸出同樣可預(yù)測(cè)的輸出,而不修改其自身范圍之外的任何內(nèi)容,我們就認(rèn)為這個(gè)模塊沒(méi)有 side effects,對(duì)于沒(méi)有 side effects 的模塊你可以放心的做 Tree Shaking。在這里我舉兩個(gè) side effects 例子:

import './index.module.scss';
import './assets/shoot.svg';

如果在某個(gè)模塊中出現(xiàn)了上面這樣的 import 語(yǔ)句,則認(rèn)為這個(gè)模塊有 side effects,這時(shí)在做 Tree Shaking 的時(shí)候你需要小心一些。默認(rèn)情況下,webpack 在做 Tree Shaking 的時(shí)候,會(huì)認(rèn)為 index.module.scss 與 assets/shoot.svg 沒(méi)有被用到,所以它們會(huì)被移除,如果不想被移除,可以告訴 webpack 它們是 side effects:

{
  "name": "webpack-tree-shaking-example",
  "version": "1.0.0",
  "sideEffects": [
    "./index.module.scss",
    "./assets/shoot.svg"
  ]
}

在項(xiàng)目的 package.json 中配置 sideEffects 字段。sideEffects 字段也能為 false,這表示項(xiàng)目中不存在有 side effects 的模塊。

只導(dǎo)入你需要的

現(xiàn)在我們已經(jīng)告訴 babel 不要將 ES6 模塊轉(zhuǎn)成 CommonJS 模塊,現(xiàn)在我們需要對(duì)導(dǎo)入語(yǔ)法做一點(diǎn)微調(diào),只從 utils 模塊中引入我們需要的函數(shù)嗎,在本指南的例子中,我們只需要 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);
}

現(xiàn)在我們已經(jīng)完成了 Tree Shaking 的工作,下面是 Tree Shaking 之前 webpack 打包生成的 js 包大?。?/p>

                 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 的文件大小下降比較明顯,這是因?yàn)?webpack 移除了不需要的 utils 方法。

更復(fù)雜的情況

在有些情況你按照上面的步驟進(jìn)行 Tree Shaking,但是 webpack 還是將模塊的所有內(nèi)容都打包到最終的 Chunk 中了,例如:lodash。

// 仍然會(huì)導(dǎo)入所有的內(nèi)容
import { sortBy } from "lodash";
// 這只會(huì)導(dǎo)入 sortBy
import sortBy from "lodash/sortBy";

如果你想要使用第一種寫(xiě)法,那么你還需要安裝 babel-plugin-lodash。如果你使用了第三方庫(kù),你可以看一下這個(gè)庫(kù)的導(dǎo)出是否使用了 ES6 語(yǔ)法,如果它的導(dǎo)出用的是 CommonJS 語(yǔ)法,例如:module.exports,那么 webpack 不能對(duì)它進(jìn)行 Tree Shaking 優(yōu)化。有些插件,例如:webpack-common-shake,提供了對(duì) CommonJS 模塊進(jìn)行 Tree Shaking 的能力,但是它有一些限制

總結(jié)

為了確保構(gòu)建工具可以成功地優(yōu)化你的應(yīng)用程序,應(yīng)該避免依賴 CommonJS 模塊,并在整個(gè)應(yīng)用程序中使用 ES6 模塊語(yǔ)法。

以上就是JS 加載性能Tree Shaking優(yōu)化詳解的詳細(xì)內(nèi)容,更多關(guān)于JS 加載Tree Shaking的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Prototype框架詳解

    Prototype框架詳解

    Prototype是一個(gè)JavaScript框架,旨在簡(jiǎn)化動(dòng)態(tài)Web應(yīng)用程序的開(kāi)發(fā)。原型被稱為作為一個(gè)單一的文件分發(fā)的prototype.js,本文給大家介紹prototype框架,感興趣的朋友一起學(xué)習(xí)吧
    2015-11-11
  • inquirer.js一個(gè)用戶與命令行交互的工具詳解

    inquirer.js一個(gè)用戶與命令行交互的工具詳解

    這篇文章主要介紹了inquirer.js一個(gè)用戶與命令行交互的工具詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • JS選取DOM元素的簡(jiǎn)單方法

    JS選取DOM元素的簡(jiǎn)單方法

    下面小編就為大家?guī)?lái)一篇JS選取DOM元素的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-07-07
  • 動(dòng)態(tài)加載外部javascript文件的函數(shù)代碼分享

    動(dòng)態(tài)加載外部javascript文件的函數(shù)代碼分享

    動(dòng)態(tài)加載外部javascript文件的函數(shù)代碼分享,做個(gè)記錄備忘,方便查找。
    2011-07-07
  • js 在定義的時(shí)候立即執(zhí)行的函數(shù)表達(dá)式(function)寫(xiě)法

    js 在定義的時(shí)候立即執(zhí)行的函數(shù)表達(dá)式(function)寫(xiě)法

    如果不需要顯示調(diào)用函數(shù), 讓這個(gè)函數(shù)在定義的時(shí)候就執(zhí)行的話, 該如何寫(xiě)才可以呢,接下來(lái)將詳細(xì)介紹實(shí)現(xiàn)步驟,感興趣的朋友可以了解下
    2013-01-01
  • JavaScript常見(jiàn)的函數(shù)中的屬性與方法總結(jié)

    JavaScript常見(jiàn)的函數(shù)中的屬性與方法總結(jié)

    當(dāng)定義和調(diào)用函數(shù)時(shí),JavaScript?函數(shù)對(duì)象會(huì)自動(dòng)具有一些特定的屬性,本文為大家總結(jié)了一些常見(jiàn)的屬性和方法,感興趣的小伙伴可以了解一下
    2023-05-05
  • Bootstrap基本組件學(xué)習(xí)筆記之列表組(11)

    Bootstrap基本組件學(xué)習(xí)筆記之列表組(11)

    這篇文章主要為大家詳細(xì)介紹了Bootstrap基本組件學(xué)習(xí)筆記之列表組,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • JS常見(jiàn)疑難點(diǎn)分析之match,charAt,charCodeAt,map,search用法分析

    JS常見(jiàn)疑難點(diǎn)分析之match,charAt,charCodeAt,map,search用法分析

    這篇文章主要介紹了JS常見(jiàn)疑難點(diǎn)分析之match,charAt,charCodeAt,map,search用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了match,charAt,charCodeAt,map,search的功能,使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2016-12-12
  • javascript跑馬燈抽獎(jiǎng)實(shí)例講解

    javascript跑馬燈抽獎(jiǎng)實(shí)例講解

    這篇文章主要為大家介紹了javascript跑馬燈抽獎(jiǎng)特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-01-01
  • 使用uniapp實(shí)現(xiàn)發(fā)布朋友圈功能

    使用uniapp實(shí)現(xiàn)發(fā)布朋友圈功能

    這篇文章主要介紹了使用uniapp實(shí)現(xiàn)發(fā)布朋友圈功能,在文章底部給大家介紹了uniapp?微信小程序分享、分享朋友圈功能,通過(guò)頁(yè)內(nèi)自定義分享按鈕,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09

最新評(píng)論