外观
Loader 和 Plugin 怎么区分?
Loader 是转换器,输入源码,输出新的源码,并且只处理匹配到的那一类文件。Plugin 监听打包过程的事件,可以改输出、注入变量、生成额外文件。
原理
Loader 链式执行,配置里写在后面的先执行。处理脚本、样式和资源引用的 Loader 各自做一种转换。一个 Loader 应当只做一件事,方便复用。
手写 Loader 时,从 this.async() 取得回调,用 this.resourcePath 知道文件是谁。返回的内容要能被下一个 Loader 接受。如果还读了别的文件,要声明依赖,否则监听模式不知道何时重编。
Plugin 是带 apply(compiler) 的对象。在 compiler 或某次 compilation 的钩子上注册。生成 HTML、定义环境变量、提取 CSS、压缩,都发生在构建的某个阶段,而不是在读单个源文件的时候。
不要在 Loader 里去改整个输出目录。那会在每个匹配到的文件上重复执行。
追问
执行顺序为什么容易错?
Loader 从右到左、从下到上。先把 TypeScript 转成 JavaScript,再交给后续处理。写反了,后面的 Loader 会看到不认识的语法。
和 Vite 插件的关系?
Vite 插件按 Vite 和 Rollup 的钩子写,不是 Webpack 的 Compiler 钩子。职责仍然类似:有的做单文件转换,有的参与打包结果。见 Vite 与 Webpack。
易错点
- 用 Plugin 去做单文件语法转换,或用 Loader 去改最终的文件列表。
- Loader 写成有状态的单例,并行编译时互相污染。
- 忘记声明额外依赖,改了被引用的文件却不重新构建。