专栏首页coding个人笔记webpack插件怎么手写

webpack插件怎么手写

webpack插件没什么好说的,用过的都知道怎么配置,只是不知道内部怎么执行。今天学一学插件的一些机制,手写一个插件并不难。

之前介绍过了,webpack本质上是一种事件流机制,核心就是tapable,通过注册事件,触发回调,完成插件在不同生命周期的调用,内部也是通过大量的插件实现的。tapable内部暴露的方法挺多的,主要就是同步和异步,异步分为并行和串行。可以去GitHub上面看看:

https://github.com/webpack/tapable#tapable

这些方法都有用法示例,本来想写写使用方法,发现GitHub上面都有了,就不写了:

const {
 SyncHook,
 SyncBailHook,
 SyncWaterfallHook,
 SyncLoopHook,
 AsyncParallelHook,
 AsyncParallelBailHook,
 AsyncSeriesHook,
 AsyncSeriesBailHook,
 AsyncSeriesWaterfallHook
 } = require("tapable");

在写插件之前,不得不提一下compiler和compilation:

compiler对象代表了完整的 webpack 环境配置,可以访问整个环境。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置(options、loader、plugin等)。使用插件时将收到此 compiler 对象的引用。

compilation 对象代表了一次资源版本构建。在运行过程中,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation提供了很多关键时机的回调供插件做自定义处理时使用。

使用插件就是new一个,所以插件其实就是一个类(构造函数或者class类),内部在prototype定义一个apply方法(会直接调用),并提供compiler,通过compiler提供的hooks注册事件和在相应的回调里面进行操作。而compiler提供的compilation的重要属性是assets,表示所有的静态资源。

关于提供的hook和参数,可以在webpack>lib>Compiler.js搜hooks,其实compiler和compilation都是继承tapable。

关于hooks分别表示什么阶段可以去官网查看:https://www.webpackjs.com/api/compiler-hooks/

还需要明确一下,tapable里面提供的几个hook,同步的(sync开头)注册是tap,异步的(async开头)有tap、tapAsync、tapPromise,后面两个提供了回调函数。

引入自己的插件:

const MyPlugin = require('./plugins/my-plugin.js')

plugins里面使用:

new MyPlugin({
  name: 'wade plugin'
})
my-plugin.js里面:
class MyPlugin {
    constructor(options) {
        this.options = options;
    }
    apply(compiler){
        compiler.hooks.done.tap('MyPlugin', (stats) => {
            console.log('MyPlugin ', this.options);
        });
    }
}
module.exports = MyPlugin;

apply提供了compiler,done是编译完成,同步的调用tap,第一个参数没什么意义,一般写自己插件名字,stats里面对象就多了,有 options、 outputOptions等,可以自己命令行那边看看。

异步的:

class MyPlugin {
    constructor(options) {
        this.options = options;
    }
    apply(compiler){
        compiler.hooks.done.tapAsync('DonePlugin', (stats, callback) => {
            console.log('Hello ', this.options.name);
            setTimeout(() => {console.log(1);}, 1000);
            setTimeout(() => {console.log(2);}, 2000);
            setTimeout(() => {console.log(3);}, 3000);
            setTimeout(() => {
                callback();
            }, 4000)
        });
    }
}
module.exports = MyPlugin;

可以看看控制台,看看效果。

一般自己写插件会在emit和afterEmit进行一些操作,这两个钩子的参数是compilation,里面有assets是静态资源,可以进行操作:

compiler.hooks.emit.tap('DonePlugin', (compilation) => {
   let assets = compilation.assets;
    console.log(assets);
});

比如我想给bundle.js添加一个字符串:

let content = assets['bundle.js'].source();
assets['bundle.js'] = {
    source(){
        return '"build by wade"\r\n' + content
    },
    size(){
        return content.length;
    }
}

打包结果:

比如创建一个文件:

let creatContent = '创建一个文件';
assets['creat.js'] = {
    source(){
        return creatContent
    },
    size(){
        return creatContent.length
    }
}

上面都是没什么意义的操作,只是想表达插件的一些方法,比如可以在文件生成之后进行压缩,或者自动化部署到服务器之类的插件。真正写一些有用的插件还是需要根据具体清空具体实现代码,可能还需要引入一些外部的插件,比如进行请求需要引入ajax或者axios,压缩要引入JSZip等。

(完)

本文分享自微信公众号 - coding个人笔记(gh_2ce38b49dae1),作者:coding个人笔记

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Vue3新建项目

    Vue3.x已经出了很久了,只是现在业务没有新工程,所以还是一直在vue2.x上工作,为了不被落下,理了理vue3.x新建项目的过程。

    wade
  • 哔哩哔哩开源的flvjs

    之前有分享过rtmp和m3u8的直播,后来才有了哔哩哔哩开源的flvjs做,于是就出现了ios不兼容的问题。

    wade
  • toString()和valueOf()函数调用和优先级

    简单了说就是链式调用,链式调用的方法有很多,jQuery的,underscore的和lodash这三个库采用了不同的方式。而上面这个就简单多了:

    wade
  • 表单校验实战

    前端的表单验证肯定会经常遇到,特别是做报表系统、后台管理系统等项目的时候,必然会涉及到。当然前端表单验证的插件很多,而且可配置性很高,使用起来也是得心应手,比如...

    grain先森
  • ElasticSearch入门介绍之安装部署(二)

    我是攻城师
  • freemarker-number-formatter

    我们使用mavel来管理我们的包依赖,因此,只需在pom.xml中配置包依赖即可:

    zhangheng
  • MySQL 证明为什么用limit时,offset很大会影响性能

    链接:https://github.com/zhangyachen/zhangyachen.github.io/issues/117

    用户2769421
  • MySQL的Limit 性能差?真的不能再用了?

    我们知道,当limit offset rows中的offset很大时,会出现效率问题:

    IT大咖说
  • Python处理PDF及生成多层PDF

    Python提供了众多的PDF支持库,本文是在Python3环境下,试用了两个库来完成PDF的生成的功能。PyPDF对于读取PDF支持较好,但是没找到生成多层P...

    大江小浪
  • 一张900w的数据表,怎么把原先要花费17s执行的SQL优化到300ms?

    有一张财务流水表,未分库分表,目前的数据量为9555695,分页查询使用到了limit,优化之前的查询耗时16 s 938 ms (execution: 16 ...

    用户2781897

扫码关注云+社区

领取腾讯云代金券