2020年春節已過,原本打算回鄭州,卻由於新型冠狀病毒感染肺炎的疫情公司推遲了上班的時間,我也推遲了去鄭州的時間,在家多陪娃幾天。之前都是在書房學習寫博客,今天比較特殊,抱着電腦,在樓頂曬着太陽,陪着家人,寫着博客。javascript
前面的幾篇文章主要告訴你們如何安裝、配置webpack、webpack實現樣式分離等,今天這篇文章主要跟你們分享若是webpack如何實現代碼分片。css
如今工程項目中,實現高性能應用的其中重要的一點就是讓用戶每次只加載必要的資源,優先級別不過高的資源採用延遲加載等技術漸進地進行加載獲取。html
Webpack 做爲打包工具所特有的一項技術就是代碼分片技術,經過這項技術咱們能夠把代碼按照特定的形式進行拆分,使用按需加載資源,沒必要要所有加載下來。 代碼分片能夠有效下降首屏加載資源的大小,可是咱們同時又面臨着其餘問題,好比如何對項目模塊進行分片,分片後的資源如何進行管理等等。今天咱們須要對這些問題進行分析解決。java
在Webpack中,配置參數中每一個入口都將生成一個對應的資源文件,經過入口的配置咱們能夠進行一些簡單有效的代碼拆分。node
對於項目中經常會引入一些第三方庫和工具,這些通常不會改動的,能夠把它們單獨放在一個入口中,由該入口的資源不會常常更新,所以能夠有效利用客戶端緩存這些資源,讓用戶沒必要在每次請求頁面時候都從新加載。react
//webpack.config.js
entry: {
index: './index.js',
lib: ['lib-1', 'lib-2']
}
//index.html
<script src="dist/lib.js"></script>
<script src="dist/index.js"></script>
複製代碼
這種拆分方法主要適合於那些將接口綁定在全局對象上的庫,由於業務代碼中的模塊沒法直接引用庫中的模塊,兩者屬於不一樣的依賴樹。webpack
對於多頁面應用來講,咱們能夠利用入口劃分的方式拆分代碼。好比,爲每個頁面建立一個入口,並放入只涉及該頁面的代碼,同時再建立一個入口來包含全部公共模塊,並使每一個頁面都進行加載。可是這樣仍會帶來公共模塊與業務模塊處於不一樣依賴樹的問題。另外,不少時候不是全部的頁面都須要這些公共模塊。這就須要咱們利用webpack專用的插件來解決這種問題了。web
CommonsChunkPlugin是webpack4以前內部自帶的插件,webpack4以後用的是SplitChunks。CommonsChunkPlugin主要是用來提取第三方庫和公共模塊,避免首屏加載的bundle文件或者按需加載的bundle文件體積過大,從而致使加載時間過長,是一把優化項目的利器。瀏覽器
優勢:緩存
//webpack.config.js
module.exports = {
entry: {
a: './a.js',
b: './b.js'
},
output: {
filename: '[name].js'
}
}
//a.js
import React from 'React'
... //省略
// b.js
import React from 'React'
... //省略
複製代碼
若是打包,從打包的資源體積能夠看出,react被分別打包到a.js 和b.js中。
更改webpack.config.js,添加CommonsChunkPlugin配置
const webpack = require('webpack');
module.exports = {
entry: {
a: './a.js',
b: './b.js'
},
output: {
filename: '[name].js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'commons',
filename: 'commons.js'
})
]
}
複製代碼
在配置文件的頭部引入Webpack,接着使用其內部CommonsChunkPlugin函數建立了一個插件實例,並傳入配置對象,配置參數能夠理解爲
在提取公共模塊方面,CommonsChunkPlugin能夠知足不少場景的需求,可是它也有一些欠缺的地方。 1)一個CommonsChunkPlugin只能提取一個vendor,假如咱們想提取多個vendor則須要配置多個插件,這會增長不少重複的配置代碼。
2)前面咱們提到的manifest實際上會使瀏覽器多加載一個資源,這對於頁面渲染速度是不友好的。
3)因爲內部設計上的一些缺陷,CommonsChunkPlugin在提取公共模塊的時候會破壞掉原有Chunk中模塊的依賴關係,致使難以進行更多的優化。好比在異步Chunk的場景下CommonsChunkPlugin並不會按照咱們的預期正常工做。
optimization.SplitChunks(簡稱SplitChunks)是Webpack 4爲了改進CommonsChunk-Plugin而從新設計和實現的代碼分片特性。它不只比CommonsChunkPlugin功能更增強大,還更簡單易用。
配置文件web pack.config.js爲:
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js'
},
output: {
// path: path.join(__dirname, 'dist'),
filename: 'index.js',
publicPath: '/dist/'
},
mode: 'development',
optimization: {
splitChunks: {
chunks: 'all'
}
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', {
loader: 'css-loader',
options: {
modules: {
localIdentName: '[path][name]__[local]--[hash:base64:5]',
}
}
}]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
[
'env', {
modules: false
}
]
]
}
}
}
],
}
}
複製代碼
須要引入的兩個index.js文件和index2.js文件
// index
import index2 from './index2.js';
import React from 'react'
document.write('index.js', React.version);
//index2
import React from 'react'
document.write('index2.js', React.version);
複製代碼
使用optimization.splitChunks替代了CommonsChunkPlugin,並指定了chunks的值爲all,這個配置項的含義是,SplitChunks將會對全部的chunks生效(默認狀況下,SplitChunks只對異步chunks生效,而且不須要配置) 打包結果以下圖:
本來咱們打包的結果應該是index.js,可是因爲SplitChunks的存在,又生成了一個vendors~index.index.js,而且把react提取到了裏面。 運行的效果以下圖:
在使用CommonsChunkPlugin的時候,咱們大多數時候是經過配置項將特定入口中的特定模塊提取出來,也就是更貼近命令式的方式。而SplitChunks的不一樣之處在於咱們只須要設置一些提取條件,如提取的模式、提取模塊的體積等,當某些模塊達到這些條件後就會自動被提取出來。SplitChunks的使用更像是聲明式的。SplitChunks 默認的提取方式是異步提取,當咱們在chunks上配置參數爲all的時候,不是異步資源也能夠提取。
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
minRemainingSize: 0,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 6,
maxInitialRequests: 4,
automaticNameDelimiter: '~',
name: true,
automaticNameMaxLength: 30,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
複製代碼
(1)匹配模式經過chunks咱們能夠配置SplitChunks的工做模式。它有3個可選值,分別爲async(默認)、initial和all。async即只提取異步chunk,initial則只對入口chunk生效(若是配置了initial則上面異步的例子將失效),all則是兩種模式同時開啓。
(2)匹配條件minSize、minChunks、maxAsyncRequests、maxInitialRequests都屬於匹配條件,
(3)命名配置項name默認爲true,它意味着SplitChunks能夠根據cacheGroups和做用範圍自動爲新生成的chunk命名,並以automaticNameDelimiter分隔。如vendors~a~b~c.js意思是cacheGroups爲vendors,而且該chunk是由a、b、c三個入口chunk所產生的。
(4)cacheGroups能夠理解成分離chunks時的規則。默認狀況下有兩種規則——defaultVendors和default。defaultVendors用於提取全部node_modules中符合條件的模塊,default則做用於被屢次引用的模塊。咱們能夠對這些規則進行增長或者修改,若是想要禁用某種規則,也能夠直接將其置爲false。當一個模塊同時符合多個cacheGroups時,則根據其中的priority配置項肯定優先級。
有關webpack實現代碼分片的幾種方法:合理地規劃入口,使用Commons-ChunkPlugin或SplitChunks就暫時分享到這裏,這僅表明我的的觀點,如想了解更多請掃描二維碼
最後友情提醒你們要戴口罩,勤洗手,儘可能減小外出,作好預防 措施,遠離新型冠狀病毒。