当前位置: 首页 > 后端技术 > Node.js

webpack-插件插件开发

时间:2023-04-03 19:38:02 Node.js

开发webpack插件需要知道的几个必要条件:获取编译器的compiler对象,通过它可以得到编译阶段的生命周期函数包括config配置、资源文件、编译信息、hook函数等信息得到,找到合适的钩子函数处理相应逻辑返回的结果,支持同步和异步两种方式获取编译器实例。第一步是获取编译器实例对象://helloPlugin.jsmodule.exports=classRemoveLogs{constructor(options){this.options=options}apply(compiler){console.log(`Hello${this.options.名字}`)}};引入这个脚本,在控制台执行,可以看到编译结果://webpack.config.jsvarHelloWorldPlugin=require('./helloPlugin.js');module.exports={//配置插件plugins:[newHelloWorldPlugin({名称:"chenwl"})]};生命周期钩子函数可以通过官方文档compiler-hooks查看编译器提供的钩子函数,也可以直接去/node_modules/webpack/lib/Compiler.js查看同步和异步钩子函数可以同步处理或异步:module.exports=classSyncPlugin{apply(compiler){//tap同步compiler.hooks.emit.tap("tap",(compilation)=>{console.log("*****tap*****")})//在tapAsync参数cb调用compiler.hooks.emit之前进程会暂停。tapAsync("tapAsync",(compilation,cb)=>{开始(0);函数开始(索引){console.log(索引);if(index<=3){setTimeout(()=>{start(++index);},1000);}else{cb()}}})//tapPromise调用compiler.hooks.emit.tapPromise("tapPromise",(compilation)=>{returnnewPromise((resolve,reject)=>{console.log("starttap-promise");setTimeout(()=>{resolve()},2000)})})}}logRemoverPlugin文件编译完成后,去掉console://logRemoverPlugin.jsconstfs=require("fs");module.exports=classRemoveLogs{apply(compiler){compiler.hooks.done.tap("RemoveLogs",stats=>{const{path,filename}=stats.compilation.options.output;try{//这里你可以在处理之前匹配文件名letfilePath=path+"/"+filename;fs.readFile(filePath,"utf8",(err,data)=>{constrgx=/console.log\(['|"](.*?)['|"]\)/;constnewdata=data.replace(rgx,"");如果(错误)console.log(错误);fs.writeFile(filePath,newdata,function(err){if(err){returnconsole.log(err)}console.log("LogsRemoved");});});}catch(error){console.log(error)}});}};AnalyzePlugin分析打包后的资源文件信息,生成文件:文件名文件大小index.html1266文件总数1//AnalyzePlugin.jsconst{compilation}=require("webpack")module.exports=classAnalyze{constructor(config){//获取包文件名this.filename=config.filename;}应用(编译器){编译器。hooks.emit.tap("analyze-plugin",(compilation)=>{constassets=compilation.assets;constentries=Object.entries(assets);constcontent=`|filename|filesize||-----------|------------|`entries.forEach(([filename,fileObj])=>{content+=`|${filename}|${fileObj.size()}|`});content+=`>文件总数${entries.length}`//console.log(this.filename)compilation.assets[this.filename]={source(){returncontent},size(){returncontent.length}}})}}inlinePlugin将资源文件插入到html中,将head标签组和body标签组link标签转化为style标签,获取链接属性link的样式内容,插入到style标签里面script标签获取src属性链接的脚本内容,插入到script标签中=配置匹配;//匹配需要转换的文件this.compilation=null;//保存编译}processTag(tag){if(!this.compilation)return;//获取文件链接consturl=tag.attributes.href||标签.属性.src;//获取文件内容constsource=this.compilation.assets[url].source()if(!this.match||!this.match.test(url))返回标签;if(tag.tagName==="link"){tag={tagName:"style",innerHTML:source}}if(tag.tagName==="script"){tag={tagName:"script",innerHTML:来源}}删除this.compilation.assets[url];returntag}processTags(data){letheadTags=data.headTags让bodyTags=data.bodyTagsheadTags=headTags.map((tag)=>{returnthis.processTag(tag)})bodyTags=bodyTags.map((tag)=>{returnthis.processTag(tag)});return{headTags,bodyTags,}}apply(compiler){compiler.hooks.compilation.tap("MyPlugin",(compilation)=>{HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync("MyPlugin",(data,cb)=>{//保存编译this.compilation=compilation;cb(null,this.processTags(data))})})}}写一个上传文件到七牛云的插件UploadQiNiuPlugin首先需要安装七牛云的依赖包npminstallqiniuconstpath=require("path")constqiniu=require("qiniu")module.exports=classUploadQiNiuPlugin{constructor(options){let{bucket="",accessKey="",secretKey=""}=optionsletmac=newqiniu.auth.digest.Mac(accessKey,secretKey)letputPolicy=newqiniu.rs.PutPolicy({scope:bucket})this.outputPath=""this.uploadToken=putPolicy.uploadToken(mac)letconfig=newqiniu.conf.Config()this.formUploader=newqiniu.form_up.FormUploader(config)this.putExtra=newqiniu.form_up.PutExtra()}upload(filename){returnnewPromise((resolve,reject)=>{letrealPath=path.join(this.outputPath,filename)//上传文件this.formUploader.putFile(this.uploadToken,filename,realPath,this.putExtra,(err,body)=>{err?reject(err):resolve(body)})})}apply(compiler){compiler.hooks.afterEmit.tapPromise("upload-plugin",(compilation)=>{this.outputPath=compiler.outputPathletassets=compilation.assetsletpromises=复制代码[]Object.keys(assets).forEach((filename)=>{promises.push(this.upload(filename))})returnPromise.all(promises)})}}QiniuManager上传前可能需要删除旧的七牛云资源文件,这里还有一个工具:classQiniuManager{constructor({bucket,accessKey,secretKey}){conf.Config()this.bucketManager=newqiniu.rs.BucketManager(mac,config)}deleteFiles(filenames){letdeleteFile=(filename)=>{returnnewPromise((resolve,reject)=>{this.bucketManager.delete(bucket,filename,(err)=>err?reject(err):resolve(filename))})}让deletePromises=文件名。地图((f)=>删除teFile(f))返回Promise.all(deletePromises)}}