webpack-自定义loader

如何自己编写一个loader:

loader是一个函数,声明式函数,不能使用箭头函数;拿到源码,做进一步的修饰处理,再返回处理后的源码就可以了

官方文档:https://webpack.js.org/contribute/writing-a-loader

接口文档:https://webpack.js.org/api/loaders

简单案例:创建一个替换源码中字符串的loader

创建一个项目文件夹,并初始化:npm init -y

安装webpack webpack-cli:npm i webpack webpack-cli -D

项目里创建一个文件夹src,再创建一个文件夹myLoaders存放自己写的loader

创建配置文件:webpack.config.js

##webpack.config.js
const path = require("path")
module.exports = {
    mode:"development",
    entry:"./src/index.js",
    output:{
        path:path.resolve(__dirname,"./dist"),
        filename:"[name].js"
    },
    module:{
        rules:[{                  //配置loader
            test:/.js$/,
            use:[
                {
                    loader:path.resolve(__dirname,'./myLoaders/replaceLoader.js'),
                    options:{
                        name:"替换传参"
                    }
                }
            ]
        }]
    }
}
##写一个替换的loader----replaceLoader.js
//loader是一个函数,不可以是箭头函数
module.exports  = function(source){
    //source为接收的源代码
    //不能用箭头函数的原因是,会改变this的指向,接收参数需要借助this
    //如果loader配置了options对象,this.query指向这个options对象
    console.log(source,this.query);
    //必须有返回值
    return source.replace("world","kkb")
}

运行:npm run dev

 传参:this.query

 另一种传参的方法是,安装loader-utils,处理loader参数的工具

this.callback:可用来返回多个信息,不止是处理好的源码

返回四个参数:

err:错误信息;content:string | Buffer;sourceMap:可被这个模块解析的source map;meta:任意信息;

##replaceLoader.js
//loader是一个函数,不可以是箭头函数
module.exports  = function(source){
    //return source.replace("world","kkb")
    const result = source.replace("world",this.query.name);
    this.callback(null,result)
}

this.async:处理loader里有异步的事情---告诉loader-runner这个loader将会异步回调,返回this.callback

##replaceLoader.js
module.exports  = function(source){
    setTimeout(() => {
        const result = source.replace("world",this.query.name);
        return result
    },1000)
    
}
执行npm run dev报错,说明loader不会自动解析异步操作

解决办法:this.async

module.exports  = function(source){
    //this.async返回一个callback,他=this.callback
    const callback = this.async();//告诉loader-runner这里有异步操作
    setTimeout(() => {
        const result = source.replace("world",this.query.name);
        callback(null,result)
    },1000)    
}

处理多个loader的顺序问题: 执行顺序:自右往左,自下往上

##webpack.config.js
const path = require("path")
module.exports = {
    mode:"development",
    entry:"./src/index.js",
    output:{
        path:path.resolve(__dirname,"./dist"),
        filename:"[name].js"
    },
    module:{
        rules:[{
            test:/.js$/,//配置loader
            use:[
                path.resolve(__dirname,"./myLoaders/replaceLoader.js"),  
                {
                    loader:path.resolve(__dirname,'./myLoaders/replaceLoaderAaync.js'),
                    options:{
                        name:"您好"
                    }
                }             
            ]
        }]
    }
}
##replaceLoader.js

module.exports  = function(source){
    return source.replace("world","word");   
}
##replaceLoaderAaync.js

module.exports = function(source){
    const callback = this.async();
    setTimeout(() => {
        const result = source.replace("hello",this.query.name);
        callback(null,result)
    },1000)  
}

loader的路径问题:loader配置的时候,路径太繁琐,我们可以对路径进行一下设置

##webpack.config.js

const path = require("path")
module.exports = {
    resolveLoader:{
        modules:["node_moudles","./myLoaders"]//遇到loader,先去node_modules里找,然后再去./myLoaders里找
    },
    module:{
        rules:[{
            test:/.js$/,//配置loader
            use:[
                "replaceLoader", //本地路径  如果是npm安装进来的 不用考虑路径
                {
                    loader:'replaceLoaderAaync',
                    options:{
                        name:"您好"
                    }
                }             
            ]
        }]
    }
}
原文地址:https://www.cnblogs.com/znLam/p/13056575.html