什么是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) compiler | compiler | AsyncSeriesHook 异步串行 | compile | 一个新的编译(compilation)创建之后,钩入(hook into) compiler | compilationParams | SyncHook 同步 | compilation | 编译(compilation)创建之后,执行插件 | compilation | SyncHook 同步 | make | 从 entry 开始递归分析依赖,准备对每个模块进行 build | compilation | AsyncParallelHook 异步并行 | after-compile | 编译 build 过程结束 | compilation | AsyncSeriesHook 异步串行 | emit | 生成资源到 output 目录之前 | compilation | AsyncSeriesHook 异步串行 | after-emit | 生成资源到 output 目录之后 | compilation | AsyncSeriesHook 异步串行 | done | 编译(compilation)完成 | stats | SyncHook 同步 |
---|
干货,项目中上传完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
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!