webpack的自定义插件学习

Plugin

webpack的插件可以加入自定义构建的行为,使webpack更加灵活的执行更广泛的任务

webpack在编译源码的过程中,会触发一系列的Tapable钩子事件,而插件就找到合适时机的钩子事件,向其挂载自己的任务,这样就会在webpack构建的时候随着钩子触发而执行

webpack生命周期两个核心对象compiler和compilation

Compiler 模块是 webpack 的主要引擎,它通过 CLI 或者 Node API 传递的所有选项创建出一个 compilation 实例。 它扩展(extends)自 Tapable 类,用来注册和调用插件。 大多数面向用户的插件会首先在 Compiler 上注册。

compiler的一些属性
compiler.options 可以访问本次启动 webpack 时候所有的配置文件,包括但不限于 loaders 、 entry 、 output 、 plugin 等等完整配置信息。
compiler.inputFileSystem 和 compiler.outputFileSystem 可以进行文件操作,相当于 Nodejs 中 fs。
compiler.hooks 可以注册 tapable 的不同种类 Hook,从而可以在 compiler 生命周期中植入不同的逻辑。
compilation 对象

compilation 对象代表一次资源的构建,compilation 实例能够访问所有的模块和它们的依赖。

一个 compilation 对象会对构建依赖图中所有模块,进行编译。 在编译阶段,模块会被加载(load)、封存(seal)、优化(optimize)、 分块(chunk)、哈希(hash)和重新创建(restore)。

webpack执行顺序

img

自定义插件并挂载到Hook
class TestPlugin{
    constructor(str){
      console.log('str=============>',str)
    }
    apply(compiler){
            //同步钩子
        compiler.hooks.environment.tap("TestPlugin",() => {
          console.log("enviroment");
        })
        compiler.hooks.emit.tap("TestPlugin",(compilation) => {
            // console.log('compilation=============>',compilation)
        })
         //异步钩子  
        //emit是串行钩子,即钩子函数是一个个按顺序执行,例如以下需要花3s
        compiler.hooks.emit.tapAsync("TestPlugin",(compilation,callback) => {
            setTimeout(() => {
                console.log("emit Async 111");
                // console.log('compilation=============>',compilation)
                callback()
            }, 1000);
          })
        compiler.hooks.emit.tapPromise("TestPlugin",(compilation) => {
              return new Promise((resolve,reject)=>{
                setTimeout(() => {
                    console.log("emit Async 222");
                    resolve()
                }, 2000);
              })
            
          })
        //make是并行钩子,,以下需要花2s
        compiler.hooks.make.tapAsync("TestPlugin",(compilation,callback) => {
            setTimeout(() => {
                console.log("make Async 111");
                // console.log('compilation=============>',compilation)
                callback()
            }, 1000);

       
          })
        compiler.hooks.make.tapAsync("TestPlugin",(compilation) => {
              return new Promise((resolve,reject)=>{
                setTimeout(() => {
                    console.log("make Async 222");
                    resolve()
                }, 2000);
              })
            
          })
          //注册compilation的钩子
        compiler.hooks.compilation.tap('TestPlugin', (compilation) => {
            compilation.hooks.seal.tap('TestPlugin', () => {
              console.log('compilation.hooks.seal hook called');
            });
          });
    }


}
module.exports=TestPlugin
自定义clean-webpack-plugin

clean-webpack-plugin每次打包用于清除dist下目录的文件

class CleanWebpackPlugin {

    apply(complier){
        
        const outputPath =  complier.options.output.path
        const fs = complier.outputFileSystem
        complier.hooks.emit.tap('CleanWebpackPlugin',(compliation) => {
            this.removeFiles(fs,outputPath)
        })
    }

    removeFiles(fs,outputPath){
        const files = fs.readdirSync(outputPath)
        files.forEach((file) => {
           const pathfile = outputPath+"\\" +file
            if(fs.statSync(pathfile).isFile()){
                fs.unlinkSync(pathfile)
                return
            }else{
                    this.removeFiles(fs,pathfile)
            }
            //清空目录
           fs.rmdirSync(pathfile)
        })

      
    }
    //Api一行解决
    // removeFiles(fs,outputPath){
    //     fs.rmdirSync(outputPath,{recursive:true})
    // }

}
module.exports=CleanWebpackPlugin
自定义inline-chunk-plugin

将runtime等js文件改为内联的嵌入html的方式

runtime文件是用于解决缓存问题出现的

const HtmlWebpackPlugin = require('html-webpack-plugin');
class InlineChunkPlugin{
    constructor({tests=[]}){
        this.tests=tests
    }
    apply(compiler){
        compiler.hooks.compilation.tap('InlineChunkPlugin', (compilation) => {
            // console.log('The compiler is starting a new compilation...')
      
            // Static Plugin interface |compilation |HOOK NAME | register listener 
           const hooks =  HtmlWebpackPlugin.getHooks(compilation)
           hooks.alterAssetTagGroups.tap("InlineChunkPlugin",(assets) => {
            //    console.log('assets.headTags=============>',assets.headTags)
             /* 
                现在headTags的内容如下
               {
                tagName: 'script',
                voidTag: false,
                meta: { plugin: 'html-webpack-plugin' },
                attributes: { defer: true, type: undefined, src: 'static/js/runtime~main.js' }
              }, 
              要修改为如下
              {
                tagName: 'script',
                innerHTML: runtime文件内容
              }, 
              */
              
              assets.headTags=  this.getInlineChunk(assets.headTags,compilation.assets)
              //删除runtime文件
            

               Object.keys(compilation.assets).forEach((filepath)=>{
                   if(this.tests.some((test)=> test.test(filepath) )){
                       delete compilation.assets[filepath]
                   }
               })

           })
        }
        )

    }
    getInlineChunk(headTags,assets){
        return headTags.map ((tag) => {
            if(tag.tagName!=='script') return tag
            const filepath = tag.attributes.src;
            if(!this.tests.some((test)=> test.test(filepath) ))return tag
            return {
                meta: { plugin: 'InlineChunkPlugin' },
                tagName: 'script',
                innerHTML: assets[filepath].source()
            }
        })
    }
}
module.exports= InlineChunkPlugin
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Webpack允许开发者创建自定义插件来扩展其功能。创建自定义插件的步骤如下: 1. 创建一个 JavaScript 文件作为插件的入口文件。 2. 在该文件中,定义一个 JavaScript 类作为插件的主体。 3. 在该类中,实现一个 `apply` 方法,该方法会在 Webpack 编译过程中被调用。 4. 在 `apply` 方法中,可以通过 Webpack 提供的钩子(Hook)来注册各种编译过程的事件回调函数,以实现自定义的功能。 下面是一个简单的示例,展示了如何创建一个打印构建信息的自定义插件: ```javascript class MyCustomPlugin { apply(compiler) { compiler.hooks.done.tap('MyCustomPlugin', (stats) => { console.log('Build completed!'); console.log('----------------'); console.log(stats.toString()); }); } } module.exports = MyCustomPlugin; ``` 在上述示例中,我们创建了一个名为 `MyCustomPlugin` 的自定义插件类,并在其中实现了一个 `apply` 方法。在该方法中,我们使用了 `compiler.hooks.done.tap` 方法来注册一个回调函数,在每次构建完成后打印构建信息。 要在 Webpack 配置文件中使用此自定义插件,可以像使用其他插件一样进行配置: ```javascript const MyCustomPlugin = require('./path/to/MyCustomPlugin'); module.exports = { // ...其他配置项 plugins: [ new MyCustomPlugin(), ], }; ``` 通过将自定义插件实例添加到 `plugins` 配置项中,Webpack 在构建过程中会调用该插件的 `apply` 方法,并触发注册的事件回调函数。 请注意,这只是一个简单的示例。根据你的需求,你可以在自定义插件中实现更复杂的逻辑,以满足你的特定需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值