0%

webpack

主要成分

每一个文件都是一个ModuleModule形成ModuleGraph。打包过程将module组合成chunks。chunks组合成chunk group并形成一个由module互联的ChunkGraph。当指定entry point时,底层创建带有一个chunk的chunk group。

1
2
3
module.exports = {
entry: './index.js',
};

创建一个名为main的chunk group(main是入口点的默认名字)。这个chunk group包含 ./index.jsmodule,当parser处理index.js中的import时,新的module添加到这个chunk。

1
2
3
4
5
6
module.exports = {
entry: {
home: './home.js',
about: './about.js',
},
};

两个chunk group被创建了,名字分别是home和about。每一个都有一个chunk,home chunk group包含home,about chunk group包含about。

一个chunk group可能包含多个chunk。splitChunksPlugin将一个chunk分割成一个或者多个chunks。

chunks

chunk有两种形式,一种为initial,是入口点的main chunk。这个chunk包含为入口点指定的所有模块和依赖项。另外一种是non-initial,可能被懒加载,当使用dynamic import或者splitChunksPlugin时可能出现。

每个chunk可能有对应的asset,assets就是输出的文件,也就是打包的结果。

1
2
3
4
// webpack.config.js
module.exports = {
entry: './src/index.jsx',
};
1
2
3
4
5
6
7
// src/index.jsx
import React from 'react';
import ReactDOM from 'react-dom';

import('./app.jsx').then((App) => {
ReactDOM.render(<App />, root);
});

名为main的initial chunk被创建了,包含index.jsx、react和react-dom和他们所有的依赖,除了app.jsx。

对于app.jsx,一个non-initial chunk被创建了,因为这个module是动态引入的。

最终输出两个chunk,分别是:

  • /dist/main.js——一个initialchunk
  • /dist/394.js——一个non-initialchunk

默认情况下,non-initialchunk没有名称,故使用了一个唯一id代替。当使用动态import时,可以用magic comment显式指定chunk的名称。

1
2
3
4
5
6
import(
/* webpackChunkName: "app" */
'./app.jsx'
).then((App) => {
ReactDOM.render(<App />, root);
});

输出:

  • /dist/main.js——initial chunk
  • /dist/app.js —— non-initial chunk

输出

输出文件的名称受配置文件两个字段的影响:

  • output.filename —— 针对initial chunk文件
  • output.chunkFilename —— 针对non-initialchunk文件
  • 某些情况下,initialnon-initial被用于chunk,这个时候output.filename被使用。

一些占位符可用,如:

  • [id] —— chunk id([id].js -> 555.js)
  • [name] —— chunk name, 没名字的,使用ID
  • [contenthash] —— 输出文件内容的md4 hash,如[contenthash].js -> 4ea6ff1de66c537eb9b2.js