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
相关推荐
牧羊狼的狼25 分钟前
React 中的 HOC 和 Hooks
前端·javascript·react.js·hooks·高阶组件·hoc
知识分享小能手2 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
魔云连洲2 小时前
深入解析:Vue与React的异步批处理更新机制
前端·vue.js·react.js
mCell2 小时前
JavaScript 的多线程能力:Worker
前端·javascript·浏览器
超级无敌攻城狮4 小时前
3 分钟学会!波浪文字动画超详细教程,从 0 到 1 实现「思考中 / 加载中」高级效果
前端
excel5 小时前
用 TensorFlow.js Node 实现猫图像识别(教学版逐步分解)
前端
gnip5 小时前
JavaScript事件流
前端·javascript
赵得C5 小时前
【前端技巧】Element Table 列标题如何优雅添加 Tooltip 提示?
前端·elementui·vue·table组件
wow_DG5 小时前
【Vue2 ✨】Vue2 入门之旅 · 进阶篇(一):响应式原理
前端·javascript·vue.js
weixin_456904275 小时前
UserManagement.vue和Profile.vue详细解释
前端·javascript·vue.js