三种本地开发测试 loader
的方法
1. 匹配(test)单个 loader
你可以通过在 rule 对象使用 path.resolve
指定一个本地文件:
webpack.config.js
const path = require('path');
module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve('path/to/loader.js'),
options: {
/* ... */
},
},
],
},
],
},
};
2. 匹配(test)多个 loaders
你可以使用 resolveLoader.modules
配置,webpack 将会从这些目录中搜索这些 loaders。例如,如果你的项目中有一个 /loaders
本地目录:
webpack.config.js
const path = require('path');
module.exports = {
//...
resolveLoader: {
modules: ['node_modules', path.resolve(__dirname, 'loaders')],
},
};
3. npm link
如果你已经为 loader 创建了独立的库和包,你可以使用 npm link
来将其链接到你要测试的项目。
项目目录
让我们实现一个简易的raw-loader
,我们将其命名为 my-raw-loader
。这个loader的功能就是支持javascript
引用文件原始文本内容
├── loaders # loader目录
├── src # 业务代码
│ │── happy-new-year.txt
│ │── index.html
│ └── index.js
├── .gitignore
├── package.json
├── package-lock.json
└── webpack.config.js # webpack 配置文件
搭建项目
mkdir my-loader
cd my-loader
npm init -y
npm i -D webpack webpack-cli html-webpack-plugin webpack-dev-server loader-utils
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
mode: 'development',
plugins: [
new HtmlWebpackPlugin({
title: '自定义 webpack loader',
template: './src/index.html',
}),
],
};
src/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
</body>
</html>
src/index.js
import text from './happy-new-year.txt';
const textDom = document.createElement('p');
textDom.style.cssText = 'width: 200px;height: 200px;background-color: pink;';
textDom.innerText = text;
document.body.appendChild(textDom);
src/happy-new-year.txt
🎉🎉🎆🎆🧨🧨
新年快乐!大吉大利!
🎉🎉🎆🎆🧨🧨
执行 npx webpack-dev-server
,会发现编译报错了
那么下面我们就实现 my-raw-loader
来抛砖引玉!
my-raw-loader
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /.txt$/,
use: [
{
loader: path.resolve(__dirname, 'loaders/my-raw-loader'),
options: {
esModule: true,
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: '自定义 webpack loader',
template: './src/index.html',
}),
],
};
参数
当一个 loader 在资源中使用,这个 loader 只能传入一个参数 - 一个包含资源文件内容的
字符串
。loader 会返回一个或者两个值。第一个值的类型是 JavaScript 代码的
字符串
或者buffer
loaders/my-raw-loader.js
function myRawLoader(source) {
console.log('source', source);
}
module.exports = myRawLoader;
执行 npx webpack-dev-server
可以看到打印结果,这个参数是一个字符串
简单实现一个 loader
修改 loaders/my-raw-loader.js
function myRawLoader(source) {
// 提取给定的 loader 选项,
// 从 webpack 5 开始,this.getOptions 可以获取到 loader 上下文对象。它用来替代来自 loader-utils 中的 getOptions 方法。
const { esModule } = this.getOptions();
console.log('esModule:', esModule);
if (!esModule) {
return `module.exports = ${JSON.stringify(source)}`;
}
return `export default ${JSON.stringify(source)}`;
}
module.exports = myRawLoader;
执行 npx webpack-dev-server
可以看到通过 this.getOptions()
获取到了当前 loader 的配置,并且编译未报错,访问 http://localhost:8080/ 页面得偿所愿!成功读取并渲染了原始文本内容。
schema-utils
schema-utils
包配合 loader-utils
,用于保证 loader 选项,进行与 JSON Schema 结构一致的校验
const { validate } = require('schema-utils');
const schema = {
type: 'object',
properties: {
esModule: {
type: 'boolean',
}
},
"additionalProperties": false // 是否允许不存在的选项传入
};
function myRawLoader(source) {
const options = this.getOptions();
validate(schema, options, {
name: 'my-raw-loader',
baseDataPath: 'options',
});
// 提取给定的 loader 选项,
// 从 webpack 5 开始,this.getOptions 可以获取到 loader 上下文对象。它用来替代来自 loader-utils 中的 getOptions 方法。
console.log('esModule:', options.esModule);
if (!options.esModule) {
return `module.exports = ${JSON.stringify(source)}`;
}
return `export default ${JSON.stringify(source)}`;
}
module.exports = myRawLoader;
如果传入未定义的选项,则会发生编译报错
{
test: /.txt$/,
use: [
{
loader: path.resolve(__dirname, 'loaders/my-raw-loader'),
options: {
esModule2: true,
},
},
],
},
源码地址:https://gitee.com/yanhuakang/webpack-demos/tree/master/advanced/step_17-custom-loader