热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

插件的内部实现_webpack插件怎么手写

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

f24942cedb79595ba5e6775455d2bfa7.png

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。

a86014d8a72dfba48797b1513d673118.png

关于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);

});

fc65429cbad23230b1b09b1c8a64fa5d.png

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

let content = assets['bundle.js'].source();

assets['bundle.js'] = {

    source(){

        return '"build by wade"\r\n' + content

    },

    size(){

        return content.length;

    }

}

打包结果:

18d60f4c821f949f2ef773e6cf155e52.png

比如创建一个文件:

let creatContent = '创建一个文件';

assets['creat.js'] = {

    source(){

        return creatContent

    },

    size(){

        return creatContent.length

    }

}

03806683c65bab365c9db7817d37fc4c.png

5b3d57a3e0119f35c23cbd6de3e01ddd.png

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

(完)

Coding 个人笔记

f946001727cf4949e36446f708053a12.png




推荐阅读
  • 在Java开发中,保护代码安全是一个重要的课题。由于Java字节码容易被反编译,因此使用代码混淆工具如ProGuard变得尤为重要。本文将详细介绍如何使用ProGuard进行代码混淆,以及其基本原理和常见问题。 ... [详细]
  • 本文详细介绍了如何在 Vue CLI 3.0 和 2.0 中配置 proxy 来解决开发环境下的跨域问题,包括具体的配置项和使用场景。 ... [详细]
  • java类名的作用_java下Class.forName的作用是什么,为什么要使用它?
    湖上湖返回与带有给定字符串名的类或接口相关联的Class对象。调用此方法等效于:Class.forName(className,true,currentLoader) ... [详细]
  • Flutter 核心技术与混合开发模式深入解析
    本文深入探讨了 Flutter 的核心技术,特别是其混合开发模式,包括统一管理模式和三端分离模式,以及混合栈原理。通过对比不同模式的优缺点,帮助开发者选择最适合项目的混合开发策略。 ... [详细]
  • 本打算教一步步实现koa-router,因为要解释的太多了,所以先简化成mini版本,从实现部分功能到阅读源码,希望能让你好理解一些。希望你之前有读过koa源码,没有的话,给你链接 ... [详细]
  • PHP函数的工作原理与性能分析
    在编程语言中,函数是最基本的组成单元。本文将探讨PHP函数的特点、调用机制以及性能表现,并通过实际测试给出优化建议。 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • 深入探讨前端代码优化策略
    本文深入讨论了前端开发中代码优化的关键技术,包括JavaScript、HTML和CSS的优化方法,旨在提升网页加载速度和用户体验。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
  • 本文档详细介绍了软通动力Java开发工程师职位的笔试题目,涵盖了Java基础、集合框架、JDBC、JSP等内容,并提供了详细的答案解析。 ... [详细]
  • 在Qt框架中,信号与槽机制是一种独特的组件间通信方式。本文探讨了这一机制相较于传统的C风格回调函数所具有的优势,并分析了其潜在的不足之处。 ... [详细]
  • 本文详细介绍了如何在 Node.js 环境中利用 Nodemailer 库实现邮件发送功能,包括环境配置、代码实现及常见问题解决方法。 ... [详细]
  • 本文详细记录了腾讯ABS云平台的一次前端开发岗位面试经历,包括面试过程中遇到的JavaScript相关问题、Vue.js等框架的深入探讨以及算法挑战等内容。 ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中安装 Python 3.7 的步骤,包括编译工具的安装、Python 3.7 源码的下载与编译、软链接的创建以及常见错误的处理方法。 ... [详细]
  • 在使用Python 3.x的argparse模块时,如果输入参数中包含&符号,会遇到解析错误。本文介绍了如何解决这一问题,确保输入参数能够正确解析。 ... [详细]
author-avatar
一片绿洲053766
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有