幕后

本节描述了 webpack 的内部机制,对插件开发者很有用。

打包是一个函数,它接收一些文件并输出另一些文件。

但在输入和输出之间,它还有模块(modules)入口点(entry points)、代码块(chunks)、代码块组(chunk groups)以及许多其他中间部分。

主要部分

项目中使用的每个文件都是一个模块(Module)

./index.js

import app from './app.js';

./app.js

export default 'the app';

通过相互引用,模块会形成一个图(ModuleGraph)。

在打包过程中,模块被组合成代码块。代码块再组合成代码块组,并通过模块相互连接形成一个图(ChunkGraph)。当你描述一个入口点时,在底层机制上,你创建了一个包含一个代码块的代码块组。

./webpack.config.js

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

创建了一个名为 main 的代码块组(main 是入口点的默认名称)。这个代码块组包含 ./index.js 模块。当解析器处理 ./index.js 内部的导入时,新的模块会被添加到这个代码块中。

另一个例子

./webpack.config.js

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

创建了两个名为 homeabout 的代码块组。每个代码块组都含有一个代码块和一个模块 —— home 对应 ./home.jsabout 对应 ./about.js

一个代码块组中可能有多个代码块。例如 SplitChunksPlugin 会将一个代码块拆分成一个或多个代码块。

代码块

代码块有两种形式

  • initial 是入口点的主代码块。此代码块包含你为入口点指定的所有模块及其依赖。
  • non-initial 是一个可能被延迟加载的代码块。它在使用动态导入(dynamic import)SplitChunksPlugin时可能会出现。

每个代码块都有一个对应的资源(asset)。资源就是输出文件 —— 打包的结果。

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);
});

创建了名为 main 的 initial 代码块。它包含

  • ./src/index.jsx
  • react
  • react-dom

及其所有依赖,除了 ./app.jsx

由于 ./app.jsx 模块是动态导入的,因此为其创建了 non-initial 代码块。

输出

  • /dist/main.js - 一个 initial 代码块
  • /dist/394.js - non-initial 代码块

默认情况下,non-initial 代码块没有名称,因此会使用唯一 ID 而不是名称。在使用动态导入时,我们可以通过使用“魔法注释”("magic" comment)来显式指定代码块名称

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

输出

  • /dist/main.js - 一个 initial 代码块
  • /dist/app.js - non-initial 代码块

输出

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

  • output.filename - 用于 initial 代码块文件
  • output.chunkFilename - 用于 non-initial 代码块文件
  • 在某些情况下,initial 和 non-initial 代码块会同时使用。在这些情况下,会使用 output.filename

这些字段中可以使用一些占位符。最常用的是

  • [id] - 代码块 ID(例如 [id].js -> 485.js
  • [name] - 代码块名称(例如 [name].js -> app.js)。如果代码块没有名称,则会使用其 ID。
  • [contenthash] - 输出文件内容的 md4 哈希值(例如 [contenthash].js -> 4ea6ff1de66c537eb9b2.js

4 贡献者

smelukovEugeneHlushkochenxsanamirsaeed671