Webpack加载器顺序:什么是Webpack预先和后置加载器,它们与一串加载器有何不同?

16
我知道在最新的Webpack中,我们可以指定module.rules选项enforce:'pre'使某个loader作为“pre-loader”运行,如文档所述。
但是我找不到任何关于什么是pre-loader和post-loader的适当解释。当然我们可以从逻辑上思考"pre"在"post"之前运行,但我不明白究竟发生了什么(为什么没有记录?)。
这也考虑到已经有一种方法可以通过查看文档中的Rule.use属性来指定装载程序的顺序,该属性表示装载程序可以通过传递多个装载程序链接在一起,这些装载程序将从右到左应用(最后一个配置的先应用) 因此,有两个相关的问题:
  • 链接、pre和post之间的区别是什么?
  • 是否有一种更详细的webpack日志记录链的顺序,以了解先后顺序?
PS1:我知道SO上有类似的问题,但我找不到任何链接到详细解释加载顺序的文档片段。
PS2:我运行typescript、tslint和babel,我想了解正确的链接过程和各个步骤中实际发生的情况。
2个回答

25

为了找出答案,我编写了自己的加载器a-loader.jsh-loader.js,它们接受内容,打印日志,然后返回内容。每个加载器文件都有一个正常阶段和一个 pitching 阶段以保证完整性。您可以在此处阅读关于 pitching 加载器的信息:https://webpack.js.org/api/loaders/#pitching-loader

a-loader.js:

module.exports = function(content) {
  console.log('Loader A, normal phase.');
  return content;
};

module.exports.pitch = function(remainingRequest, precedingRequest, data) {
  console.log('Loader A, pitching phase.');
}

所有的加载程序代码都是一样的,除了我将日志记录语句更改为记录加载程序的内容。

我的webpack-config.js是这样的:

  module: {
    rules: [
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/a-loader.js')}],
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/b-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/c-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/d-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/e-loader.js')}],
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/f-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/g-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/h-loader.js')}]
      },
    ]
  }

输出:

Loader A, pitching phase.
Loader B, pitching phase.
Loader C, pitching phase.
Loader D, pitching phase.
Loader E, pitching phase.
Loader F, pitching phase.
Loader G, pitching phase.
Loader H, pitching phase.
Loader H, normal phase.
Loader G, normal phase.
Loader F, normal phase.
Loader E, normal phase.
Loader D, normal phase.
Loader C, normal phase.
Loader B, normal phase.
Loader A, normal phase.

没有意外。先运行 pitching 阶段,然后再运行正常阶段。正如你所指出的那样,普通阶段的加载器是从右往左应用的。h 在普通阶段中是首先处理的,因为它在数组(链)中最靠右。我有一个有用的方法来记住 pitching 的顺序。只需想象一下正常阶段的顺序,并想象一个在正常顺序上方投影的镜像图像。这个镜像图像就是 pitching 的顺序。

接下来,我调整了 webpack.config.js 如下:

  • pre: a, h
  • post: d, f
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/a-loader.js')}],
        enforce: "pre"
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/b-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/c-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/d-loader.js')}],
        enforce: "post"
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/e-loader.js')}],
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/f-loader.js')}],
        enforce: "post"
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/g-loader.js')}]
      },
      {
        test: /\.js$/,
        use: [{loader: path.resolve('loaders/h-loader.js')}],
        enforce: "pre"
      },
    ]
  }

输出:

Loader D, pitching phase.
Loader F, pitching phase.
Loader B, pitching phase.
Loader C, pitching phase.
Loader E, pitching phase.
Loader G, pitching phase.
Loader A, pitching phase.
Loader H, pitching phase.
Loader H, normal phase.
Loader A, normal phase.
Loader G, normal phase.
Loader E, normal phase.
Loader C, normal phase.
Loader B, normal phase.
Loader F, normal phase.
Loader D, normal phase.

暂时忽略分块阶段,因为它们只是正常阶段的镜像反映。将enforce: prepost视为分组。"pre"是第一组,然后是未标记的"normal"组,最后是"post"组。在正常阶段中,第一个加载器是h,因为它在"pre"组中并且在数组中最右边。接下来是a,因为它是另一个在"pre"组中的加载器。接下来是"未分组"的gecb,从右到左依次运行。最后是"post"组,fd从右到左顺序运行。

我不知道为什么这在webpack网站上没有更好的文档说明。


0

webpack loader 的 normal 和 pitch period 有点棘手。似乎 'pre' 是 pitch,而 'post' 是 normal。Normal 只将单个文件视为字符串并将字符串返回给 webpack 核心。然而,pitch 就像是预编译期,为 webpack 的 resolveModule 制作离散的 Map<request, codeChunk>。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接