文章目录
- 项目目录
- 搭建项目
- my-raw-loader
- 参数
- schema-utils
- tpl-loader
项目目录
让我们实现一些简易的loader
,从大量的简易loader的实现过程中学习编写如何 webpack loader
├── loaders # loader目录
├── src # 业务代码
│ │── index.html
│ └── index.js
├── .gitignore
├── package.json
├── package-lock.json
└── webpack.config.js # webpack 配置文件
搭建项目
mkdir loaders
cd loaders
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);
my-raw-loader
src/happy-new-year.txt
🎉🎉🎆🎆🧨🧨
新年快乐!大吉大利!
🎉🎉🎆🎆🧨🧨
执行 npx webpack-dev-server
,会发现编译报错了
那么下面我们就实现 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',
}),
],
};
loaders/my-raw-loader.js
function myRawLoader(source) {
console.log('source', source);
}
module.exports = myRawLoader;
执行 npx webpack-dev-server
可以看到打印结果,这个参数是一个字符串
参数
修改 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);
// 这里一定要返回字符串或者 buffer
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
由webpack 官方提供, 它配合 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);
// 这里一定要返回字符串或者 buffer
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,
},
},
],
},
tpl-loader
待续,马上…