《Webpack5 核心原理与应用实践》学习笔记-> 提升插件健壮性

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 《Webpack5 核心原理与应用实践》学习笔记-> 提升插件健壮性

其实从loader开始,个人已经没有多少想法了,自己基本上用不到loaderplugin的开发, 目前的情况也不需要开发或者是调试这些玩意,而且课程里面干货嗯,所以差点弃坑,但是反正就剩几章了,咬咬牙吧,这是写给自己的,后面把一个技术栈弄得七七八八了再来写专栏。


插件的健壮性其实和自己写的项目类似,要排查问题,需要记录日志,分析性能瓶颈等,这些webpack都替你考虑过了, 所以会有一些工具来帮助你做这些事。


日志处理


在之前的loader中写过,可以通过this.getLogger()来使用日志功能,它是内置了infrastructureLogging,还不了解可以翻翻之前写的或者去webpack官网搜索一下这个。


loader中使用是通过注入的上下文this来获取log,在plugin中是通过apply中传入的compiler或者compilation来使用的,如下:


class MyPlugin {
    apply(compiler) {
        // 通过compiler.getInfrastructureLogger获取一个logger
        const logger = compiler.getInfrastructureLogger('MyPlugin');
        logger.info('MyPlugin is starting');
        compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
            // 通过compilation.getLogger获取一个logger
            const logger = compilation.getLogger('MyPlugin');
            logger.info('Hello from MyPlugin');
            callback();
        })
    }
}
module.exports = MyPlugin;

log的日志分级就不用讲了吧,接下来就是通过log上报异常,通过log上报的异常不会中断webpack的构建:


class MyPlugin {
    apply(compiler) {
        compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
            // 通过compilation.getLogger获取一个logger
            const logger = compilation.getLogger('MyPlugin');
            // log的分级
            logger.info('Hello from MyPlugin');
            logger.log('Log from MyPlugin');
            logger.debug('Debug from MyPlugin');
            logger.warn('Warning from MyPlugin');
            logger.error('Error from MyPlugin');
            // 可以通过 logger.warn() logger.error() 等方法输出异常日志,这不会影响webpack的编译结果
            logger.warn('Warning');
            logger.error('Error');
            // 还可以通过compilation.errors和compilation.warnings添加错误和警告
            compilation.errors.push(new Error("Emit Error From FooPlugin"));
            compilation.warnings.push("Emit Warning From FooPlugin");
            callback();
        })
    }
}
module.exports = MyPlugin;

这里可以通过loggerwarnerror方法输出异常日志,也可以通过compilationwarningserrors添加错误警告,他们都不会中断webpack的构建。


他们的区别在于,使用log仅仅是出入错误信息到控制台,而使用compilation.warningscompilation.errors还会将错误信息汇总到 stats 统计对象:


image.png

处理错误信息


上面讲到通过log来记录编译过程中的一些信息,包括错误信息,但是这个错误信息并不会影响构建,其实除了通过log来处理异常还有其他的方式来处理异常。


  1. 直接抛出异常


class MyPlugin {
    apply(compiler) {
        compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
            if (Math.random() > 0.5) {
                // 直接抛出异常会中断webpack的构建
                throw new Error('MyPlugin error');
            }
            callback();
        })
    }
}
module.exports = MyPlugin;

  1. 向下透传错误信息


class MyPlugin {
    apply(compiler) {
        compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
            let error = undefined;
            if (Math.random() > 0.5) {
                error = new Error('MyPlugin error');
            }
            // callback的第一个参数是错误信息,错误信息会被webpack捕获,如果有错误信息,webpack会停止打包
            callback(error);
        })
    }
}
module.exports = MyPlugin;

上报统计信息


有时候处理一些文件会特别耗时,用户可能需要对此进行一些优化,这个时候就需要插件的开发者提供统计信息了,上报统计信息有两种方式:


  • 使用 ProgressPlugin 插件的 reportProgress 接口上报执行进度;


  • 简单用法:npx webpack --progress


这种方式最终输出的进度和真实的构建进度差别很大(虽然进度条都是假的),因为有些插件可能没有提交任何构建进度相关的信息。


  • 使用webpack提供的ProgressPlugin插件
  • 首先在配置文件中配置一下
const MyPlugin = require('./src/plugin/index')
const {ProgressPlugin} = require('webpack')
module.exports = {
    // 省略其他配置
    plugins: [
        new MyPlugin(),
        new ProgressPlugin({
            activeModules: false,
            entries: true
        })
    ]
}

  • 然后在插件中编写上报进度的代码


const {ProgressPlugin} = require('webpack');
const wait = (misec) => new Promise((r) => setTimeout(r, misec));
class MyPlugin {
    apply(compiler) {
        compiler.hooks.emit.tapAsync('MyPlugin', async (compilation, callback) => {
            // 获取 Reporter ,这个有可能为 null,我这里没有写兜底的空函数
            const reportProgress = ProgressPlugin.getReporter(compiler);
            for (let i = 0; i < 100; i++) {
                await wait(100);
                reportProgress(i / 100, `Our plugin is working ${i}%`);
            }
            callback()
        })
    }
}
module.exports = MyPlugin;

  • 使用 stats 接口汇总插件运行的统计数据。
  • 编写代码
class MyPlugin {
    apply(compiler) {
        compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
            const statsMap = new Map();
            // buildModule 钩子将在开始处理模块时触发
            compilation.hooks.buildModule.tap('MyPlugin', (module) => {
                const ident = module.identifier();
                const startTime = Date.now();
                // 模拟5秒钟的构建时间
                while (new Date().getTime() - startTime < 5000);
                const endTime = Date.now();
                // 记录处理耗时
                statsMap.set(ident, endTime - startTime);
            });
            compilation.hooks.statsFactory.tap('MyPlugin', (factory) => {
                factory.hooks.result
                    .for("module")
                    .tap('MyPlugin', (module, context) => {
                        const { identifier } = module;
                        const duration = statsMap.get(identifier);
                        // 添加统计信息
                        module.fooDuration = duration || 0;
                    });
            });
        })
    }
}
module.exports = MyPlugin;

  • 输出结果:npx webpack --profile --json=compilation-stats.json

这个命令会在根目录创建一个compilation-stats.json的文件,可以找到module.fooDuration就是构建时间,也是上面自己记录的信息,不出意外应该是5000

总结


插件其实就是一个工程项目,提高项目的健壮性是很有必要的一件事,上面的对于插件的开发没有任何帮助,但是对一个软件系统质量提升有很大的帮助,这有益于问题的排查,软件的运行状态,性能等有一个可靠的输出结果来查看,让软件更加可靠。


课程中还讲到了参数校验、测试环境搭建、编写测试用例,但是这些在之前我写loader的时候都有讲过,这里我也就不做记录了。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
测试技术 开发者
如何确保 Webpack plugin 与其他插件的兼容性?
【10月更文挑战第23天】确保 Webpack plugin 与其他插件的兼容性需要从多个方面进行考虑和努力。通过遵循规范、进行充分测试、保持沟通协作等方式,
|
1月前
|
监控 前端开发 JavaScript
Webpack 中 HMR 插件的工作原理
【10月更文挑战第23天】可以进一步深入探讨 HMR 工作原理的具体细节、不同场景下的应用案例,以及与其他相关技术的结合应用等方面的内容。通过全面、系统地了解 HMR 插件的工作原理,能够更好地利用这一功能,为项目的成功开发提供有力保障。同时,要不断关注技术的发展动态,以便及时掌握最新的 HMR 技术和最佳实践。
|
2月前
|
移动开发 JavaScript 前端开发
webpack学习四:使用webpack配置plugin,来使用HtmlWebpackPlugin、uglifyjs-webpack-plugin、webpack-dev-server等插件简化开发
这篇文章主要介绍了如何通过配置Webpack的插件,如HtmlWebpackPlugin、uglifyjs-webpack-plugin和webpack-dev-server,来简化前端开发流程。
55 0
webpack学习四:使用webpack配置plugin,来使用HtmlWebpackPlugin、uglifyjs-webpack-plugin、webpack-dev-server等插件简化开发
|
2月前
|
前端开发 JavaScript 数据可视化
Webpack加载器和插件之间有什么区别
【10月更文挑战第13天】Webpack加载器和插件之间有什么区别
|
4月前
|
前端开发 JavaScript 开发者
Angular与Webpack协同优化:打造生产级别的打包配置——详解从基础设置到高级代码拆分和插件使用
【8月更文挑战第31天】在现代前端开发中,优化应用性能和加载时间至关重要,尤其是对于使用Angular框架的项目。本文通过代码示例详细展示了如何配置Webpack,以实现生产级别的打包优化。从基础配置到生产环境设置、代码拆分,再到使用加载器与插件,每个步骤都旨在提升应用效率,确保快速加载和稳定运行。通过这些配置,开发者能更好地控制资源打包,充分发挥Webpack的强大功能。
124 0
|
4月前
|
前端开发 开发者
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。本文阐述 DefinePlugin 的原理、用法及案例,包括安装配置、具体示例(如动态加载资源、配置接口地址)和注意事项,帮助开发者更好地利用此插件优化项目。
110 0
|
7月前
|
前端开发
【专栏】`webpack` 的 `DefinePlugin` 插件用于在编译时动态定义全局变量,实现环境变量差异化、配置参数动态化和条件编译
【4月更文挑战第29天】`webpack` 的 `DefinePlugin` 插件用于在编译时动态定义全局变量,实现环境变量差异化、配置参数动态化和条件编译。通过配置键值对,如 `ENV: JSON.stringify(process.env.NODE_ENV)`,可以在代码中根据环境执行相应逻辑。实际应用包括动态加载资源、动态配置接口地址和条件编译优化代码。注意变量定义的合法性和避免覆盖,解决变量未定义或值错误的问题,以提升开发效率和项目质量。
338 3
|
7月前
|
存储 缓存 JavaScript
《Webpack5 核心原理与应用实践》学习笔记-> webpack的loader开发技巧
《Webpack5 核心原理与应用实践》学习笔记-> webpack的loader开发技巧
90 1
|
7月前
|
缓存 监控 JavaScript
《Webpack5 核心原理与应用实践》学习笔记-> webpack极致性能优化
《Webpack5 核心原理与应用实践》学习笔记-> webpack极致性能优化
84 1
|
7月前
|
存储 缓存 前端开发
《Webpack5 核心原理与应用实践》学习笔记-> webpack5持久化缓存
《Webpack5 核心原理与应用实践》学习笔记-> webpack5持久化缓存
267 1