Plugin 插件机制
webpack 插件机制
目的:增强webpack项目自动化能力。
Loader 专注实现 资源模块的加载,从而实现整体项目的打包。
Plugin 解决项目中 除了资源加载以外 的自动化工作。
例如
- 在打包之前,自动清除dist目录
- 拷贝不需要参与打包的资源文件到输出目录
- 压缩打包结果输出的代码
webpack + Plugin 实现了大多前端 工程化 的工作,也是很多开发者理解为 webpack就是前端工程化 的原因。
webpack 常用插件
- clean-webpackl-plugin
- html-webpack-plugin
- copy-webpack-plugin
绝大多数插件导出的都是一个模块类(class),所以使用时就要创建这个插件的示例,并配置到plugins属性中。
clean-webpack-plugin 自动清理输出目录
// webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
// ...
plugins: [
new CleanWebpackPlugin()
]
}
html-webpack-plugin 自动生成html
目前位置示例都是以硬编码的方式,单独存放在项目根目录下,这个方式有两个问题:
- 项目发布时需要同时发布根目录下的 html文件 和 dist目录下所有的打包结果,并且上线后,需要人工确认html中路径引用都是正确的,相对麻烦。
- 项目输出(output)的目录或文件名,也就是打包结果的配置,发生了变化,还需要手动去修改html中script标签的src
解决办法就是通过webpack输出html文件,也就是让html也参与到webpack的构建过程。
构建过程中
- webpack知道生成了多少bundle,它会自动将这些打包文件添加到html文件中。
- webpack还把html文件输出到dist目录,这样上线时直接发布dist目录即可。
- bundle文件是webpack动态的注入到html文件中,不需要手动的硬编码,它确保路径的引用是正常的。
html-webpack-plugin 默认自动生成一个空白的index.html文件到配置的输出目录,并将打包文件(bundle)动态注入到html中。
html-webpack-plugin 配置
通过修改插件的配置属性,对自动生成的html文件做一些简单改进,例如:
- title:配置标题
- meta:自定义元数据标签
通过配置template指定一个html模板,可以配置更多内容以及自定义基础的dom结构。
html模板默认使用lodash语法。
同时输出多个页面文件
html-webpack-plugin 默认生成一个index.html文件。
同样可以通过创建多个实例,生成多个html文件。
通过filename指定输出的文件名。
copy-webpack-plugin 复制静态文件
对于项目中不需要参与构建的静态文件,也需要发布到线上,它们一般统一放在项目的public目录中。
可以通过 copy-webpack-plugin 插件将它们拷贝到输出目录。
它接收一个文件相对路径或目录组成的数组,路径可以使用通配符。
// 拷贝文件 v5.x用法
// new CopyWebpackPlugin([
// 'public/**',
// 'public'
// ])
// 拷贝文件 v6.x使用patterns 配置
new CopyWebpackPlugin({
patterns: [
// 'public/**'
'public'
]
})
插件机制的工作原理
相比于Loader,Plugin拥有更宽的能力范围。
webpack要求插件(在plugins中使用时)必须是一个函数或者是一个包含apply方法的对象。
官方:插件是由[具有
apply方法的prototype对象]所实例化出来的。
webpack在启动时,会自动调用插件的apply方法。
apply方法接收一个compiler对象作为参数。
compiler对象是webpack工作过程中最核心的对象。
它包含当前构建的所有的配置信息。
可以用它来注册钩子函数。
一般都会把一个插件定义为一个类(class),然后在其中定义一个apply方法。
使用插件时,通过这个class构建一个实例。
钩子机制
Plugin通过钩子机制实现。
钩子机制类似web中的事件。
为了便于插件的扩展,webpack几乎给每一个环节都埋下了一个钩子。
开发插件时就可以,向这些不同的节点,挂载不同的任务。
可以去webpack官网查看它预先定义好的钩子(API-PLUGINS - Compiler Hooks)
开发一个插件
自定义一个用于清除bundle.js中/*[*+]*/注释的插件。
确认插件执行时机(即挂载到哪个钩子上)
- emit`钩子:确认bundle.js内容,在生成到output目录之前。
通过compiler.hooks访问到具体的钩子。
通过tap方法注册一个钩子函数,它接收两个参数:
- 参数1:插件的名称
- 参数2:需要挂载到这个钩子上的函数,它接收一个
compilation对象作为参数compilation可以理解为此次打包过程的上下文- 此次所有打包过程产生的结果都会放到
compilation对象中 compilation.assets访问所有编译的资源文件,每个元素都是一个包含资源文件信息的对象key是资源文件的名称value包含一个source()方法- 调用它可以获取编译文件的内容
- 重定义这个方法返回的值,实现修改编译文件的内容
- 注:webpack还要求必须返回一个
size()方法,用于返回编译文件的大小
- 注:webpack还要求必须返回一个
class MyPlugin {
apply(compiler) {
compiler.hooks.emit.tap('MyPlugin', compilation => {
// 打印资源文件的名称
// console.log(name)
// 打印资源文件的内容,通过资源文件的值的source方法获取
// onsole.log(compilation.assets[name].source())
// 判断是否是js文件
if (name.endsWith('.js')) {
// 获取内容
const contents = compilation.assets[name].source()
// 清除/*[*+]*/注释
const withoutComments = contents.replace(/\/\*\*+\*\//g, '')
// 覆盖编译内容
compilation.assets[name] = {
source: () => withoutComments,
size: () => withoutComments.length, // 必要属性
}
}
}
}
}
总结
插件通过在生命周期的钩子中挂载函数实现扩展。
在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。
compiler对象代表了完整的webpack环境配置。- 这个对象在webpack启动时一次性建立,并配置好所有可操作的设置。
- 当在webpack环境中应用一个插件时,插件将受到此
compiler对象的引用。 - 可以使用它来访问webpack的主环境
compilation对象代表了一次资源版本构建。- 当运行webpack开发环境中间件时,每检测到一个文件变化,就会创建一个新的
compilation,从而生成一组新的编译资源。 - 一个
compilation对象表现了当前模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。 compilation也提供了很多关键时机的回调,供插件做自定义处理时选择使用。
- 当运行webpack开发环境中间件时,每检测到一个文件变化,就会创建一个新的
本文深入探讨Webpack插件机制,介绍其如何增强项目自动化能力,包括常见插件如clean、html及copy-webpack-plugin的使用,以及插件机制的底层原理与自定义插件开发流程。
1423

被折叠的 条评论
为什么被折叠?



