如何自己编写一个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:"您好" } } ] }] } }