最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Webpack之tree-starking 解析

 更新時間:2018年09月11日 14:04:54   作者:pandashen  
這篇文章主要介紹了Webpack之tree-starking 解析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

tree-sharking 簡介

tree-sharking 是 Webpack 2 后續(xù)版本的優(yōu)化功能,顧名思義,就是將多余的代碼給 “搖晃” 掉,在開發(fā)中我們經(jīng)常使用一些第三方庫,而這些第三方庫只使用了這個庫的一部門功能或代碼,未使用的代碼也要被打包進(jìn)來,這樣出口文件會非常大,tree-sharking 幫我們解決了這個問題,它可以將各個模塊中沒有使用的方法過濾掉,只對有效代碼進(jìn)行打包。

AST 語法樹分析

假設(shè)我們現(xiàn)在使用了 ElementUI 庫的兩個組件,通常會使用解構(gòu)賦值來引入。

優(yōu)化前

import { Button, Alert } from "element-ui";

這樣引用資源, Webpack 在打包的時候會找到 element-ui 并把里面所有的代碼全部打包到出口文件,我們只使用了兩個組件,全部打包不是我們所希望的,tree-sharking 是通過在 Webpack 中配置 babel-plugin-import 插件來實現(xiàn)的,它可以將解構(gòu)的代碼轉(zhuǎn)換成下面的形式。

優(yōu)化后

import Button from "element-ui/lib/button";
import Alert from "element-ui/lib/Alert";

轉(zhuǎn)化后會去 node_modules 中的 element-ui 模塊找到 Button 和 Alert 兩個組件對應(yīng)的文件,并打包到出口文件中。

通過上面的轉(zhuǎn)換可以看出,其實 tree-sharking 的實現(xiàn)原理是通過改變 AST 語法樹的結(jié)構(gòu)來實現(xiàn)的,我們可以通過在線轉(zhuǎn)換網(wǎng)站 http://esprima.org/demo/parse.html 將 JS 代碼裝換成 AST 語法樹。

優(yōu)化前的 AST 語法樹

 {
  "type": "Program",
  "body": [
    {
      "type": "ImportDeclaration",
      "specifiers": [
        {
          "type": "ImportSpecifier",
          "local": {
            "type": "Identifier",
            "name": "Button"
          },
          "imported": {
            "type": "Identifier",
            "name": "Button"
          }
        },
        {
          "type": "ImportSpecifier",
          "local": {
            "type": "Identifier",
            "name": "Alert"
          },
          "imported": {
            "type": "Identifier",
            "name": "Alert"
          }
        }
      ],
      "source": {
        "type": "Literal",
        "value": "element-ui",
        "raw": "\"element-ui\""
      }
    }
  ],
  "sourceType": "module"
}

優(yōu)化后的 AST 語法樹

 {
  "type": "Program",
  "body": [
    {
      "type": "ImportDeclaration",
      "specifiers": [
        {
          "type": "ImportDefaultSpecifier",
          "local": {
            "type": "Identifier",
            "name": "Button"
          }
        }
      ],
      "source": {
        "type": "Literal",
        "value": "element-ui/lib/button",
        "raw": "\"element-ui/lib/button\""
      }
    },
    {
      "type": "ImportDeclaration",
      "specifiers": [
        {
          "type": "ImportDefaultSpecifier",
          "local": {
            "type": "Identifier",
            "name": "Alert"
          }
        }
      ],
      "source": {
        "type": "Literal",
        "value": "element-ui/lib/Alert",
        "raw": "\"element-ui/lib/Alert\""
      }
    }
  ],
  "sourceType": "module"
}

從上面的語法樹對比,可以看出在優(yōu)化前 body 里面只有一個對象,使用的組件信息存在 specifiers 里,source 指向了 element-ui,而在優(yōu)化后,將兩個組件分別拆成了兩個對象存在 body 中,每個對象的的 specifiers 只存儲一個組件,并在 source 里面指向了當(dāng)前組件對應(yīng)的路徑。

模擬 tree-starking

既然我們已經(jīng)清楚要修改語法樹的位置,下面就使用 AST 來模擬 tree-sharking 功能,對語法樹的操作是依賴于 babel-core 和 babel-types 兩個核心模塊的,下面先安裝依賴。

npm install babel-core babel-types

文件:babel-plugin-my-import.js

const babel = require("babel-core");
const types = require("babel-types");

let code = `import { Button, Alert } from "element-ui"`;

let importPlugin = {
  visitor: {
    ImportDeclaration(path) {
      let node = path.node;
      let source = node.source.value;
      let specifiers = node.specifiers;

      // 判斷是否是默認(rèn)導(dǎo)出,其中一個不是默認(rèn)導(dǎo)出,則都不是默認(rèn)導(dǎo)出
      if (!types.isImportDefaultSpecifier(specifiers[0])) {
        // 如果不是默認(rèn)導(dǎo)出,則需要轉(zhuǎn)換
        specifiers = specifiers.map(specifier => {
          // 數(shù)組內(nèi)容:當(dāng)前默認(rèn)導(dǎo)出的標(biāo)識、從哪里導(dǎo)入
          return types.importDeclaration(
            [types.importDefaultSpecifier(specifier.local)],
            types.stringLiteral(`${source}/lib/${specifier.local.name.toLowerCase()}`)
          );
        });

        // 替換樹結(jié)構(gòu)
        path.replaceWithMultiple(specifiers);
      }
    }
  }
};

let result = babel.transform(code, {
  plugins: [importPlugin]
});

console.log(result.code);

// import Button from "element-ui/lib/button";
// import Alert from "element-ui/lib/alert";

通過上面的代碼可以發(fā)現(xiàn)我們使用 babel-core 和 babel-types 兩個模塊的核心方法對語法書進(jìn)行了遍歷、修改和替換,更詳細(xì)的 API 可以查看 https://github.com/babel/babel/tree/6.x/packages/babel-types。

結(jié)合 Webpack 使用插件

前面只是驗證了 tree-sharking 中 JS 語法的轉(zhuǎn)換過程,接下來將上面的代碼轉(zhuǎn)換成插件配合 Webpack 使用,來徹底感受 tree-sharking 的工作過程。

文件:~node_modules/babel-plugin-my-import.js

const babel = require("babel-core");
const types = require("babel-types");

let importPlugin = {
  visitor: {
    ImportDeclaration(path) {
      let node = path.node;
      let source = node.source.value;
      let specifiers = node.specifiers;

      // 判斷是否是默認(rèn)導(dǎo)出,其中一個不是默認(rèn)導(dǎo)出,則都不是默認(rèn)導(dǎo)出
      if (!types.isImportDefaultSpecifier(specifiers[0])) {
        // 如果不是默認(rèn)導(dǎo)出,則需要轉(zhuǎn)換
        specifiers = specifiers.map(specifier => {
          // 數(shù)組內(nèi)容:當(dāng)前默認(rèn)導(dǎo)出的標(biāo)識、從哪里導(dǎo)入
          return types.importDeclaration(
            [types.importDefaultSpecifier(specifier.local)],
            types.stringLiteral(`${source}/lib/${specifier.local.name.toLowerCase()}`)
          );
        });

        // 替換樹解構(gòu)
        path.replaceWithMultiple(specifiers);
      }
    }
  }
};

module.exports = importPlugin;

上面刪掉了多余的測試代碼,將模塊中的 importPlugin 插件導(dǎo)出,并把 babel-plugin-my-import.js 移入了 node_modules 當(dāng)中。

接下來安裝需要的依賴:

npm install webpack webpack-cli babel-loader babel-presets-env
npm install vue element-ui --save

安裝完依賴,寫一個要編譯的文件,使用 Webpack 進(jìn)行打包,查看使用插件前和使用插件后出口文件的大小。

文件:import.js

import Vue from "vue";
import { Button, Alert } from "element-ui";

下面來寫一個簡單的 Webpack 配置文件。

文件:webpcak.config.js

module.exports = {
  mode: "development",
  entry: "import.js",
  output: {
    filename: "bundle.js",
    path: __dirname
  },
  module: {
    rules: [{
      test: /\.js$/,
      use: {
        loader: "babel-loader",
        options: {
          presets: [
            "env",
          ],
          plugins: [
            // 插件:不使用插件打包注釋掉該行即可
            ["my-import", { libararyName: "element-ui" }]
          ]
        }
      },
      exclude: /node_modules/
    }]
  }
};

為了防止 babel 相關(guān)的依賴升級 7.0 后出現(xiàn)一些問題導(dǎo)致 Webpack 無法啟動,再此貼出 package.json 文件,按照對應(yīng)版本下載依賴保證上面 Webpack 配置生效。

文件:package.json

{
 "name": "ast-lesson",
 "version": "1.0.0",
 "description": "tree-starking",
 "main": "index.js",
 "scripts": {
  "test": "echo \"Error: no test specified\" && exit 1"
 },
 "keywords": [],
 "author": "",
 "license": "ISC",
 "dependencies": {
  "babel-core": "^6.26.3",
  "babel-loader": "^7.1.5",
  "babel-preset-env": "^1.7.0",
  "babel-types": "^6.26.0",
  "escodegen": "^1.10.0",
  "esprima": "^4.0.0",
  "estraverse": "^4.2.0",
  "webpack": "^4.16.0",
  "webpack-cli": "^3.0.8"
 },
 "devDependencies": {
  "vue": "^2.5.17",
  "element-ui": "^2.4.6"
 }
}

對比使用插件前后的出口文件

接下來分別在使用插件和不使用插件時執(zhí)行打包命令,查看出口文件 bondle.js 的大小。

npx webpack

使用 babel-plugin-my-import 前:

使用 babel-plugin-my-import 后:

通過對比,可以看到使用 tree-sharking 即我們自己實現(xiàn)的 babel-plugin-my-import 插件后,打包的出口文件大大減小,其原因是將引入第三方庫沒有使用的代碼全都過濾掉了,只打包了有效代碼。

總結(jié)

上面對 Webpack 的 tree-sharking 進(jìn)行了分析,并模擬 babel-plugin-import 簡易的實現(xiàn)了一版 tree-sharking 的優(yōu)化插件,這個過程中相信大家已經(jīng)了解了 tree-sharking 的原理以及實現(xiàn)類似插件的思路,并已經(jīng)具備了開發(fā)類似插件的基本條件,最后還有一點需要補充,tree-sharking 優(yōu)化的方式是根據(jù) ES6 語法 import “靜態(tài)” 引入的特性實現(xiàn)的,如果要說 tree-sharking 很強大,還不如說 ES6 模塊化規(guī)范 “靜態(tài)” 引入的特性強大,正由于是基于 “靜態(tài)” 引入,所以目前 tree-sharking 只支持遍歷一層 import 關(guān)鍵字。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Javascript中的相等與不等運算

    Javascript中的相等與不等運算

    在 javascript 中,可以使用 == 來比較兩個數(shù)據(jù)是否相等,如果兩個數(shù)據(jù)的類型不同,那么,將在進(jìn)行轉(zhuǎn)換后進(jìn)行比較
    2010-04-04
  • JavaScript的console命令使用實例

    JavaScript的console命令使用實例

    這篇文章主要介紹了javascript的console命令使用實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • 如何使用ImageDecoder API讓GIF圖片暫停播放

    如何使用ImageDecoder API讓GIF圖片暫停播放

    在本文中,我們介紹了如何使用ImageDecoder API來暫停GIF圖像的播放,雖然這需要一些JavaScript編程知識,但它是一個非常強大的技術(shù),可以讓您對GIF圖像進(jìn)行各種高級操作,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • JavaScript表單驗證實現(xiàn)過程詳解

    JavaScript表單驗證實現(xiàn)過程詳解

    表單校驗是注冊環(huán)節(jié)中必不可少的操作,表單校驗通過一定的規(guī)則來確保用戶提交數(shù)據(jù)的有效性,下面這篇文章主要給大家介紹了關(guān)于el-form表單驗證的一些實用方法,需要的朋友可以參考下
    2023-01-01
  • JavaScript中正則表達(dá)式的實際應(yīng)用詳解

    JavaScript中正則表達(dá)式的實際應(yīng)用詳解

    這篇文章主要給大家介紹了關(guān)于JavaScript中正則表達(dá)式實際應(yīng)用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 基于mouseout和mouseover等類似事件的冒泡問題解決方法

    基于mouseout和mouseover等類似事件的冒泡問題解決方法

    這篇文章主要介紹了關(guān)于mouseout和mouseover等類似事件的冒泡問題解決方法。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-11-11
  • parseInt parseFloat js字符串轉(zhuǎn)換數(shù)字

    parseInt parseFloat js字符串轉(zhuǎn)換數(shù)字

    轉(zhuǎn)換函數(shù)、強制類型轉(zhuǎn)換、利用js變量弱類型轉(zhuǎn)換。
    2010-08-08
  • layui前端時間戳轉(zhuǎn)化實例

    layui前端時間戳轉(zhuǎn)化實例

    今天小編就為大家分享一篇layui前端時間戳轉(zhuǎn)化實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • JS 實現(xiàn)完美include載入實現(xiàn)代碼

    JS 實現(xiàn)完美include載入實現(xiàn)代碼

    在寫這個之前在網(wǎng)上搜索了些資料,發(fā)現(xiàn)以前寫的include都存在2個問題,這也是include需要解決的比較重要的2個問題。
    2010-08-08
  • JavaScript 正則表達(dá)式中g(shù)lobal模式的特性

    JavaScript 正則表達(dá)式中g(shù)lobal模式的特性

    這篇文章主要介紹了JavaScript 正則表達(dá)式中g(shù)lobal模式的特性 的相關(guān)資料,需要的朋友可以參考下
    2016-02-02

最新評論

白水县| 翼城县| 尖扎县| 华容县| 鄯善县| 通州市| 河津市| 沙田区| 柏乡县| 拉孜县| 驻马店市| 洪雅县| 新干县| 绥芬河市| 宁晋县| 贵定县| 石首市| 木兰县| 黔东| 怀化市| 乌审旗| 昭平县| 武宣县| 扎赉特旗| 汉中市| 阳春市| 进贤县| 泽普县| 吉安县| 黑水县| 台湾省| 安福县| 郁南县| 青龙| 新干县| 什邡市| 成安县| 赣榆县| 舞钢市| 湾仔区| 白城市|