欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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