webpack plugins
Webpack 插件是用于扩展 Webpack 功能的工具,它可以在 Webpack 构建过程的不同阶段进行干预,实现各种自定义的构建逻辑和优化操作。Webpack 插件是一个 JavaScript 对象,它通常包含一个 apply 方法,在 apply 方法中定义了插件的逻辑。
webpack plugin 常见功能
Webpack 插件可以用于实现各种功能,包括但不限于:
- 打包优化:优化打包结果,减小输出文件的体积,提高应用程序的加载速度。例如,使用 UglifyJsPlugin 插件压缩 JavaScript 代码,使用 OptimizeCSSAssetsPlugin 插件压缩 CSS 代码等。
- 资源管理:管理静态资源文件,包括图片、字体等文件的处理和优化。例如,使用 HtmlWebpackPlugin 插件生成 HTML 文件,并自动注入打包后的资源文件链接。
- 模块解析:自定义模块解析规则,实现特定的模块加载逻辑。例如,使用 ProvidePlugin 插件自动加载模块,使用 IgnorePlugin 插件忽略特定的模块等。
- 环境变量注入:在打包过程中注入环境变量,实现不同环境下的不同配置。例如,使用 DefinePlugin 插件定义全局变量,根据环境变量来控制代码的行为。
- 自定义输出:自定义输出文件的命名规则和路径,实现灵活的文件输出配置。例如,使用 CopyWebpackPlugin 插件复制静态资源文件到输出目录,使用 MiniCssExtractPlugin 插件提取 CSS 文件并单独输出等。
- 代码分割:实现代码分割功能,将应用程序拆分为多个代码块,实现按需加载和减小首次加载时间。例如,使用 SplitChunksPlugin 插件将公共代码提取为单独的代码块,使用 BundleAnalyzerPlugin 插件分析代码块的大小和依赖关系等。
- 自定义处理逻辑:实现特定的自定义处理逻辑,满足项目的特定需求。例如,使用自定义插件实现特定的文件处理逻辑,修改 Webpack 内部配置等。
总的来说,Webpack 插件是 Webpack 构建过程中非常重要的一部分,它可以扩展 Webpack 功能,实现各种自定义的构建逻辑和优化操作,帮助开发者更好地管理和优化项目的构建过程。
常见的 webpack plugin
- HtmlWebpackPlugin:用于生成 HTML 文件,并自动注入打包后的资源文件链接,支持多页面应用的构建。
- MiniCssExtractPlugin:用于提取 CSS 文件,并单独输出,适用于生产环境的 CSS 分离和压缩。
- OptimizeCSSAssetsPlugin:用于优化和压缩 CSS 文件,提升页面加载速度。
- UglifyJsPlugin:用于压缩 JavaScript 代码,减小输出文件的体积,提高应用程序的加载速度。
- CopyWebpackPlugin:用于复制静态资源文件到输出目录,例如图片、字体等。
- DefinePlugin:用于定义全局变量,可以在代码中直接使用环境变量。
- SplitChunksPlugin:用于代码分割,将公共模块提取为单独的代码块,减小首次加载时间。
- CleanWebpackPlugin:用于清理输出目录,保证每次构建前输出目录是干净的。
- ProvidePlugin:自动加载模块,不需要 import 或 require 手动引入。
- BundleAnalyzerPlugin:分析构建结果,可视化代码块的大小和依赖关系,帮助优化打包结果。
自定义 webpack plugin
webpack plugin 由以下几个部分组成:
- A named JavaScript function or a JavaScript class.
- Defines
apply
method in its prototype. - Specifies an event hook to tap into.
- 处理 webpack 内部实例的特定数据。
- 函数执行完成后调用 webpack 提供的回调。
// 一个 JavaScript 类
class MyExampleWebpackPlugin {
// 在插件函数的 prototype 上定义一个 `apply` 方法,
// 以 compiler 为参数。
apply(compiler) {
// 指定一个挂载到 webpack 自身的事件钩子。
compiler.hooks.emit.tapAsync(
'MyExampleWebpackPlugin',
(compilation, callback) => {
// compilation 对象包含了当前构建过程的各种信息
// 可以在这里获取和操作构建过程的各个阶段
console.log('这是一个示例插件!');
console.log(
'这里表示了资源的单次构建的 `compilation` 对象:',
compilation
);
// 用 webpack 提供的插件 API 处理构建过程
compilation.addModule(/* ... */);
callback();
}
);
}
}
compiler
Webpack 中的 compiler 对象是整个构建过程的核心,它负责编译整个项目并生成最终的构建结果。
下面是一些关于 compiler 对象的具体细节:
1.compiler 对象结构
- options:包含了 Webpack 的配置信息,例如 entry、output、module、resolve 等配置项的值。可以通过 compiler.options 来访问和修改这些配置信息。
- hooks:包含了各种钩子函数(hooks),用于在构建过程的不同阶段执行自定义的逻辑。常见的钩子函数包括 beforeRun、run、compile、emit 等,可以通过 compiler.hooks.xxx.tap 来注册钩子函数。
- context:表示项目的上下文路径,是项目根目录的绝对路径。Webpack 会根据 entry 配置项来设置项目的上下文路径。
- inputFileSystem:用于读取项目中的源文件和资源文件。Webpack 使用 inputFileSystem 来加载模块和解析依赖关系。
- outputFileSystem:用于写入和输出编译后的代码和资源文件。Webpack 使用 outputFileSystem 将编译后的结果输出到指定的输出路径。
- resolvers:包含了解析器(resolver)的集合,用于解析模块的路径和依赖关系。Webpack 使用解析器来查找模块,并确定模块的具体路径和位置。
- run:执行构建过程的入口方法,会触发整个构建过程的各个阶段和钩子函数,直到构建完成。
- compile:编译代码的方法,会根据配置信息和钩子函数执行相应的编译逻辑,包括加载模块、转换代码、生成输出文件等。
- emit:生成最终的构建结果的方法,会将编译后的代码输出到指定的输出路径,并生成最终的输出文件。
2.compiler 常见使用
- 访问配置信息:通过 compiler.options 可以访问 Webpack 的配置信息,包括 entry、output、module、resolve 等配置项的值。例如,可以通过 compiler.options.entry 获取入口文件的配置信息。
- 注册钩子函数:通过 compiler.hooks.xxx.tap 方法可以注册钩子函数,钩子函数会在构建过程的不同阶段执行。例如,可以通过 compiler.hooks.run.tap 注册在构建开始阶段执行的钩子函数。
- 读取文件:通过 compiler.inputFileSystem 可以读取项目中的源文件和资源文件。Webpack 使用 inputFileSystem 加载模块和解析依赖关系。
- 输出文件:通过 compiler.outputFileSystem 可以写入和输出编译后的代码和资源文件。Webpack 使用 outputFileSystem 将编译后的结果输出到指定的输出路径。
- 执行构建过程:通过 compiler.run 方法可以执行整个构建过程,触发各个阶段的钩子函数,并生成最终的构建结果。可以在构建过程中通过注册钩子函数来插入自定义的逻辑。
- 编译代码:通过 compiler.compile 方法可以执行编译代码的过程,包括加载模块、转换代码、生成输出文件等。可以在编译过程中通过注册钩子函数来添加自定义的编译逻辑。
- 生成构建结果:通过 compiler.emit 方法可以生成最终的构建结果,将编译后的代码输出到指定的输出路径,并生成最终的输出文件。可以在生成过程中通过注册钩子函数来添加自定义的输出逻辑。
3.compiler 代码示例
const webpack = require('webpack');
const path = require('path');
// 1. 创建 compiler 实例
const compiler = webpack({
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
});
// 2. 注册 beforeRun 钩子函数,在构建开始前执行
compiler.hooks.beforeRun.tap('MyPlugin', () => {
console.log('Webpack 构建即将开始...');
});
// 3. 注册 emit 钩子函数,在生成输出文件前执行
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
console.log('Webpack 构建即将完成,准备生成输出文件...');
// 可以在这里添加一些自定义的输出逻辑,例如生成额外的文件等
setTimeout(() => {
console.log('额外文件已生成!');
callback();
}, 1000);
});
// 4. 执行构建过程
compiler.run((err, stats) => {
if (err) {
console.error(err);
return;
}
console.log(stats.toString({
colors: true
}));
});
compilation
Webpack 中的 compilation 对象代表了一次构建过程中的所有信息和数据的集合。它包含了当前构建过程中涉及的所有模块、资源、编译状态等信息,是 Webpack 在构建过程中的核心对象之一。
1.compilation 对象结构
Webpack 中的 compilation 对象是在每次构建过程中创建的,它包含了当前构建过程中的所有信息和数据。
以下是 compilation 对象的主要结构:
- 模块(Modules):compilation.modules 属性是一个模块的集合,包含了当前构建过程中所有的模块信息。每个模块包含了模块的路径、依赖关系、源代码等信息。
- 依赖图(Dependency Graph):compilation.dependencyGraph 属性是一个依赖图对象,表示了当前构建过程中模块之间的依赖关系。它记录了每个模块的依赖关系,并提供了一些方法来查询和分析依赖图。
- 资源(Assets):compilation.assets 属性是一个资源的集合,包含了当前构建过程中生成的所有资源文件。每个资源包含了资源的路径、内容、大小等信息。
- 编译器(Compiler):compilation.compiler 属性是一个编译器对象,表示了当前构建过程的编译器信息。它提供了一些方法和属性来获取和修改编译过程的状态。
- 插件(Plugins):compilation 对象也有自己的一套钩子函数,允许开发者在构建过程中插入自定义的逻辑。常见的钩子函数包括 optimize、optimize-modules、after-optimize-assets 等。
- 错误信息(Errors):compilation.errors 属性是一个错误的集合,包含了当前构建过程中发生的所有错误信息。可以通过遍历这个集合来获取和处理构建错误。
- Hash:compilation.hash 属性是当前构建过程的 hash 值,用于标识当前构建结果的唯一性。
- 模块工厂(Module Factory):compilation.moduleFactory 属性是模块工厂对象,用于创建和管理模块的实例。它提供了一些方法来创建模块、解析模块路径等。
- 模块解析器(Module Resolver):compilation.moduleResolver 属性是模块解析器对象,用于解析模块的路径和依赖关系。它提供了一些方法来解析模块路径、查找模块等。
- Chunk:compilation.chunks 属性是一个 chunk 的集合,包含了当前构建过程中生成的所有 chunk。每个 chunk 包含了 chunk 的名称、入口模块、依赖关系等信息。
- 模板(Templates):compilation.templates 属性是模板对象,用于生成最终的输出文件。它提供了一些方法来生成输出文件的内容、格式化输出文件等。
以上是 compilation 对象的主要结构,它包含了构建过程中的各个方面的信息和数据。通过 compilation 对象,可以获取和处理当前构建过程中的模块、资源、编译状态等各个方面的信息,实现对构建过程的灵活控制和定制化。
2. compilation 常用功能
compilation 对象是 Webpack 构建过程中的核心对象之一,提供了丰富的 API 和钩子函数,允许开发者在构建过程中获取和处理各种信息。
以下是一些常见的 compilation 对象的用法:
- 访问模块信息:通过 compilation.modules 属性可以访问当前构建过程中的所有模块信息。可以遍历模块集合,获取模块的路径、依赖关系、源代码等信息。
compilation.modules.forEach(module => {
console.log(module.identifier()); // 打印模块的标识符
});
- 访问资源信息:通过 compilation.assets 属性可以访问当前构建过程中生成的所有资源文件。可以遍历资源集合,获取资源的路径、内容、大小等信息。
Object.keys(compilation.assets).forEach(assetName => {
console.log(assetName); // 打印资源文件名
});
- 注册钩子函数:通过 compilation.hooks 可以注册钩子函数,在构建过程的不同阶段执行自定义的逻辑。
compilation.hooks.optimizeChunks.tap('MyPlugin', chunks => {
// 在优化 chunk 阶段执行自定义逻辑
});
- 生成输出文件:通过 compilation.emitAssets 方法可以生成最终的输出文件,并输出到指定的输出路径。
compilation.emitAssets((err, assets) => {
if (err) {
console.error(err);
return;
}
console.log('输出文件已生成!');
});
- 处理错误信息:通过 compilation.errors 属性可以获取当前构建过程中发生的所有错误信息。可以遍历错误集合,处理构建过程中的错误情况。
compilation.errors.forEach(error => {
console.error(error);
});
- 获取编译状态:通过 compilation.compiler 属性可以获取当前构建过程的编译器信息。可以访问编译器的各种属性和方法,获取和修改编译过程的状态。
console.log(compilation.compiler.options); // 打印编译器的配置信息
总的来说,compilation 对象提供了丰富的 API 和钩子函数,允许开发者在构建过程中获取和处理各种信息,实现对构建过程的灵活控制和定制化。通过使用 compilation 对象,可以访问和处理当前构建过程中的模块、资源、编译状态等各个方面的信息,满足项目的特定需求。
自定义 webpack plugin
插件是由「具有 apply 方法的 prototype 对象」所实例化出来的。这个 apply 方法在安装插件时,会被 webpack compiler 调用一次。apply 方法可以接收一个 webpack compiler 对象的引用,从而可以在回调函数中访问到 compiler 对象。
- 编写一个插件
class HelloWorldPlugin {
apply(compiler) {
compiler.hooks.done.tap(
'Hello World Plugin',
(
stats /* 绑定 done 钩子后,stats 会作为参数传入。 */
) => {
console.log('Hello World!');
}
);
}
}
module.exports = HelloWorldPlugin;
- 引入自定义插件
要安装这个插件,只需要在你的 webpack 配置的 plugin 数组中添加一个实例:
// webpack.config.js
var HelloWorldPlugin = require('hello-world');
module.exports = {
// ... 这里是其他配置 ...
plugins: [new HelloWorldPlugin({ options: true })],
};