Q: Loader 的执行顺序是什么?为什么是这个顺序?
Loader 是一组串行执行的过程。
这是 Webpack (及其前身) 对 Loader 的默认调用顺序。因为它是按照函数式编程 (Functional Programming) 的组合 (Compose) 思想设计的。
配置示例:
如果你看过 Loader 的源码,你会发现 Loader 还有一个 pitch 属性 (也是个函数)。
Loader 的完整执行过程其实分为两个阶段: Pitching 和 Normal。
style-loader.pitch -> css-loader.pitch -> less-loader.pitchless-loader -> css-loader -> style-loader特殊机制:如果在 Pitching 阶段某个 Loader 的 pitch 方法直接返回了非 undefined 的值,那么后续的 Pitching Loaders 和 Normal Loaders 都会被跳过,直接回头执行前一个 Loader 的 Normal 阶段。这也叫 熔断机制。
Webpack 内部使用 loader-runner 这个独立的库来运行 Loader。它负责处理 Pitching 和 Normal 阶段的转换,以及异步 Loader (this.async()) 的等待。
为了让 Loader 有机会跳过后续的处理过程,或者在处理之前获取 metadata。
最典型的例子是 style-loader。当你 require('./style.css') 时,style-loader 的 pitch 方法会被执行。它会生成一段 JS 代码 (包含 require('./style.css') 的 Request 字符串),通过 !! (忽略其他 loader) 再次请求自身 (Normal 阶段),从而解决循环引用问题,并将生成的 CSS 内容注入到 DOM 中。这涉及到了 Loader 之间的数据传递和请求拦截。