æåï¼chunksï¼ä»¥åå
é¨å¯¼å
¥ç模åï¼æ¯éè¿å
é¨ webpack å¾è°±ä¸çç¶åå
³ç³»å
³èçãCommonsChunkPlugin æ¾è¢«ç¨æ¥é¿å
ä»ä»¬ä¹é´çéå¤ä¾èµï¼ä½æ¯ä¸å¯è½ååè¿ä¸æ¥çä¼åã
ä» webpack v4 å¼å§ï¼ç§»é¤äº CommonsChunkPluginï¼åè代ä¹çæ¯ optimization.splitChunksã
å¼ç®±å³ç¨ç SplitChunksPlugin 对äºå¤§é¨åç¨æ·æ¥è¯´é常å好ã
é»è®¤æ åµä¸ï¼å®åªä¼å½±åå°æéå è½½ç chunksï¼å ä¸ºä¿®æ¹ initial chunks ä¼å½±åå°é¡¹ç®ç HTML æä»¶ä¸çèæ¬æ ç¾ã
webpack å°æ ¹æ®ä»¥ä¸æ¡ä»¶èªå¨æå chunksï¼
node_modules æä»¶å¤¹å½å°è¯æ»¡è¶³æå两个æ¡ä»¶æ¶ï¼æå¥½ä½¿ç¨è¾å¤§ç chunksã
webpack ä¸ºå¸æå¯¹è¯¥åè½è¿è¡æ´å¤æ§å¶çå¼åè æä¾äºä¸ç»é项ã
ä¸é¢è¿ä¸ªé
置对象代表 SplitChunksPlugin çé»è®¤è¡ä¸ºã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};string = '~'
é»è®¤æ
åµä¸ï¼webpack å°ä½¿ç¨ chunk çæ¥æºååç§°çæåç§°ï¼ä¾å¦ vendors~main.jsï¼ãæ¤éé¡¹ä½¿ä½ å¯ä»¥æå®ç¨äºçæåç§°çåé符ã
string = 'async' function (chunk)
è¿è¡¨æå°éæ©åªäº chunk è¿è¡ä¼åã彿ä¾ä¸ä¸ªåç¬¦ä¸²ï¼ææå¼ä¸º allï¼async å initialã设置为 all å¯è½ç¹å«å¼ºå¤§ï¼å ä¸ºè¿æå³ç chunk å¯ä»¥å¨å¼æ¥åé弿¥ chunk ä¹é´å
±äº«ã
Note that it is applied to the fallback cache group as well (splitChunks.fallbackCacheGroup.chunks).
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
// include all types of chunks
chunks: 'all',
},
},
};æè ï¼ä½ ä¹å¯ä»¥æä¾ä¸ä¸ªå½æ°å»åæ´å¤çæ§å¶ãè¿ä¸ªå½æ°çè¿åå¼å°å³å®æ¯å¦å 嫿¯ä¸ä¸ª chunkã
module.exports = {
//...
optimization: {
splitChunks: {
chunks(chunk) {
// exclude `my-excluded-chunk`
return chunk.name !== 'my-excluded-chunk';
},
},
},
};number = 30
æéå è½½æ¶çæå¤§å¹¶è¡è¯·æ±æ°ã
number = 30
å ¥å£ç¹çæå¤§å¹¶è¡è¯·æ±æ°ã
[string] = ['javascript', 'unknown']
Sets the size types which are used when a number is used for sizes.
number = 1
æååå¿ é¡»å ±äº«æ¨¡åçæå° chunks æ°ã
boolean
ä¸ºç± maxSize åå²çé¨åå建åç§°æ¶ï¼é»æ¢å ¬å¼è·¯å¾ä¿¡æ¯ã
number = 20000 { [index: string]: number }
çæ chunk çæå°ä½ç§¯ï¼ä»¥ bytes 为åä½ï¼ã
number { [index: string]: number }
çæ chunk æéç主 chunkï¼bundleï¼çæå°ä½ç§¯ï¼ä»¥åè为åä½ï¼ç¼©åãè¿æå³ç妿å岿ä¸ä¸ª chunk 并没æåå°ä¸» chunkï¼bundleï¼çç»å®åèæ°ï¼å®å°ä¸ä¼è¢«åå²ï¼å³ä½¿å®æ»¡è¶³ splitChunks.minSizeã
splitChunks.cacheGroups.{cacheGroup}.enforceSizeThresholdnumber = 50000
å¼ºå¶æ§è¡æåçä½ç§¯éå¼åå ¶ä»éå¶ï¼minRemainingSizeï¼maxAsyncRequestsï¼maxInitialRequestsï¼å°è¢«å¿½ç¥ã
splitChunks.cacheGroups.{cacheGroup}.minRemainingSizenumber = 0
å¨ webpack 5 ä¸å¼å
¥äº splitChunks.minRemainingSize é项ï¼éè¿ç¡®ä¿æååå©ä½çæå° chunk ä½ç§¯è¶
è¿éå¶æ¥é¿å
大å°ä¸ºé¶ç模åã 'development' æ¨¡å¼ ä¸é»è®¤ä¸º 0ã对äºå
¶ä»æ
åµï¼splitChunks.minRemainingSize é»è®¤ä¸º splitChunks.minSize çå¼ï¼å æ¤é¤éè¦æ·±åº¦æ§å¶çæå°æ°æ
åµå¤ï¼ä¸éè¦æå¨æå®å®ã
splitChunks.cacheGroups.{cacheGroup}.layerRegExp string function
ææ¨¡åå±å°æ¨¡ååé ç»ç¼åç»ã
number = 0
ä½¿ç¨ maxSizeï¼æ¯ä¸ªç¼åç» optimization.splitChunks.cacheGroups[x].maxSize å
¨å±ä½¿ç¨ optimization.splitChunks.maxSize æå¯¹åå¤ç¼åç» optimization.splitChunks.fallbackCacheGroup.maxSize 使ç¨ï¼åè¯ webpack å°è¯å°å¤§äº maxSize 个åèç chunk å岿è¾å°çé¨åã è¿äºè¾å°çé¨åå¨ä½ç§¯ä¸è³å°ä¸º minSizeï¼ä»
æ¬¡äº maxSizeï¼ã
è¯¥ç®æ³æ¯ç¡®å®æ§çï¼å¯¹æ¨¡åçæ´æ¹åªä¼äº§çå±é¨å½±åãè¿æ ·ï¼å¨ä½¿ç¨é¿æç¼åæ¶å°±å¯ä»¥ä½¿ç¨å®å¹¶ä¸ä¸éè¦è®°å½ãmaxSize åªæ¯ä¸ä¸ªæç¤ºï¼å½æ¨¡åå¤§äº maxSize æè
æåä¸ç¬¦å minSize æ¶å¯è½ä¼è¢«è¿åã
å½ chunk å·²ç»æä¸ä¸ªåç§°æ¶ï¼æ¯ä¸ªé¨åå°è·å¾ä¸ä¸ªä»è¯¥åç§°æ´¾ççæ°åç§°ã æ ¹æ® optimization.splitChunks.hidePathInfo çå¼ï¼å®å°æ·»å ä¸ä¸ªä»ç¬¬ä¸ä¸ªæ¨¡ååç§°æå
¶åå¸å¼æ´¾ççå¯é¥ã
maxSize é项æ¨å¨ä¸ HTTP/2 åé¿æç¼åä¸èµ·ä½¿ç¨ãå®å¢å äºè¯·æ±æ°é以å®ç°æ´å¥½çç¼åãå®è¿å¯ä»¥ç¨äºå尿件大å°ï¼ä»¥å å¿«äºæ¬¡æå»ºé度ã
number
å maxSize 䏿 ·ï¼maxAsyncSize å¯ä»¥ä¸º cacheGroupsï¼splitChunks.cacheGroups.{cacheGroup}.maxAsyncSizeï¼æ fallback ç¼åç»ï¼splitChunks.fallbackCacheGroup.maxAsyncSize ï¼å
¨å±åºç¨ï¼splitChunks.maxAsyncSizeï¼
maxAsyncSize å maxSize çåºå«å¨äº maxAsyncSize ä»
ä¼å½±åæéå è½½ chunkã
number
å maxSize 䏿 ·ï¼maxInitialSize å¯ä»¥å¯¹ cacheGroupsï¼splitChunks.cacheGroups.{cacheGroup}.maxInitialSizeï¼æ fallback ç¼åç»ï¼splitChunks.fallbackCacheGroup.maxInitialSizeï¼å
¨å±åºç¨ï¼splitChunks.maxInitialSizeï¼ã
maxInitialSize å maxSize çåºå«å¨äº maxInitialSize ä»
ä¼å½±ååå§å è½½ chunksã
boolean = false function (module, chunks, cacheGroupKey) => string string
æ¯ä¸ª cacheGroup ä¹å¯ä»¥ä½¿ç¨ï¼splitChunks.cacheGroups.{cacheGroup}.nameã
æå chunk çåç§°ã设为 false å°ä¿æ chunk çç¸ååç§°ï¼å æ¤ä¸ä¼ä¸å¿
è¦å°æ´æ¹åç§°ãè¿æ¯ç产ç¯å¢ä¸æå»ºç建议å¼ã
æä¾å符串æå½æ°ä½¿ä½ å¯ä»¥ä½¿ç¨èªå®ä¹åç§°ãæå®å符串æå§ç»è¿åç¸åå符串ç彿°ä¼å°ææå¸¸è§æ¨¡åå vendor å并为ä¸ä¸ª chunkãè¿å¯è½ä¼å¯¼è´æ´å¤§çåå§ä¸è½½éå¹¶åæ ¢é¡µé¢å è½½é度ã
å¦æä½ éæ©æå®ä¸ä¸ªå½æ°ï¼åå¯è½ä¼åç° chunk.name å chunk.hash 屿§ï¼å
¶ä¸ chunk æ¯ chunks æ°ç»çä¸ä¸ªå
ç´ ï¼å¨éæ© chunk åæ¶ç¹å«æç¨ã
妿 splitChunks.name ä¸ entry point åç§°å¹é
ï¼entry point å°è¢«å é¤ã
main.js
import _ from 'lodash';
console.log(_.join(['Hello', 'webpack'], ' '));webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
// cacheGroupKey here is `commons` as the key of the cacheGroup
name(module, chunks, cacheGroupKey) {
const moduleFileName = module
.identifier()
.split('/')
.reduceRight((item) => item);
const allChunksNames = chunks.map((item) => item.name).join('~');
return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`;
},
chunks: 'all',
},
},
},
},
};使ç¨ä»¥ä¸ splitChunks é
ç½®æ¥è¿è¡ webpack ä¹ä¼è¾åºä¸ç»å
¬ç¨ç»ï¼å
¶ä¸ä¸ä¸ªå称为ï¼commons-main-lodash.js.e7519d2bb8777058fa27.jsï¼ä»¥å叿¹å¼ä½ä¸ºçå®ä¸çè¾åºç¤ºä¾ï¼ã
splitChunks.cacheGroups{cacheGroup}.usedExportsboolean = true
弿¸
åªäº export 被模å使ç¨ï¼ä»¥æ··æ· export åç§°ï¼çç¥æªä½¿ç¨ç exportï¼å¹¶çæææç代ç ã
å½å®ä¸º true æ¶ï¼åææ¯ä¸ªè¿è¡æ¶ä½¿ç¨çåºå£ï¼å½å®ä¸º "global" æ¶ï¼åæææè¿è¡æ¶çå
¨å± export ç»åï¼ã
ç¼åç»å¯ä»¥ç»§æ¿å/æè¦çæ¥èª splitChunks.* çä»»ä½é项ã使¯ testãpriority å reuseExistingChunk åªè½å¨ç¼åç»çº§å«ä¸è¿è¡é
ç½®ãå°å®ä»¬è®¾ç½®ä¸º false以ç¦ç¨ä»»ä½é»è®¤ç¼åç»ã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
default: false,
},
},
},
};splitChunks.cacheGroups.{cacheGroup}.prioritynumber = -20
ä¸ä¸ªæ¨¡åå¯ä»¥å±äºå¤ä¸ªç¼åç»ãä¼åå°ä¼å
èèå
·ææ´é« priorityï¼ä¼å
级ï¼çç¼åç»ãé»è®¤ç»çä¼å
级为è´ï¼ä»¥å
许èªå®ä¹ç»è·å¾æ´é«çä¼å
级ï¼èªå®ä¹ç»çé»è®¤å¼ä¸º 0ï¼ã
splitChunks.cacheGroups.{cacheGroup}.reuseExistingChunkboolean = true
妿å½å chunk å å«å·²ä»ä¸» bundle 䏿ååºç模åï¼åå®å°è¢«éç¨ï¼è䏿¯çææ°çæ¨¡åãè¿å¯è½ä¼å½±å chunk çç»ææä»¶åã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
reuseExistingChunk: true,
},
},
},
},
};splitChunks.cacheGroups.{cacheGroup}.typefunction RegExp string
å è®¸ææ¨¡åç±»åå°æ¨¡ååé ç»ç¼åç»ã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
json: {
type: 'json',
},
},
},
},
};splitChunks.cacheGroups.{cacheGroup}.testfunction (module, { chunkGraph, moduleGraph }) => boolean RegExp string
æ§å¶æ¤ç¼åç»éæ©ç模åãçç¥å®ä¼éæ©æææ¨¡åãå®å¯ä»¥å¹é ç»å¯¹æ¨¡åèµæºè·¯å¾æ chunk åç§°ãå¹é chunk åç§°æ¶ï¼å°éæ© chunk ä¸çæææ¨¡åã
为 {cacheGroup}.test æä¾ä¸ä¸ªå½æ°ï¼
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
svgGroup: {
test(module) {
// `module.resource` contains the absolute path of the file on disk.
// Note the usage of `path.sep` instead of / or \, for cross-platform compatibility.
const path = require('path');
return (
module.resource &&
module.resource.endsWith('.svg') &&
module.resource.includes(`${path.sep}cacheable_svgs${path.sep}`)
);
},
},
byModuleTypeGroup: {
test(module) {
return module.type === 'javascript/auto';
},
},
},
},
},
};ä¸ºäºæ¥ç module and chunks 对象ä¸å¯ç¨çä¿¡æ¯ï¼ä½ å¯ä»¥å¨åè°å½æ°ä¸æ¾å
¥ debugger; è¯å¥ãç¶å 以è°è¯æ¨¡å¼è¿è¡ webpack æå»º æ£æ¥ Chromium DevTools ä¸çåæ°ã
å {cacheGroup}.test æä¾ RegExpï¼
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
// Note the usage of `[\\/]` as a path separator for cross-platform compatibility.
test: /[\\/]node_modules[\\/]|vendor[\\/]analytics_provider|vendor[\\/]other_lib/,
},
},
},
},
};splitChunks.cacheGroups.{cacheGroup}.filenamestring function (pathData, assetInfo) => string
ä»
å¨åå§ chunk æ¶æå
许è¦çæä»¶åã
ä¹å¯ä»¥å¨ output.filename ä¸ä½¿ç¨ææå ä½ç¬¦ã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: '[name].bundle.js',
},
},
},
},
};è¥ä¸ºå½æ°ï¼åï¼
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: (pathData) => {
// Use pathData object for generating filename string based on your requirements
return `${pathData.chunk.name}-bundle.js`;
},
},
},
},
},
};éè¿æä¾ä»¥æä»¶åå¼å¤´çè·¯å¾ 'js/vendor/bundle.js'ï¼å¯ä»¥å建æä»¶å¤¹ç»æã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: 'js/[name]/bundle.js',
},
},
},
},
};splitChunks.cacheGroups.{cacheGroup}.enforceboolean = false
åè¯ webpack å¿½ç¥ splitChunks.minSizeãsplitChunks.minChunksãsplitChunks.maxAsyncRequests å splitChunks.maxInitialRequests é项ï¼å¹¶å§ç»ä¸ºæ¤ç¼åç»å建 chunkã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
enforce: true,
},
},
},
},
};splitChunks.cacheGroups.{cacheGroup}.idHintstring
设置 chunk id çæç¤ºã å®å°è¢«æ·»å å° chunk çæä»¶åä¸ã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
idHint: 'vendors',
},
},
},
},
};// index.js
import('./a'); // dynamic import// a.js
import 'react';
//...ç»æï¼ å°å建ä¸ä¸ªåç¬çå
å« react ç chunkãå¨å¯¼å
¥è°ç¨ä¸ï¼æ¤ chunk å¹¶è¡å è½½å°å
å« ./a çåå§ chunk ä¸ã
为ä»ä¹ï¼
node_modules çæ¨¡åreact å¤§äº 30kbè¿èåçåå æ¯ä»ä¹ï¼react å¯è½ä¸ä¼åä½ çåºç¨ç¨åºä»£ç 飿 ·é¢ç¹å°æ´æ¹ãéè¿å°å
¶ç§»å¨å°åç¬ç chunk ä¸ï¼å¯ä»¥å°è¯¥ chunk ä¸åºç¨ç¨åºä»£ç åå¼è¿è¡ç¼åï¼åè®¾ä½ ä½¿ç¨çæ¯ chunkhashï¼recordsï¼Cache-Control æå
¶ä»é¿æç¼åæ¹æ³ï¼ã
// entry.js
// dynamic imports
import('./a');
import('./b');// a.js
import './helpers'; // helpers is 40kb in size
//...// b.js
import './helpers';
import './more-helpers'; // more-helpers is also 40kb in size
//...ç»æï¼ å°å建ä¸ä¸ªåç¬ç chunkï¼å
¶ä¸å
å« ./helpers åå
¶ææä¾èµé¡¹ãå¨å¯¼å
¥è°ç¨æ¶ï¼æ¤ chunk ä¸åå§ chunks å¹¶è¡å è½½ã
为ä»ä¹ï¼
helpers å¤§äº 30kbå° helpers çå
容æ¾å
¥æ¯ä¸ª chunk ä¸å°å¯¼è´å
¶ä»£ç 被ä¸è½½ä¸¤æ¬¡ãéè¿ä½¿ç¨åç¬çåï¼è¿åªä¼åç䏿¬¡ãæä»¬ä¼è¿è¡é¢å¤ç请æ±ï¼è¿å¯ä»¥è§ä¸ºä¸ç§æè¡·ãè¿å°±æ¯ä¸ºä»ä¹æå°ä½ç§¯ä¸º 30kb çåå ã
å建ä¸ä¸ª commons chunkï¼å
¶ä¸å
æ¬å
¥å£ï¼entry pointsï¼ä¹é´ææå
±äº«ç代ç ã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2,
},
},
},
},
};å建ä¸ä¸ª vendors chunkï¼å
¶ä¸å
æ¬æ´ä¸ªåºç¨ç¨åºä¸ node_modules çææä»£ç ã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
};å建ä¸ä¸ª custom vendor chunkï¼å
¶ä¸å
å«ä¸ RegExp å¹é
çæäº node_modules å
ã
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
},
};