webpack loader和plugin配置项
npx webpack –mode=development
1 | module: { |
loader
简单来说,loader就是一个nodejs模块,loader 是导出为一个函数的 node 模块。该函数在 loader 转换资源的时候调用。给定的函数将调用 API,并通过 this 上下文访问。
比如这样
1 | const loaderUtils = require('loader-utils'); // loader 工具库 ,调用loaderUtils.getOptions拿到webpack配置参数 |
loader前置知识
loader 支持链式调用。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个 loader,返回 webpack 所期望的 JavaScript。
loader 可以是同步的,也可以是异步的。
loader 运行在 Node.js 中,并且能够执行任何操作。
loader 可以通过 options 对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。
除了常见的通过 package.json 的 main 来将一个 npm 模块导出为 loader,还可以在 module.rules 中使用 loader 字段直接引用一个模块。
插件(plugin)可以为 loader 带来更多特性。loader 能够产生额外的任意文件
手写loader
4种本地开发测试的方法
匹配(test)单个 loader,你可以简单通过在 rule 对象设置 path.resolve 指向这个本地文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15module: {
rules: [
{
test: /\.js$/,
use: {
// loader: path.join(__dirname, '../loader/cpp-loader,js'),
// loader: 'cpp-test-loader',
loader: path.resolve('./loader/cpp-test-loader.js'),
options: {
log: 'hello 这是我目前用的loader'
}
}
}
]
},匹配(test)多个 loaders,你可以使用 resolveLoader.modules 配置,webpack 将会从这些目录中搜索这些 loaders。例如,如果你的项目中有一个 /loaders 本地目录:
1
2
3resolveLoader: {
modules: ['node_modules', path.resolve(__dirname, 'loader')]
},还阔以通过resolveLoader配置别名的方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18resolveLoader: {
alias: {
'a-loader': path.resolve(__dirname, 'loader/a.js')
}
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'a-loader',
options: {
test: 'hello this is options'
}
}
}
]
}npm link 软连接的方式调试独立库和包,来将其关联到你要测试的项目。node模块根目录下 运行 npm link,项目里使用 npm link cpp-test-loader。其实跟调试单独的npm包一模一样。
使用 loader-utils 能够编译 loader 的配置,还可以通过 schema-utils 对传递的配置进行验证
1 | // webpack.config.js |
同步 loader
无论是 return 还是 this.callback 都可以同步地返回转换后的 content 内容:
1 | module.exports = function(content, map, meta) { |
this.callback灵活 支持多个参数
1 | module.exports = function(content, map, meta) { |
异步 loader
对于异步 loader,使用 this.async 来获取 callback 函数:
1 | module.exports = function(content, map, meta) { |
plugin
为社区用户提供一种强大方式来触及webpack编译过程(compilation process),插件能够 钩入(hook) 到在每个编译(compilation)中触发的所有关键事件。在编译的每一步,插件都具备完全访问 compiler 对象的能力,如果情况合适,还可以访问当前 compilation 对象。
在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。
compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。
compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。
这两个组件是任何 webpack 插件不可或缺的部分(特别是 compilation),因此,开发者在阅读源码,并熟悉它们之后,会感到获益匪浅:
plugin前置知识
1 | const webpack = (options) => { |
手写plugin
webpack 插件由以下组成:
- 一个 JavaScript 命名函数,构造函数。
- 在插件函数的 prototype 上定义一个 apply 方法。
- 指定一个绑定到 webpack 自身的事件钩子。(compiler.hooks.emit // Compiler.emit() 输出到dist目录)
- 处理 webpack 内部实例的特定数据。(主要是处理compilation,比如检索遍历资源(asset)、chunk、模块和依赖、监听 chunk 的修改)
- 功能完成后调用 webpack 提供的回调
1 | // plugin.js |
plugin实例
island-webpack-plugin 是一个在 bundle 中添加作者信息的插件,这个插件同样是在 emit 这个钩子上触发的,同样是获取 source 后对 source 添加作者信息的字符串。
1 | class AuthorPlugin { |
令人执行的compiler里的钩子函数