溫馨提示×

溫馨提示×

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

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

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

發(fā)布時間:2020-07-28 11:41:03 來源:網(wǎng)絡(luò) 閱讀:1148 作者:powertoolsteam 欄目:web開發(fā)

轉(zhuǎn)載請注明出處:葡萄城官網(wǎng),葡萄城為開發(fā)者提供專業(yè)的開發(fā)工具、解決方案和服務(wù),賦能開發(fā)者。
原文出處:https://wanago.io/2018/06/04/code-splitting-with-splitchunksplugin-in-webpack-4/

Webpack 4 給我們帶來了一些變化。其中包括更快地打包,引入了SplitChunksPlugin,并淘汰掉之前的CommomsChunksPlugin。在本文,你將學(xué)習(xí)如何拆分輸出代碼以提高應(yīng)用的性能。

代碼分離的思想

先說重要的:在Webpack中,到底什么是代碼分離?代碼分離允許你把代碼拆分到多個文件中。如果使用得當(dāng),你的應(yīng)用性能會提高很多。因為瀏覽器能緩存你的代碼。

每當(dāng)你做出一次修改,包含修改的文件需要被所有訪問你網(wǎng)站的人重新下載。但你并不會經(jīng)常修改應(yīng)用的依賴庫(譯者注:你常修改的是你的業(yè)務(wù)邏輯)。如果你能把那些依賴庫拆分到完全分離的文件中,即使業(yè)務(wù)邏輯發(fā)生了更改,訪問者也不需要再次下載依賴庫,直接使用之前的緩存就可以了。

使用Webpack時,你會得到一個或多個生成的輸出文件,這些文件包含了我們源碼的最終輸出。而它們由代碼塊(chunks)組成。

入口(Entry)

入口定義了我們代碼中應(yīng)用是從哪里開始執(zhí)行的,這也是Webpack開始打包的地方。你可以定義一個入口(常見于單頁應(yīng)用),或者多個入口(常見于多頁應(yīng)用)。

定義一個入口,就會得到一個chunk。如果你只使用字符串定義一個入口,那么這個chunk名為main。如果你使用對象定義了多個入口,那么它們會以entry對象的屬性來命名。下面的例子會得到相同的chunk:

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

// 例1
entry: './src/index.js'
// 例2
entry: {
  main: './src/index.js'
}

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

輸出(Output)

在配置文件中,輸出配置是一個對象,它指明了Webpack應(yīng)該在哪兒和如何對我們的打包結(jié)果和資源進行輸出。雖然可能有多個入口,但是只能有一個輸出配置對象。而chunk名稱的用處,就在于根據(jù)入口對應(yīng)不同的輸出。你可以為我們的打包輸出定義一個固定的文件名,但若想代碼分離,就不應(yīng)該這么做。你可以使用[name]為我們的輸出文件創(chuàng)建文件名的模板:

output: {
  filename: '[name].[chunkhash].bundle.js',
  path: path.resolve(__dirname, 'dist')
}

一件值得注意的重要東西是[chunkhash]:它是一個基于文件內(nèi)容的屬于特定chunk的哈希值。它僅會隨著文件內(nèi)容的改變而改變。因此,瀏覽器就可以利用這一點來緩存它。如果打包輸出的文件名變了,瀏覽器就知道自己需要重新下載它。一個chunkhash可能長這樣:0c553ebfd158e16da428。

我們的主chunk會被打包進一個叫main.[chunkhash].bundle.js的文件。

SplitChunksPlugin

由于有了SplitChunksPlugin,你可以把應(yīng)用中的特定部分移至不同文件。如果一個模塊在不止一個chunk中被使用,那么利用代碼分離,該模塊就可以在它們之間很好地被共享。這是Webpack的默認行為。

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

// utilities/users.js
export default [
  { firstName: "Adam", age: 28 },
  { firstName: "Jane", age: 24 },
  { firstName: "Ben",  age: 31 },
  { firstName: "Lucy", age: 40 }
]
// a.js
import _ from 'lodash';
import users from './users';

const adam = _.find(users, { firstName: 'Adam' });
// b.js
import _ from 'lodash';
import users from './users';

const lucy = _.find(users, { firstName: 'Lucy' });
// webpack.config.js
module.exports = {
  entry: {
    a: "./src/a.js",
    b: "./src/b.js"
  },
  output: {
    filename: "[name].[chunkhash].bundle.js",
    path: __dirname + "/dist"
  }
};

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

如果運行它,你會看到Webpack創(chuàng)建了兩個文件:a.[chunkhash].bundle.js和b.[chunkhash].bundle.js,而且每一個文件都包含對lodash庫的拷貝:這并不好!我之前說過,為共享的庫創(chuàng)建分離的文件是Webpack的一個默認行為,但這只涉及異步的chunk,即意味著只作用于我們異步引入的那些文件。我們會在介紹懶加載的時候討論這個話題。為了使這個默認行為能支持所有類型的chunks,我們需要稍微改一下Webpack的配置:

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

// webpack.config.js
module.exports = {
  entry: {
    a: "./src/a.js",
    b: "./src/b.js"
  },
  output: {
    filename: "[name].[chunkhash].bundle.js",
    path: __dirname + "/dist"
  },
  optimization: {
    splitChunks: {
      chunks: "all"
    }
  },
};

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

現(xiàn)在我們看到,創(chuàng)建了額外的vendors~a~b.[chunkhash].bundle.js文件,它包含了lodash庫的代碼。這是因為我們默認有一些cacheGroups配置:

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

splitChunks: {
  chunks: "all",
  cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      priority: -10
    },
    default: {
      minChunks: 2,
      priority: -20,
      reuseExistingChunk: true
    }
  }
}

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

首先,是vendors,它包含的文件來自于你node_modules。再者,是所有其他共享模塊的默認緩存組。這里有一個小點:有一些冗余。a.[chunkhash].bundle.js和b.[chunkhash].bundle.js都包含了users.js的內(nèi)容。這是因為,SplitChunksPlugin默認地只會分離大于30Kb的文件。我們可以輕松地修改它:

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

// webpack.config.js
module.exports = {
  entry: {
    a: "./src/a.js",
    b: "./src/b.js"
  },
  output: {
    filename: "[name].[chunkhash].bundle.js",
    path: __dirname + "/dist"
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 0 // 修改了這里
    }
  }
};

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

結(jié)果是,它新創(chuàng)建了屬于默認緩存組的名為a~b.[chunkhash].bundle.js的文件。因為我們的users.js文件所占空間遠遠小于30Kb,在沒有修改minSize屬性的情況下,它不會被打包到單獨的分離文件。在真實環(huán)境下,這是一件好事,因為這樣不會帶來實質(zhì)的性能提升,反而會強制瀏覽器為分離出的文件(它現(xiàn)在是很小的)再發(fā)一次額外的請求。

我們可以進一步,為僅在utilities目錄下的做特殊處理:

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    a: "./src/a.js",
    b: "./src/b.js"
  },
  output: {
    filename: "[name].[chunkhash].bundle.js",
    path: __dirname + "/dist"
  },
  optimization: {
    splitChunks: {
      chunks: "all",
      cacheGroups: {
        utilities: {
          test: /[\\/]src[\\/]utilities[\\/]/,
          minSize: 0
        }
      }
    }
  }
};

Webpack 4教程 - 第四部分,使用SplitChunksPlugin分離代碼

這樣我們的輸出包含4個文件:a.[chunkhash].bundle.js,b.[chunkhash].bundle.js,vendors~a~b.[chunkhash].bundle.js和utilities~a~b.[chunkhash].bundle.js。(譯者注:這需要在打包之前,把users.js文件移至./src/utilities目錄下,并修改a.js和b.js中的相關(guān)引用路徑)。雖然我們現(xiàn)在可以讓minSize:0成為全局設(shè)置(即放在splitChunks對象中作為其屬性),但即使這樣,默認的緩存組也不會被創(chuàng)建。因為,所有可能被引入的文件都應(yīng)該在我們剛創(chuàng)建的utilities組下。這個組具的優(yōu)先級是0,高于默認緩存組的優(yōu)先級。你可能已經(jīng)注意到了,默認緩存組的優(yōu)先級被設(shè)置為了-20。

還有其他的配置供你使用,可查看SplitChunksPlugin文檔。

總結(jié)

即使你只有一個入口(常發(fā)生于大多數(shù)單頁應(yīng)用中),把你的依賴放入一個獨立的文件依然是個好主意。這其實很容易做到,因為使用SplitChunksPlugin是Webpack 4的默認行為,可能你設(shè)置一下chunks: 'all'就足夠了。如果你想讓我討論此相關(guān)話題,歡迎留言。很快我們將會學(xué)習(xí)如何使用懶加載,讓你的應(yīng)用性能更上一層樓。敬請期待!


向AI問一下細節(jié)

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

AI