最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深入学习webpack plugin到手写一个plugin

    正文概述 掘金(_空谷)   2020-11-27   692

    什么是webpack插件

    const webpack = require('webpack')
    const TestWebpackPlugin = require('test-webpack-plugin')
    webpack({
    	plugins: [new TestWebpackPlugin({/* opt 配置 */})]
    })
    
    • 是一个独立的js模块
    • 模块对外暴露一个js函数
    • 函数的原型上定义了一个apply方法,方法注入了compiler对象作为参数
    • apply函数中通过调用compiler对象挂载webpack事件钩子,钩子回调中能拿到当前编译compilation对象,如果是异步编译插件则拿到回调callback
    • 完成自定义编译流程,处理compiltion对象的内部数据
    • 如果是异步插件,则数据处理完后执行callback回调
    // es5
    var pluginName = 'test-webpack-plugin'
    function TestWebpackPlugin (opt) {
    	this.options = opt
    }
    TestWebpackPlugin.prototype.apply = function (compiler) {
    	if (compiler.hooks) { // webpack4 +
        	compiler.hooks.emit.tapAsync(pluginName, function (compilation) {
            	// ...
            })
        } else {
        	compiler.plugin('emit', function (compilation, callback) {
            	// ...
                callback()
            })
        }
    }
    // es6
    const pluginName = Symbol('test-webpack-plugin')
    class TestWebpackPlugin {
    	constructor (opt) {
        	this.options = opt
        }
        apply (compiler) {
        	const { hooks } = compiler
            if (hooks) {
            	hooks.emit.tapAsync(pluginName, (compilation) => {})
            } else {
            	compiler.plugin('emit', (compilation) => {})
            }
        }
    }
    

    compiler和compilation对象

    • Compiler 对象包含了 Webpack 环境所有的的配置信息

    • Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等

    • Compiler 和 Compilation 的区别在于:Compiler 代表了整个 Webpack 从启动到关闭的生命周期,而 Compilation 只是代表了一次新的编译。

    compiler

    compiler源码参考

    compilation

    compilation源码参考

    webpack插件机制

    Tapable

    const {
    	SyncHook, // 同步串行钩子,在触发事件之后,会按照事件注册的先后顺序执行所有的事件处理函数
    	SyncBailHook, // 同步保险钩子,如果事件处理函数执行时有一个返回值不为空。则跳过剩下未执行的事件处理函数
    	SyncWaterfallHook, // 同步瀑布流钩子,上一个事件处理函数的返回值作为参数传递给下一个事件处理函数,依次类推
    	SyncLoopHook, // 同步循环钩子,事件处理函数返回true表示继续循环,如果返回undefined的话,表示结束循环
    	AsyncParallelHook, // 异步并行钩子
    	AsyncParallelBailHook, // 异步并行保险钩子
    	AsyncSeriesHook, // 异步串行钩子
    	AsyncSeriesBailHook, // 异步串行保险钩子
    	AsyncSeriesWaterfallHook // 异步串行瀑布流钩子
     } = require("tapable");
    

    Tapable源码参考

    compiler 事件钩子

    事件钩子触发时机参数类型
    entryOption在 entry 配置项处理过之后,执行插件SyncBailHook 同步保险run开始读取 records 之前,钩入(hook into) compilercompilerAsyncSeriesHook 异步串行compile一个新的编译(compilation)创建之后,钩入(hook into) compilercompilationParamsSyncHook 同步compilation编译(compilation)创建之后,执行插件compilationSyncHook 同步make从 entry 开始递归分析依赖,准备对每个模块进行 buildcompilationAsyncParallelHook 异步并行after-compile编译 build 过程结束compilationAsyncSeriesHook 异步串行emit生成资源到 output 目录之前compilationAsyncSeriesHook 异步串行after-emit生成资源到 output 目录之后compilationAsyncSeriesHook 异步串行done编译(compilation)完成statsSyncHook 同步

    深入学习webpack plugin到手写一个plugin

    干货,项目中上传完sourceMap后删除sourceMap的插件

    const _del = require('del')
    const symbols = require('log-symbols')
    const chalk = require('chalk')
    const pluginName = {
      name: 'clean-source-map-webpack-plugin'
    }
    class CleanSourceMapWebpackPlugin {
      constructor (options) {
        const defaultOptions = {
          sourceMapPath: [], // sourceMap的文件位置
          dangerouslyAllowCleanPatternsOutsideProject: false // 是否允许跨文件夹删除
        }
        this.options = Object.assign(defaultOptions, options)
        this.outputPath = ''
      }
      handleDone () {
        const { sourceMapPath, dangerouslyAllowCleanPatternsOutsideProject } = this.options
        const { outputPath } = this
        try {
        // 调用_del库来删除sourceMap文件
          _del.sync(sourceMapPath.map(item => outputPath + '/' +item), { force: dangerouslyAllowCleanPatternsOutsideProject })
          console.log(symbols.success, chalk.green('clean-source-map-webpack-plugin: complated'))
        } catch (error) {
          const needsForce = /Cannot delete files\/folders outside the current working directory\./.test(error.message)
          if (needsForce) {
            const message = 'clean-source-map-webpack-plugin: Cannot delete files/folders outside the current working directory. Can be overridden with the `dangerouslyAllowCleanPatternsOutsideProject` option.'
            throw new Error(message)
          }
          throw error
        }
      }
      apply (compiler) {
      	// 如果没有获取到输出地址
        if (!compiler.options.output || !compiler.options.output.path) {
          console.warn(symbols.warning, chalk.red('clean-source-map-webpack-plugin: options.output.path not defined. Plugin disabled...'))
          return
        }
        const { sourceMapPath } = this.options
        // 如果没有获取到sourceMap的相对地址
        if (sourceMapPath.length === 0) {
          console.warn(symbols.warning, chalk.red('clean-source-map-webpack-plugin: please input sourceMapPath. Plugin disabled...'))
          return
        }
        const { hooks } = compiler
        this.outputPath = compiler.options.output.path
        // 如果是webpack4+
        if (hooks) {
        // 在done的事件钩子中注册删除事件
          hooks.done.tap(pluginName, stats => {
            this.handleDone()
          })
        } else {
          compiler.plugin('done', stats => {
            this.handleDone()
          })
        }
      }
    }
    module.exports = CleanSourceMapWebpackPlugin
    
    

    看清楚真正的 Webpack 插件

    webpack4核心模块tapable源码解析

    深入浅出 Webpack


    起源地下载网 » 深入学习webpack plugin到手写一个plugin

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元