代ç åç¦»æ¯ webpack 䏿å¼äººæ³¨ç®çç¹æ§ä¹ä¸ãæ¤ç¹æ§è½å¤æä»£ç å离å°ä¸åç bundle ä¸ï¼ç¶åä¾¿è½æéå è½½æå¹¶è¡å è½½è¿äºæä»¶ã代ç å离å¯ä»¥ç¨äºè·åæ´å°ç bundleãæ§å¶èµæºå è½½ä¼å 级ï¼å¦æä½¿ç¨åçï¼ä¼æå¤§åå°å è½½æ¶é´ã
常ç¨ç代ç åç¦»æ¹æ³æä¸ç§ï¼
entry é
ç½®æå¨å°å离代ç ãSplitChunksPlugin å»éåå离 chunkãè¿æ¯è¿ä»ä¸ºæ¢æç®åç´è§çå®ç°ä»£ç åç¦»çæ¹å¼ãä¸è¿ï¼è¿ç§æ¹å¼æå¨é ç½®è¾å¤ï¼å¹¶æä¸äºéæ£ãä¸è¿ï¼æä»¬å°ä¼ä»ç»å¦ä½è§£å³è¿äºéæ£ãå æ¥ççå¦ä½ä» main bundle ä¸å离å¦ä¸ä¸ªæ¨¡åï¼
project
webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js
|- /dist
|- /src
|- index.js
+ |- another-module.js
|- /node_modulesanother-module.js
import _ from 'lodash';
console.log(_.join(['Another', 'module', 'loaded!'], ' '));webpack.config.js
const path = require('path');
module.exports = {
- entry: './src/index.js',
+ mode: 'development',
+ entry: {
+ index: './src/index.js',
+ another: './src/another-module.js',
+ },
output: {
- filename: 'main.js',
+ filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};æå»ºåç»æå¦ä¸ï¼
...
[webpack-cli] Compilation finished
asset index.bundle.js 553 KiB [emitted] (name: index)
asset another.bundle.js 553 KiB [emitted] (name: another)
runtime modules 2.49 KiB 12 modules
cacheable modules 530 KiB
./src/index.js 257 bytes [built] [code generated]
./src/another-module.js 84 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 245 msæ£å¦å颿æåï¼è¿ç§æ¹å¼åå¨ä¸äºéæ£ï¼
以ä¸ä¸¤ç¹ä¸ï¼ç¬¬ä¸ç¹æå¯¹åºçé®é¢å·²ç»å¨æä»¬ä¸é¢çå®ä¾ä¸ä½ç°åºæ¥äºãé¤äº ./src/another-module.jsï¼æä»¬ä¹æ¾å¨ ./src/index.js ä¸å¼å
¥è¿ lodashï¼è¿å°±å¯¼è´äºéå¤å¼ç¨ãä¸ä¸ç« èä¼ä»ç»å¦ä½ç§»é¤éå¤ç模åã
å¨é
ç½®æä»¶ä¸é
ç½® dependOn é项ï¼ä»¥å¨å¤ä¸ª chunk ä¹é´å
±äº«æ¨¡åï¼
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
- index: './src/index.js',
- another: './src/another-module.js',
+ index: {
+ import: './src/index.js',
+ dependOn: 'shared',
+ },
+ another: {
+ import: './src/another-module.js',
+ dependOn: 'shared',
+ },
+ shared: 'lodash',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};妿æ³è¦å¨ä¸ä¸ª HTML 页é¢ä¸ä½¿ç¨å¤ä¸ªå
¥å£èµ·ç¹ï¼è¿é设置 optimization.runtimeChunk: 'single'ï¼å¦åä¼éå° æ¤å¤ æè¿°ç麻ç¦ã
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
index: {
import: './src/index.js',
dependOn: 'shared',
},
another: {
import: './src/another-module.js',
dependOn: 'shared',
},
shared: 'lodash',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
+ optimization: {
+ runtimeChunk: 'single',
+ },
};æå»ºç»æå¦ä¸ï¼
...
[webpack-cli] Compilation finished
asset shared.bundle.js 549 KiB [compared for emit] (name: shared)
asset runtime.bundle.js 7.79 KiB [compared for emit] (name: runtime)
asset index.bundle.js 1.77 KiB [compared for emit] (name: index)
asset another.bundle.js 1.65 KiB [compared for emit] (name: another)
Entrypoint index 1.77 KiB = index.bundle.js
Entrypoint another 1.65 KiB = another.bundle.js
Entrypoint shared 557 KiB = runtime.bundle.js 7.79 KiB shared.bundle.js 549 KiB
runtime modules 3.76 KiB 7 modules
cacheable modules 530 KiB
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
./src/another-module.js 84 bytes [built] [code generated]
./src/index.js 257 bytes [built] [code generated]
webpack 5.4.0 compiled successfully in 249 mså¯ä»¥çå°ï¼é¤äº shared.bundle.jsï¼index.bundle.js å another.bundle.js ä¹å¤ï¼è¿çæäºä¸ä¸ª runtime.bundle.js æä»¶ã
尽管 webpack å
许æ¯ä¸ªé¡µé¢ä½¿ç¨å¤ä¸ªå
¥å£èµ·ç¹ï¼ä½å¨å¯è½çæ
åµä¸ï¼åºè¯¥é¿å
使ç¨å¤ä¸ªå
¥å£èµ·ç¹ï¼è使ç¨å
·æå¤ä¸ªå¯¼å
¥çå个å
¥å£èµ·ç¹ï¼entry: { page: ['./analytics', './app'] }ãè¿æ ·å¯ä»¥è·å¾æ´å¥½çä¼åææï¼å¹¶å¨ä½¿ç¨å¼æ¥èæ¬æ ç¾æ¶ä¿è¯æ§è¡é¡ºåºä¸è´ã
SplitChunksPlugin æä»¶å¯ä»¥å°å
Œ
±çä¾èµæ¨¡åæåå°å·²æçå
¥å£ chunk ä¸ï¼æè
æåå°ä¸ä¸ªæ°çæç chunkã让æä»¬ä½¿ç¨è¿ä¸ªæä»¶å»é¤ä¹å示ä¾ä¸éå¤ç lodash 模åï¼
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js',
another: './src/another-module.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
+ optimization: {
+ splitChunks: {
+ chunks: 'all',
+ },
+ },
};ä½¿ç¨ optimization.splitChunks é
ç½®é项åæå»ºï¼å°ä¼åç° index.bundle.js å another.bundle.js å·²ç»ç§»é¤äºéå¤çä¾èµæ¨¡åãä»æä»¶å° lodash å离å°åç¬ç chunkï¼å¹¶ä¸å°å
¶ä» main bundle ä¸ç§»é¤ï¼åè½»äº bundle 大å°ãæ§è¡ npm run build æ¥çææï¼
...
[webpack-cli] Compilation finished
asset vendors-node_modules_lodash_lodash_js.bundle.js 549 KiB [compared for emit] (id hint: vendors)
asset index.bundle.js 8.92 KiB [compared for emit] (name: index)
asset another.bundle.js 8.8 KiB [compared for emit] (name: another)
Entrypoint index 558 KiB = vendors-node_modules_lodash_lodash_js.bundle.js 549 KiB index.bundle.js 8.92 KiB
Entrypoint another 558 KiB = vendors-node_modules_lodash_lodash_js.bundle.js 549 KiB another.bundle.js 8.8 KiB
runtime modules 7.64 KiB 14 modules
cacheable modules 530 KiB
./src/index.js 257 bytes [built] [code generated]
./src/another-module.js 84 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 241 ms以䏿¯ç±ç¤¾åºæä¾ï¼å¯¹ä»£ç åç¦»å¾æå¸®å©ç plugin å loaderï¼
mini-css-extract-pluginï¼ç¨äºå° CSS ä»ä¸»åºç¨ç¨åºä¸å离ãwebpack æä¾äºä¸¤ä¸ªç±»ä¼¼çææ¯å®ç°å¨æä»£ç å离ã第ä¸ç§ï¼ä¹æ¯æ¨èéæ©çæ¹å¼ï¼æ¯ä½¿ç¨ç¬¦å ECMAScript ææ¡ ç import() è¯æ³ å®ç°å¨æå¯¼å
¥ã第äºç§åæ¯ webpack çéçåè½ï¼ä½¿ç¨ webpack ç¹å®ç require.ensureã让æä»¬å
å°è¯ä½¿ç¨ç¬¬ä¸ç§ã
卿们å¼å§ä¹åï¼å
ä»ä¸è¿°ç¤ºä¾çé
ç½®ä¸ç§»é¤å¤ä½ç entry å optimization.splitChunksï¼å 为æ¥ä¸æ¥çæ¼ç¤ºä¸å¹¶ä¸éè¦å®ä»¬ï¼
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js',
- another: './src/another-module.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
- optimization: {
- splitChunks: {
- chunks: 'all',
- },
- },
};æä»¬å°æ´æ°æä»¬ç项ç®ï¼ç§»é¤ç°å¨æªä½¿ç¨çæä»¶ï¼
project
webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js
|- /dist
|- /src
|- index.js
- |- another-module.js
|- /node_modulesç°å¨ï¼æä»¬ä¸åéæå¯¼å
¥ lodashï¼èæ¯éè¿å¨æå¯¼å
¥æ¥å离åºä¸ä¸ª chunkï¼
src/index.js
-import _ from 'lodash';
-
-function component() {
+function getComponent() {
- const element = document.createElement('div');
- // lodash ç°å¨ä½¿ç¨ import å¼å
¥
- element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+ return import('lodash')
+ .then(({ default: _ }) => {
+ const element = document.createElement('div');
+
+ element.innerHTML = _.join(['Hello', 'webpack'], ' ');
- return element;
+ return element;
+ })
+ .catch((error) => 'An error occurred while loading the component');
}
-document.body.appendChild(component());
+getComponent().then((component) => {
+ document.body.appendChild(component);
+});éè¦ default çåå æ¯èª webpack 4 ä¹åï¼å¨å¯¼å
¥ CommonJS æ¨¡åæ¶ï¼å°ä¸åè§£æä¸º module.exports çå¼ï¼èæ¯å建ä¸ä¸ªäººå·¥å½å空é´å¯¹è±¡æ¥è¡¨ç¤ºæ¤ CommonJS 模åãåé
webpack 4: import() and CommonJs 以äºè§£æ´å¤æå
³ä¿¡æ¯ã
è¯è¯æå»ºææ°ç代ç ï¼çç lodash æ¯å¦ä¼å离å°ä¸ä¸ªåç¬ç bundleï¼
...
[webpack-cli] Compilation finished
asset vendors-node_modules_lodash_lodash_js.bundle.js 549 KiB [compared for emit] (id hint: vendors)
asset index.bundle.js 13.5 KiB [compared for emit] (name: index)
runtime modules 7.37 KiB 11 modules
cacheable modules 530 KiB
./src/index.js 434 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 268 msç±äº import() ä¼è¿å promiseï¼å æ¤å®å¯ä»¥å async 彿° ä¸èµ·ä½¿ç¨ãä¸é¢æ¯ä½¿ç¨ async ç®ååç代ç ï¼
src/index.js
-function getComponent() {
+async function getComponent() {
+ const element = document.createElement('div');
+ const { default: _ } = await import('lodash');
- return import('lodash')
- .then(({ default: _ }) => {
- const element = document.createElement('div');
+ element.innerHTML = _.join(['Hello', 'webpack'], ' ');
- element.innerHTML = _.join(['Hello', 'webpack'], ' ');
-
- return element;
- })
- .catch((error) => 'An error occurred while loading the component');
+ return element;
}
getComponent().then((component) => {
document.body.appendChild(component);
});Webpack v4.6.0+ å¢å äºå¯¹é¢è·ååé¢å è½½çæ¯æã
声æ import æ¶ä½¿ç¨ä¸åå
ç½®æä»¤å¯ä»¥è®© webpack è¾åºâResource Hintâåç¥æµè§å¨ï¼
è¯æ³ä¸ä¸ä¸é¢çåºæ¯ï¼ç°å¨æä¸ä¸ª HomePage ç»ä»¶ï¼è¯¥ç»ä»¶å
鍿¸²æäºä¸ä¸ª LoginButton ç»ä»¶ï¼ç¹å»åæé®åå¯ä»¥æéå è½½ LoginModal ç»ä»¶ã
LoginButton.js
//...
import(/* webpackPrefetch: true */ './path/to/LoginModal.js');ä¸é¢ç代ç å¨æå»ºæ¶ä¼çæ <link rel="prefetch" href="login-modal-chunk.js"> 并追å å°é¡µé¢å¤´é¨ï¼æç¤ºæµè§å¨å¨é²ç½®æ¶é´é¢è·å login-modal-chunk.js æä»¶ã
ä¸é¢è·åæä»¤ç¸æ¯ï¼é¢å è½½æä»¤æè®¸å¤ä¸åä¹å¤ï¼
ä¸é¢è¿ä¸ªç®åçé¢å 载示ä¾ä¸ï¼æä¸ä¸ª Componentï¼ä¾èµäºä¸ä¸ªè¾å¤§çåºï¼æä»¥åºè¯¥å°å
¶å离å°ä¸ä¸ªç¬ç«ç chunk ä¸ã
åæ³è¿éçå¾è¡¨ç»ä»¶ ChartComponent ç»ä»¶éè¦ä¾èµä¸ä¸ªä½ç§¯å·¨å¤§ç ChartingLibrary åºãå®ä¼å¨æ¸²ææ¶æ¾ç¤ºä¸ä¸ª LoadingIndicator ç»ä»¶ï¼ç¶åç«å³æé导å
¥ ChartingLibraryï¼
ChartComponent.js
//...
import(/* webpackPreload: true */ 'ChartingLibrary');å¨é¡µé¢ä¸ä½¿ç¨ ChartComponent æ¶ä¼å¨è¯·æ± ChartComponent.js çåæ¶éè¿ <link rel="preload"> è¯·æ± charting-library-chunkãåå® page-chunk ä½ç§¯æ¯ charting-library-chunk æ´å°ï¼ä¹æ´å¿«å°è¢«å è½½å®æï¼é£ä¹å½ charting-library-chunk å è½½å®æåï¼é¡µé¢ä¼é¦å
æ¾ç¤º LoadingIndicatorï¼å½ charting-library-chunk 请æ±å®æåï¼LoadingIndicator ç»ä»¶æä¼æ¶å¤±ãè¿å°ä¼ä½¿å¾å è½½æ¶é´è½å¤æ´çä¸ç¹ï¼å 为åªè¿è¡å次å¾è¿ï¼è䏿¯ä¸¤æ¬¡å¾è¿ï¼å°¤å
¶æ¯å¨é«å»¶è¿ç¯å¢ä¸ã
ææ¶éè¦èªå·±æ§å¶é¢å è½½ãä¾å¦ï¼ä»»ä½å¨æå¯¼å ¥çé¢å è½½é½å¯ä»¥éè¿å¼æ¥èæ¬å®æãè¿å¨æµå¼æå¡å¨ç«¯æ¸²æçæ åµä¸å¾æç¨ã
const lazyComp = () =>
import('DynamicComponent').catch((error) => {
// å¨åçé误æ¶åä¸äºå¤ç
// ä¾å¦å¯ä»¥å¨ç½ç»é误çæ
åµä¸éè¯è¯·æ±
});å¦æå¨ webpack å¼å§å è½½è¯¥èæ¬ä¹åèæ¬å 载失败ï¼å¦æè¯¥èæ¬ä¸å¨é¡µé¢ä¸ï¼webpack åªæ¯å建ä¸ä¸ª script æ ç¾æ¥å è½½å ¶ä»£ç ï¼ï¼å该 catch å¤çç¨åºå°ä¸ä¼å¯å¨ï¼ç´å° chunkLoadTimeout æªéè¿ãæ¤è¡ä¸ºå¯è½æ¯ææä¹å¤çãä½è¿æ¯å¯ä»¥è§£éç ââ webpack ä¸è½æåºä»»ä½é误ï¼å 为 webpack ä¸ç¥éé£ä¸ªèæ¬å¤±è´¥äºãwebpack å°å¨é误åçåç«å³å° onerror å¤çèæ¬æ·»å å° script ä¸ã
å¯ä»¥éè¿æ·»å èªå·±ç onerror å¤çèæ¬é¿å ä¸è¿°é®é¢ï¼è¿è½å¤å¸®å©å¨é误åçæ¶ç§»é¤è¯¥èæ¬
<script
src="https://example.com/dist/dynamicComponent.js"
async
onerror="this.remove()"
></script>è¿ç§æ åµä¸éè¯¯èæ¬å°è¢«å é¤ï¼è webpack å°å建èªå·±çèæ¬ï¼å¹¶ä¸ä»»ä½é误é½å°è¢«å¤çèæ²¡æä»»ä½è¶ æ¶ã
䏿¦å¼å§å离代ç ï¼ä¸ä»¶å¾æå¸®å©çäºæ æ¯ï¼åæè¾åºç»ææ¥æ£æ¥æ¨¡åå¨ä½å¤ç»æã宿¹åæå·¥å · æ¯ä¸ä¸ªä¸éçå¼å§ãè¿æä¸äºå ¶ä»ç¤¾åºæ¯æçå¯é项ï¼
æ¥ä¸æ¥ï¼åé
æå è½½ äºè§£å¦ä½å¨çå®çåºç¨ç¨åºä¸ä½¿ç¨ import()ï¼ä»¥ååé
ç¼å äºè§£å¦ä½ææå°è¿è¡ä»£ç å离ã