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

轉載請註明出處:葡萄城官網,葡萄城爲開發者提供專業的開發工具、解決方案和服務,賦能開發者。
原文出處:https://wanago.io/2018/06/04/code-splitting-with-splitchunksplugin-in-webpack-4/html

Webpack 4 給咱們帶來了一些變化。其中包括更快地打包,引入了SplitChunksPlugin,並淘汰掉以前的CommomsChunksPlugin。在本文,你將學習如何拆分輸出代碼以提升應用的性能。node

代碼分離的思想webpack

先說重要的:在Webpack中,到底什麼是代碼分離?代碼分離容許你把代碼拆分到多個文件中。若是使用得當,你的應用性能會提升不少。由於瀏覽器能緩存你的代碼。web

每當你作出一次修改,包含修改的文件須要被全部訪問你網站的人從新下載。但你並不會常常修改應用的依賴庫(譯者注:你常修改的是你的業務邏輯)。若是你能把那些依賴庫拆分到徹底分離的文件中,即便業務邏輯發生了更改,訪問者也不須要再次下載依賴庫,直接使用以前的緩存就能夠了。瀏覽器

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

入口(Entry)異步

入口定義了咱們代碼中應用是從哪裏開始執行的,這也是Webpack開始打包的地方。你能夠定義一個入口(常見於單頁應用),或者多個入口(常見於多頁應用)。工具

定義一個入口,就會獲得一個chunk。若是你只使用字符串定義一個入口,那麼這個chunk名爲main。若是你使用對象定義了多個入口,那麼它們會以entry對象的屬性來命名。下面的例子會獲得相同的chunk:性能

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

輸出(Output)學習

在配置文件中,輸出配置是一個對象,它指明瞭Webpack應該在哪兒和如何對咱們的打包結果和資源進行輸出。雖然可能有多個入口,可是隻能有一個輸出配置對象。而chunk名稱的用處,就在於根據入口對應不一樣的輸出。你能夠爲咱們的打包輸出定義一個固定的文件名,但若想代碼分離,就不該該這麼作。你可使用[name]爲咱們的輸出文件建立文件名的模板:

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

一件值得注意的重要東西是[chunkhash]:它是一個基於文件內容的屬於特定chunk的哈希值。它僅會隨着文件內容的改變而改變。所以,瀏覽器就能夠利用這一點來緩存它。若是打包輸出的文件名變了,瀏覽器就知道本身須要從新下載它。一個chunkhash可能長這樣:0c553ebfd158e16da428。

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

SplitChunksPlugin

因爲有了SplitChunksPlugin,你能夠把應用中的特定部分移至不一樣文件。若是一個模塊在不止一個chunk中被使用,那麼利用代碼分離,該模塊就能夠在它們之間很好地被共享。這是Webpack的默認行爲。

// 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建立了兩個文件:a.[chunkhash].bundle.js和b.[chunkhash].bundle.js,並且每個文件都包含對lodash庫的拷貝:這並很差!我以前說過,爲共享的庫建立分離的文件是Webpack的一個默認行爲,但這隻涉及異步的chunk,即意味着只做用於咱們異步引入的那些文件。咱們會在介紹懶加載的時候討論這個話題。爲了使這個默認行爲能支持全部類型的chunks,咱們須要稍微改一下Webpack的配置:

// 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"
    }
  },
};

如今咱們看到,建立了額外的vendors~a~b.[chunkhash].bundle.js文件,它包含了lodash庫的代碼。這是由於咱們默認有一些cacheGroups配置:

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

首先,是vendors,它包含的文件來自於你node_modules。再者,是全部其餘共享模塊的默認緩存組。這裏有一個小點:有一些冗餘。a.[chunkhash].bundle.js和b.[chunkhash].bundle.js都包含了users.js的內容。這是由於,SplitChunksPlugin默認地只會分離大於30Kb的文件。咱們能夠輕鬆地修改它:

// 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 // 修改了這裏
    }
  }
};

結果是,它新建立了屬於默認緩存組的名爲a~b.[chunkhash].bundle.js的文件。由於咱們的users.js文件所佔空間遠遠小於30Kb,在沒有修改minSize屬性的狀況下,它不會被打包到單獨的分離文件。在真實環境下,這是一件好事,由於這樣不會帶來實質的性能提高,反而會強制瀏覽器爲分離出的文件(它如今是很小的)再發一次額外的請求。

咱們能夠進一步,爲僅在utilities目錄下的作特殊處理:

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
        }
      }
    }
  }
};

這樣咱們的輸出包含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中的相關引用路徑)。雖然咱們如今可讓minSize:0成爲全局設置(即放在splitChunks對象中做爲其屬性),但即便這樣,默認的緩存組也不會被建立。由於,全部可能被引入的文件都應該在咱們剛建立的utilities組下。這個組具的優先級是0,高於默認緩存組的優先級。你可能已經注意到了,默認緩存組的優先級被設置爲了-20。

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

總結

即便你只有一個入口(常發生於大多數單頁應用中),把你的依賴放入一個獨立的文件依然是個好主意。這其實很容易作到,由於使用SplitChunksPlugin是Webpack 4的默認行爲,可能你設置一下chunks: 'all'就足夠了。若是你想讓我討論此相關話題,歡迎留言。很快咱們將會學習如何使用懶加載,讓你的應用性能更上一層樓。敬請期待!

相關文章
相關標籤/搜索