编写自定义 loader
loader 能做什么?
webpack loader 是用于编译源文件为目标文件,默认情况,webpack 只能编译打包 JavaScript 文件,其他文件则需要特定 loader 进行加载,如:
css文件模块,加载器为css-loader(配合style-loader或者MiniCssExtractPlugin.loader)less文件模块,加载器为less-loader(配合预处理其 less)png|jpg|jpeg|gif|svg图片,加载器为url-loader,file-loader
执行顺序
- 执行顺序为从左到右(从下到上)
- 导出
loader函数,也可添加pitch方法(类似 koa 的洋葱模型)- 配置 loaders ['loader1', 'loader2']
- 执行顺序 loader1.pitch => loader2.pitch => loader2.pitch => loader1.pitch
babel-loader
简单实现 babel-loader 转译高级 JavaScript 语法 loaders/babel-loader
const babel = require('@babel/core');
function loader(source, inputSourceMap) {
// 启用缓存
this.cacheable();
// 供 webpack 调用
const options = {
presets: ['@babel/preset-env'],
inputSourceMap,
sourceMap: true,
filename: this.request.split('!')[1].split('/').pop()
};
// this.request 数据格式
// E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\loaders\\babel-loader.js!E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\src\\index.js
let { code, map, ast } = babel.transform(source, options);
return this.callback(null, code, map, ast);
}
module.exports = loader;
这里用到 webpack.config.resolveLoader,解析 loader, 可配置别名,查找路径
webpack.config.js
{
resolveLoader: {
alias: {
'babel-loader': resolve('./loaders/babel-loader'),
},
modules: [ resolve('./loaders'), 'node_modules' ]
},
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader' }
]
}
}
banner-loader
为代码添加注释,表明代码版权,或者编写人,时间等信息
banner-loader.js
const babel = require('@babel/core');
function loader(source, inputSourceMap) {
this.cacheable && this.cacheable();
// 供 webpack 调用
const options = {
presets: ['@babel/preset-env'],
inputSourceMap,
sourceMap: true,
filename: this.request.split('!')[1].split('/').pop()
};
// this.request 数据格式
// E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\loaders\\babel-loader.js!E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\src\\index.js
let { code, map, ast } = babel.transform(source, options);
return this.callback(null, code, map, ast);
}
module.exports = loader;
bannder.js
/**
* Copyright: Xiangju
* Author: stella
*/
webpack.config.js
{
resolveLoader: {
alias: {
'babel-loader': resolve('./loaders/babel-loader'),
+ 'banner-loader': resolve('./loaders/banner-loader'),
},
},
module: {
rules: [
{ test: /\.js$/, use: [
{
loader: 'banner-loader',
+ options: {
+ filename: resolve('./loaders/banner.js'),
+ }
},
'babel-loader',
] }
]
},
}
总结
以上实现的自定义 loader,比较基础,属于入门级。