这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战node
loader 用于对模块的源代码进行转换webpack
path.resolve
指向这个本地文件resolveLoader.modules
配置npm link
var
关键词替换为 const
# loader.js
module.exports = function (source) {
return source.replace(/var/g, 'const')
}
# index.js
function test() {
var a = 1;
var b = 2;
var c = 3;
console.log(a, b, c);
}
test()
# wepback.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /.js$/,
use: [
{
loader: path.resolve('./src/loader1.js'),
},
]
}
]
},
}
# `npm run build`,获得打包文件 `bundle.js`
复制代码
loaders 应该只作单一任务。这不只使每一个 loader 易维护,也能够在更多场景链式调用。git
利用 loader 能够链式调用的优点。写五个简单的 loader 实现五项任务,而不是一个 loader 实现五项任务;github
loader 能够被链式调用意味着不必定要输出 JavaScript。只要下一个 loader 能够处理这个输出,这个 loader 就能够返回任意类型的模块web
确保 loader 在不一样模块转换之间不保存状态。每次运行都应该独立于其余编译模块以及相同模块以前的编译结果。npm
充分利用
loader-utils
包。它提供了许多有用的工具,但最经常使用的一种工具是获取传递给 loader 的选项。schema-utils
包配合loader-utils
,用于保证 loader 选项,进行与 JSON Schema 结构一致的校验。这里有一个简单使用二者的例子:json
loader.jsapi
import { getOptions } from 'loader-utils';
import validateOptions from 'schema-utils';
const schema = {
type: 'object',
properties: {
test: {
type: 'string'
}
}
}
export default function(source) {
const options = getOptions(this);
validateOptions(schema, options, 'Example Loader');
// 对资源应用一些转换……
return `export default ${ JSON.stringify(source) }`;
};
复制代码
若是一个 loader 使用外部资源(例如,从文件系统读取),必须声明它。这些信息用于使缓存 loaders 无效,以及在观察模式(watch mode)下重编译。下面是一个简单示例,说明如何使用
addDependency
方法实现上述声明:数组
loader.js缓存
import path from 'path';
export default function(source) {
var callback = this.async();
var headerPath = path.resolve('header.js');
this.addDependency(headerPath);
fs.readFile(headerPath, 'utf-8', function(err, header) {
if(err) return callback(err);
callback(null, header + "\n" + source);
});
};
复制代码
根据模块类型,可能会有不一样的模式指定依赖关系。例如在 CSS 中,使用
@import
和url(...)
语句来声明依赖。这些依赖关系应该由模块系统解析。
能够经过如下两种方式中的一种来实现:
require
语句。this.resolve
函数解析路径避免在 loader 处理的每一个模块中生成通用代码。相反,你应该在 loader 中建立一个运行时文件,并生成
require
语句以引用该共享模块。
不要在模块代码中插入绝对路径,由于当项目根路径变化时,文件绝对路径也会变化。
loader-utils
中的stringifyRequest
方法,能够将绝对路径转化为相对路径。
若是你的 loader 简单包裹另一个包,你应该把这个包做为一个
peerDependency
引入。这种方式容许应用程序开发者在必要状况下,在package.json
中指定所需的肯定版本
当你遵循上面的用法准则编写了一个 loader,而且能够在本地运行。下一步该作什么呢?让咱们用一个简单的单元测试,来保证 loader 可以按照咱们预期的方式正确运行。咱们将使用 Jest 框架。而后还须要安装
babel-jest
和容许咱们使用import
/export
和async
/await
的一些预设环境(presets)。让咱们开始安装,而且将这些依赖保存为devDependencies
:
npm install --save-dev jest babel-jest babel-preset-env
复制代码
.babelrc
{
"presets": [[
"env",
{
"targets": {
"node": "4"
}
}
]]
复制代码
仅供学习参考