webpack插件 自动部署到服务器

Webpack 通过 Plugin 机制让其更加灵活,以适应各种应用场景。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

1. 基础的plugin

一个最基础的 Plugin 的代码是这样

javascript 复制代码
class BasicPlugin{
  // 在构造函数中获取用户给该插件传入的配置
  constructor(options){
  }

  // Webpack 会调用 BasicPlugin 实例的 apply 方法给插件实例传入 compiler 对象
  apply(compiler){
    compiler.plugin('compilation',function(compilation) {
    })
  }
}

// 导出 Plugin
module.exports = BasicPlugin;

在使用这个 Plugin 时,相关配置代码如下:

ini 复制代码
const BasicPlugin = require('./BasicPlugin.js');
module.export = {
  plugins:[
    new BasicPlugin(options),
  ]
}

Webpack 启动后,在读取配置的过程中会先执行 new BasicPlugin(options) 初始化一个 BasicPlugin 获得其实例。 在初始化 compiler 对象后,再调用 basicPlugin.apply(compiler) 给插件实例传入 compiler 对象。 插件实例在获取到 compiler 对象后,就可以通过 compiler.plugin(事件名称, 回调函数) 监听到 Webpack 广播出来的事件。 并且可以通过 compiler 对象去操作 Webpack。

2. Compiler和Compilation

在webpack的插件开发时,最经常用到的就是Compiler和Compilation,他们是webpack和plugin之间的桥梁

  • Compiler包含了所有webpack的配置信息,包含options、loader、plugins等信息。这个对象在Webpack启动时被实例化,它是全局唯一的,可以简单地将它理解为Webpack的实例
  • Compilation对象包含了当前的模块资源、编译生成资源、变化的文件等。当Webpack以开发模式运行时,每当检测一个文件发生变化,便有一次新的Compilation被创建。Compilation对象也提供了很多事件回调供插件进行扩展。通过Compilation也能读取到Compiler对象

两者的区别可以理解为:Compiler代表了整个Webpack从启动到关闭的生命周期,Compilation只代表一次新的编译

3. 事件流

Webpack就像一条生产线,要经过一系列处理流程才能将源文件转化成输出结果。这个生产线上每个流程的职责都是单一的,多个流程之间存在依赖关系,只有在完成了当前处理后才能提交给下一个流程处理。

Webpack在运行过程中会广播事件,插件只需要监听它关心的事情,就能加入这条生产线了,这就是插件的运行原理。

我们可以通过Compiler和Compilation对象来广播和监听事件

csharp 复制代码
// 广播事件
// event-name为事件名称,注意不要和现有的事件重名
// params为附带的参数
compiler.apply('event-name',params)

// 监听名称为event-name的事件,当event-name事件发生时,函数就会被执行
// 同时函数中的params参数为广播事件附带的参数
compiler.plugin('event-name',function(params){})

同理,compilation.apply和compilation.plugin的使用方法和前面讲解一致

4. 开发一个插件

通过前面的知识,我们已经可以开发一个简单的插件了,比如当Webpack成功编译和输出文件后执行发布操作,将输出的文件上传到服务器,同时该插件还能区分Webpack构建是否成功。

要实现该插件,需要借助以下两个事件:

  • done:在成功构建并且输出文件后,Webpack即将退出时发生
  • failed:在构建出现异常时导致构建失败,Webpack即将退出时发生

以下是该插件的用法

javascript 复制代码
module.exports = {
    plugins: [
        //在初始化EndWebpackPlugin时传入两个参数,分别是成功时的回调函数和失败时的回调函数
        new EndWebpackPlugin(() => {
            //Webpack构建成功,并且文件在输出时会执行到这里,这里就可以做发布文件操作
        },(err) => {
            //Webpack构建失败,err是导致错误的原因
            console.error(err)
        })
    ]
}

以下是实现这个插件

javascript 复制代码
class EndWebpackPlugin {
    constructor(doneCallback,failCallback){
        // 保存在构造函数中传入的回调函数,即我们在webpack.config.js实例化EndWebpackPlugin时传进来的两个参数
        this.doneCallback = doneCallback
        this.failCallback = failCallback
    }

    apply(compiler){
        compiler.plugin('done',(stats) => {
            // 在done事件中回调doneCallback
            this.doneCallback(stats)
        }),
        compiler.plugin('failed',(err) => {
            // 在failed事件中回调failCallback
            this.failCallback(err)
        })
    }
}

// 导出插件
module.exports = EndWebpackPlugin

我们还差最后一步,就是实现doneCallback,即将我们打包后的文件上传到我们的服务器,我们可以利用axios,通过post请求将打包出来的文件发送到我们服务器

javascript 复制代码
//完整代码

//webpack.config.js
const axios = require('axios')
module.exports = {
    plugins: [
        //在初始化EndWebpackPlugin时传入两个参数,分别是成功时的回调函数和失败时的回调函数
        new EndWebpackPlugin((compilation,callback) => {
    
        var url = 'http://10.0.0.0:78/upload' //服务器的url

        var upload = async function(name,content){
            await axios.post(url,{name,content})
        }

        for(let filename in compilation.assets){
            let content = compilation.assets[filename]['source']()
            upload(filename,content)
            callback()
        }
    },(err) => {
            //Webpack构建失败,err是导致错误的原因
            console.error(err)
        })
    ]
}

//uploade.js

class EndWebpackPlugin {
    constructor(doneCallback,failCallback){
        // 保存在构造函数中传入的回调函数,即我们在webpack.config.js实例化EndWebpackPlugin时传进来的两个参数
        this.doneCallback = doneCallback
        this.failCallback = failCallback
    }

    apply(compiler){
        compiler.plugin('done',() => {
            // 在done事件中回调doneCallback
            this.doneCallback()
        }),
        compiler.plugin('failed',(err) => {
            // 在failed事件中回调failCallback
            this.failCallback(err)
        })
    }
}

// 导出插件
module.exports = EndWebpackPlugin
相关推荐
岁岁种桃花儿29 分钟前
Vue核心语法第十一篇:绑定样式
前端·javascript·vue.js
程序员黑豆8 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC9 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea9 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
浮生望9 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少10 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
波波00710 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis11 小时前
es6知识点1-自备使用
前端·ecmascript·es6
小爬的老粉丝12 小时前
JavaScript 纯前端预览 WPS:先识别容器,再路由解析器
前端·javascript·wps