webpack学习4-手写loader
程序员文章站
2024-02-11 11:14:34
...
1.loader概念
loader本质上是一个对不同文件处理的函数
2.准备工作
1. 下载一些包
1. webpack
2. webpack-cli
3. loader-utils // webapck自带的loader工具库
4. schema-utils // 校验工具库
5. @babel/core babel核心
6. @babel/preset-env babel预设环境
2. 研究下loader的特性
1. 基础结构
module.exports = function(content, map, meta){
console.log(222);
return content;
}
module.exports.pitch = function (){
console.log('pitch222');
}
2. 写法分为异步和同步
const {getOptions} = require('loader-utils'); // 获取options
const {validate} = require('schema-utils'); // 校验方法
// 使用json作为校验规则,其中属性additionalProperties代表是否允许新增属性
// 一定要注意大小写
const schema = require('./schema.json');
/**
* 异步写法 推荐异步写法 会等待文件的处理完成
* params 原来文件的内容,sourcemap ,元信息
*/
module.exports = function(content, map, meta){
console.log(111)
const options = getOptions(this);
console.log(options);
// 三个参数为 校验规则, 待校验的内容 , 提示配置
validate(schema,options, {
name: 'loader1' // 报错的loade名字
});
const callback = this.async();
setTimeout(()=>{
callback(null, content);
},10);
}
/**
* 同步写法1 推荐异步写法
* params 原来文件的内容,sourcemap ,元信息
*/
// module.exports = function(content, map, meta){
// console.log(111);
// return content;
// }
/**
* 同步写法2
* params 原来文件的内容,sourcemap ,元信息
*/
// module.exports = function(content, map, meta){
// console.log('111');
// // 第一个参数是错误信息
// this.callback(null, content, map, meta);
// }
3. 执行顺序
// loader执行顺序是倒着执行的,module.exports.pitch 的函数却是正序执行的
// 因此可以看作类似洋葱的结构,
// module.exports.pitch 处于加载阶段,正序执行
// loader处于执行阶段,倒序执行
// 如果 处于加载阶段 的pitch 有返回值, 将会中断当前loader和之后的loader的加载,也就是加载失败
// 将不会执行 pitch 有返回值后的loader
// webpack.config.js
use: [
'loader1',
'loader2',
'loader3',
]
// loader.js
/**
* pitch方法
* 加载loader时调用
*/
module.exports.pitch = function (){
console.log('pitch111');
}
3. 自定义一个babel-loader
1. webpack.config.js
const path = require('path');
module.exports = {
mode: 'production',
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
// loader执行顺序是倒着执行的,module.exports.pitch 的函数却是正序执行的
// 因此可以看作类似洋葱的结构,
// module.exports.pitch 处于加载阶段,正序执行
// loader处于执行阶段,倒序执行
// *~ 如果 处于加载阶段 的pitch 有返回值, 将会中断当前loader和之后的loader的加载,也就是加载失败
// 将不会执行 pitch 有返回值后的loader
use: [
{
loader: 'babelLoader',
options: {
presets: [
'@babel/preset-env'
]
}
}
]
}
]
},
resolveLoader:{ // 配置加载loader的路径
modules: [
"node_modules",
path.resolve(__dirname,'loaders')
]
}
}
2. babelLoader.js
const {getOptions} = require('loader-utils'); // 获取options
const {validate} = require('schema-utils'); // 校验方法
// 使用json作为校验规则,其中属性additionalProperties代表是否允许新增属性
// 一定要注意大小写
const schema = require('./babelschema.json');
// 引入babel核心主要使用 babel.transform 他是一个普通的异步方法
const babel = require('@babel/core');
// nodejs的工具方法, 主要使用util.promisify转换为promise
const util = require('util');
// 转换babel.transform 为 promise方法
const transform = util.promisify(babel.transform);
/**
* 异步写法 推荐异步写法 会等待文件的处理完成
* params 原来文件的内容,sourcemap ,元信息
*/
module.exports = function(content, map, meta){
const options = getOptions(this);
// 三个参数为 校验规则, 待校验的内容 , 提示配置
validate(schema,options, {
name: 'loader1' // 报错的loade名字
});
const callback = this.async();
// 使用babel 编译代码
transform(content,options)
.then(({code, map})=>{ // 返回 code 和 sourcemap
console.log(code);
callback(null, code, map, meta);
})
.catch((e)=>{
console.log(e)
});
}
3. babelSchema.json
{
"type": "object",
"properties": {
"presets": {
"type": "array",
"description": "preset"
}
},
"additionalProperties": true
}
推荐阅读
-
webpack学习4-手写loader
-
webpack手写loader ---- style-loader
-
Vue + Webpack + Vue-loader学习教程之功能介绍篇
-
Vue + Webpack + Vue-loader学习教程之相关配置篇
-
Vue学习之webpack调用第三方loader(十五)
-
脱离脚手架来配置、学习 webpack4.x (二)基础搭建loader 配置 css、scss
-
手写一个webpack(loader、plugin)
-
Webpack学习-Loader
-
Vue + Webpack + Vue-loader学习教程之功能介绍篇
-
Vue + Webpack + Vue-loader学习教程之相关配置篇