🗒️内部原理

来自官网 https://webpack.js.org/concepts/under-the-hood/

bundling(打包)的输入是一些文件,输出是其它一些文件。但在输入和输出之间,它还有 modules(模块)、entry points(入口点)、chunks(块)、chunk groups 和许多其他中间部分。

1. 主要部分

项目中使用的每个文件都是一个 module。通过互相引用(export 和 import),这些 modules 会形成一张 graph,即 ModuleGraph

在 bundling 过程中,modules 被组合成 chunks,chunks 组合成 chunk group,并形成一张图 ModuleGraph —— 通过 modules 相互连接的图。

eg1. 指定一个 entry point

// webpack.config.js
module.exports = {
  entry: './index.js',
};

以上代码,会在内部创建一个只有一个 chunk 的 chunk group(默认名字叫 main)。chunk group 包含了一个 ./index.js module,当 parser 处理 ./index.js 里的 imports 时,新 modules 就被添加到这个 chunk 里。

eg2. 指定多个 entry points

// webpack.config.js
module.exports = {
  entry: {
    home: './home.js',
    about: './about.js',
  },
};

以上代码,会创建名为 homeabout 的两个 chunk groups,每个 chunk group 都有个带一个 module 的 chunk,其中模块 ./home.js 用于 home,模块 ./about.js 用于 about

说明:一个 chunk group 可能有多个 chunks,比如 SplitChunksPlugin 会将一个 chunk 拆分为一个或多个 chunks。

2. chunks

chunk 有两种形式:

  • initial 是 entry point 的 main chunk。该 chunk 包含为 entry point 指定的所有 modules 及其 dependencies

  • non-initial 是一个可以 lazy-loaded 的 chunk。它可能出现在 dynamic import 或 SplitChunksPlugin

每个 chunk 都有对应的 asset(资源),即 bundling 结果的 output files。

// webpack.config.js
module.exports = {
  entry: './src/index.jsx',
};

// ./src/index.jsx
import React from 'react';
import ReactDOM from 'react-dom';

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

以上代码的 chunk:

  • 会创建一个名为 main 的 initial chunk,它包含 ./src/index.jsx, react, react-dom,以及它们的依赖——不包括 ./app.jsx

  • 还会为 ./app.jsx 创建一个 non-initial chunk,因为那个 module 是动态引入的。

以上代码的 output:

  • /dist/main.js 一个 initial chunk

  • /dist/394.js 一个 non-initial chunk

默认情况下,这些 non-initial chunks 没有名字,因此会使用唯一 ID 来替代名称。在使用 dynamic import 时,我们可以通过 magic comment 来显式指定 chunk 名称。如下:

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

以上代码的 output:

  • /dist/main.js 一个 initial chunk

  • /dist/app.js 一个 non-initial chunk

3. output

output files 的名字受配置中两个字段的影响:

  • output.filename 用于 initial chunk 文件

  • output.chunkFilename 用于 non-initial chunk 文件

  • 在某些情况下,chunks 会使用 initialnon-initial,此时可以使用 output.filename

在这些字段中可以使用一些占位符,常用的有:

  • [id] chunk id

  • [name] chunk name。若 chunk 没有 name 则会使用其 id

  • [contenthash] 输出文件内容的 md4-hash

Last updated