溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

webpack中使用tree-shaking的方法

發(fā)布時(shí)間:2021-02-22 10:36:24 來源:億速云 閱讀:143 作者:小新 欄目:web開發(fā)

這篇文章主要介紹webpack中使用tree-shaking的方法,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

1.什么是tree-shaking

webpack 2 的到來帶來的最棒的新特性之一就是tree-shaking 。tree-shaking源自于rollup.js,先如今,webpack 2也有類似的做法。

webpack 里的tree-shaking的到來不得不歸功于es6規(guī)范的模塊。為什么這么說,如今的前端模塊規(guī)范很多,比較出流行的比如commonJS , AMD , es6 ,我簡單的說一下commonJS和es6模塊的區(qū)別。

commonJS 模塊

commonJS的模塊規(guī)范在Node中發(fā)揚(yáng)光大,總的來說,它的特性有這幾個(gè):

1.動(dòng)態(tài)加載模塊

commonJS和es6的最大區(qū)別大概就在于此了吧,commonJS模塊的動(dòng)態(tài)加載能夠很輕松的實(shí)現(xiàn)懶加載,優(yōu)化用戶體驗(yàn)。

2.加載整個(gè)模塊

commonJS模塊中,導(dǎo)出的是整個(gè)模塊。

3.每個(gè)模塊皆為對(duì)象

commonJS模塊都被視作一個(gè)對(duì)象。

4.值拷貝

commonJS的模塊輸出和 函數(shù)的值傳遞相似,都是值的拷貝

es6 模塊

1.靜態(tài)解析

即在解析階段就確定輸出的模塊,所以es6模塊的import一般寫在被引入文件的開頭。

2.模塊不是對(duì)象

在es6里,每個(gè)模塊并不會(huì)當(dāng)做一個(gè)對(duì)象看待

3.加載的不是整個(gè)模塊

在es6模塊中經(jīng)常會(huì)看見一個(gè)模塊中有好幾個(gè)export 導(dǎo)出

4.模塊的引用

es6模塊中,導(dǎo)出的并不是模塊的值拷貝,而是這個(gè)模塊的引用

在結(jié)合es6模塊和commonJS模塊的區(qū)別之后,我們知道es6的特點(diǎn)是靜態(tài)解析,而commonJS模塊的特點(diǎn)是動(dòng)態(tài)解析的,因此,借于es6模塊的靜態(tài)解析,tree-shaking的實(shí)現(xiàn)才能成為可能。
在webpack中,tree-shaking指的就是按需加載,即沒有被引用的模塊不會(huì)被打包進(jìn)來,減少我們的包大小,縮小應(yīng)用的加載時(shí)間,呈現(xiàn)給用戶更佳的體驗(yàn)。

2.怎么使用tree-shaking

說了這么多那到底如何使用tree-shaking呢?
webpack默認(rèn)es6規(guī)范編寫的模塊都能使用tree-shaking。這是什么意思呢?下面來看個(gè)例子。

首先奉上我的demo目錄如下:

├─dist
    └─index.html
├─node_modules
    └─...
├─src
    ├─scripts
    ├─assets
├─webpack.config.js
└─package.json

dist用來存放打包好的代碼

src相反的用來存放源文件

src里的scripts目錄用來存放js腳本文件,assets用來存放靜態(tài)資源文件

以下幾條命令過后開始我們的tree-shaking之旅

npm install --save-dev webpack webpack-dev-server
webpack.config.js
const webpack = require('webpack')
const path = require('path')
module.exports = {
  entry:'./src/scripts/main.js',
  output:{
    path:path.resolve(__dirname,'dist/'),
    filename:'main.bundle.js'
  },
  plugins:[
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer:{
    port:4200,
    contentBase:path.resolve(__dirname,'dist/'),
    historyApiFallback:true,
    hot:true
  }
}

接下來是main.js,直接引入了sayHello

import { sayHello } from './greeter.ts';

sayHello();

相應(yīng)的main.js的依賴greeter.js

export function sayHello(){
  alert('hello')
}
export function sayWorld(){
  alert('world')
}

在dist目錄下有個(gè)index.html 用來引入打包后的bundle

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <script type="text/javascript" src="./main.bundle.js"></script>
</body>
</html>

以上就是整個(gè)demo的代碼,接下來的事情我們直接webpack打包試試看

去掉打包后冗長的代碼只看chunk傳參的部分:

[
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__person__ = __webpack_require__(1);
Object(__WEBPACK_IMPORTED_MODULE_0__person__["a" /* sayHello */])();
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return sayHello; });
/* unused harmony export sayWorld */
    function sayHello(){
        alert('hello');
    }
    function sayWorld(){
        alert('world');
    }
/***/ })
/******/ ]

我們關(guān)注這一行

/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return sayHello; });

實(shí)際上只return了一個(gè)sayHello。

因此我們現(xiàn)在只需要壓縮一下整個(gè)Js代碼,就能把沒引用的sayWorld剔除。

鍵入以下命令進(jìn)行壓縮

webpack --optimize-minimize

由于壓縮后的代碼只有一行了,我們移步尾部:

function(e,n,r){"use strict";function t(){alert("hello")}r.d(n,"a",function(){return t})}]);

可以看到sayWorld函數(shù)已經(jīng)被成功剔除。

我們啟動(dòng)webpack-dev-server

webpack-dev-server

在瀏覽器中輸入

http://localhost:4200

webpack中使用tree-shaking的方法

每次都需要在命令行里輸入?yún)?shù),豈不是很麻煩,還有沒有其他更好的辦法呢?

(1)我們可以把這串命令放入package.json的scripts字段,然后通過npm start來自動(dòng)執(zhí)行

(2)其實(shí)–optimize-minimize的底層實(shí)現(xiàn)是一個(gè)插件UglifyJsPlugin,因此,我們可以直接在webpack.config.js里配置它

在webpack.config.js里配置插件

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry:'./src/scripts/main.js',
  output:{
    filename:'main.bundle.js',
    path:path.join(__dirname,'dist')
  },
  plugins:[
    new webpack.optimize.UglifyJsPlugin(), // <----------- 壓縮js
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer:{
    port:4200,
    historyApiFallback:true,
    hot:true,
    contentBase:path.join(__dirname,"dist/")
  }
}

然后我們webpack打包

即看到同樣的效果

function(e,n,r){"use strict";function t(){alert("hello")}r.d(n,"a",function(){return t})}]);

在tree-shaking觸發(fā)打包后,僅僅是撇開了模塊的引用,但還是要結(jié)合壓縮工具來進(jìn)行,這才是完整的一次tree-shaking

那如果是typescript該怎么使用tree-shaking呢?

3.如何在typescript里使用tree-shaking

要在webpack里使用ts,首先我們必須安裝tsc

npm install --save-dev typescript

之后我們需要解析ts文件的loader

npm install --save-dev ts-loader

然后在webpack.config.js進(jìn)行配置

const webpack = require('webpack')
const path = require('path')
module.exports = {
  entry:'./src/scripts/main.ts',
  output:{
    path:path.resolve(__dirname,'dist/'),
    filename:'main.bundle.js'
  },
  module:{
    rules:[
      {
        test:/\.ts$/,
        use:['ts-loader']
      }
    ]
  },
  plugins:[
    new webpack.optimize.UglifyJsPlugin(),
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer:{
    port:4200,
    contentBase:path.resolve(__dirname,'dist/'),
    historyApiFallback:true,
    hot:true
  }
}

獻(xiàn)上我的兩份文件main.ts , greeter.ts (這兩份文件除了后綴名基本沒有改動(dòng))

main.ts

import { sayHello } from './greeter.ts';

sayHello();

greeter.ts

export var sayHello = function(){
  alert('hello')
}

export var sayWorld = function(){
  alert('world')
}

之后我們需要做的是,創(chuàng)建一個(gè)tsconfig.json的配置文件供tsc解析,這時(shí),坑來了。

下面是我的tsconfig.json文件

{
  "compilerOptions":{
    "target":"es5",
    "sourceMap":true
  },
  "exclude":[
    "./node_modules"
  ]
}

好像沒有什么不對(duì)

接著我們webpack

看下打包壓縮后的代碼的最后一部分:

"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sayHello=function(){alert("hello")},n.sayWorld=function(){alert("world")}}]);

sayWorld居然還是存在!??!怎么回事,為什么沒有被觸發(fā)tree-shaking優(yōu)化?

這是因?yàn)閠sc編譯后的代碼為es5 ,而正因如此,tsc默認(rèn)使用了commonJS的規(guī)范來加載模塊,因此并沒有觸發(fā)tree-shaking,那我們要怎么做?

修改一下tsconfig.json,把target改為es6即可!

{
  "compilerOptions":{
    "target":"es6",
    "sourceMap":true
  },
  "exclude":[
    "./node_modules"
  ]
}

再次打包

看一下打包后的bundle

function(e,n,r){"use strict";r.d(n,"a",function(){return t});var t=function({alert("hello")}}]);

果然是觸發(fā)了tree-shaking

開啟webpack-dev-server

webpack-dev-server

可以看到成功打印hello

webpack中使用tree-shaking的方法

以上是“webpack中使用tree-shaking的方法”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI