深入了解rollup(五)插件输出生成钩子

简介: 输出生成钩子可以提供有关生成的产物的信息并在构建完成后修改构建。它们的工作方式和类型与 构建钩子 相同,但是对于每个调用 bundle.generate(outputOptions) 或 bundle.write(outputOptions),它们都会单独调用。仅使用输出生成钩子的插件也可以通过输出选项传递,并且因此仅针对某些输出运行。

引言

Rollup是一个JavaScript模块打包器,它可以将多个模块打包成一个单独的文件,以便在浏览器中使用。与其他打包工具相比,Rollup的主要优势在于它可以生成更小、更快的代码。在本文中,我们将深入了解Rollup的插件输出生成钩子。



输出生成钩子

输出生成钩子可以提供有关生成的产物的信息并在构建完成后修改构建。它们的工作方式和类型与 构建钩子 相同,但是对于每个调用 bundle.generate(outputOptions)bundle.write(outputOptions),它们都会单独调用。仅使用输出生成钩子的插件也可以通过输出选项传递,并且因此仅针对某些输出运行。

输出生成阶段的第一个钩子是 outputOptions,最后一个钩子是 generateBundle(如果通过 bundle.generate(...) 成功生成输出),writeBundle(如果通过 bundle.write(...) 成功生成输出),或 renderError(如果在输出生成期间的任何时候发生错误)。

此外,closeBundle可以作为最后一个钩子调用,但是用户有责任手动调用 bundle.close()来触发此操作。CLI 将始终确保这一点。

输出钩子执行顺序

  1. 执行所有插件的 outputOptions 钩子函数,对 output 配置进行转换
  2. 执行 renderStart,该钩子读取所有outputOptions钩子的转换之后的输出选项
  3. 扫描 动态import 语句执行 renderDynamicImport 钩子,让开发者能自定义动态import的内容与行为
  4. 并发执行所有插件的 banner、footer、intro、outro 钩子,这四个钩子功能简单,就是往打包产物的固定位置(比如头部和尾部)插入一些自定义的内容,比如版本号、作者、内容、项目介绍等等
  5. 是否存在 import.meta 语句,没有就直接进入下一步,否则:对于import.meta.url调用 resolveFileUrl 来自定义 url 解析逻辑。对于import.meta调用 resolveImportMeta 来进行自定义元信息解析
  6. 生成chunk调用renderChunk钩子,便于在该钩子中进行自定义操作。如果生成的chunk文件有hash值,执行 augmentChunkHash 钩子,来决定是否更改 chunk 的哈希值。
  7. 调用 generateBundle 钩子,这个钩子的入参里面会包含所有的打包产物信息,包括 chunk (打包后的代码)、asset(最终的静态资源文件)。在这个钩子中你做自定义自己的操作,比如:可以在这里删除一些 chunk 或者 asset,最终被删除的内容将不会作为产物输出
  8. rollup.rollup方法会返回一个bundle对象,bundle对象的write方法,会触发writeBundle钩子,传入所有的打包产物信息,包括 chunkasset,与generateBundle钩子非常相似。唯一的区别是writeBundle钩子执行的时候,产物已经输出了。而 generateBundle 执行的时候产物还并没有输出。简单来说,顺序是:generateBundle--->输出并保存产物到磁盘--->writeBundle
  9. bundleclose方法被调用时,会触发closeBundle钩子,这个output阶段结束

代码压缩插件示例

安装uglify-js

npm install uglify-js -D

rollup-plugin-uglify

import { minify } from'uglify-js';
exportdefaultfunctionuglifyPlugin() {
return {
name: 'uglify',
renderChunk(code) {
constresult=minify(code);
if (result.error) {
thrownewError(`minify error: ${result.error}`);
      }
return {
code: result.code,
map: { mappings: '' }
      };
    },
  };
}

这段代码是一个使用uglify-js库进行代码压缩的Rollup插件。

  1. minify(code): 这个函数来自于uglify-js库,用于对给定的JavaScript代码进行压缩。它接受一个字符串参数code,表示要压缩的JavaScript代码,然后返回一个对象,包含压缩后的代码和可能的错误信息。
  2. throw new Error(message): 这个语句用于抛出一个错误。在这段代码中,如果压缩过程中出现错误,就会抛出一个带有错误信息的Error对象。
  3. renderChunk(code): 这是Rollup插件中定义的一个钩子函数,用于处理每个chunk(模块)生成最终输出文件时的逻辑。在这段代码中,它接受一个参数code,表示当前chunk的源代码。然后使用minify()函数对源代码进行压缩,并检查是否有错误发生。如果有错误,则抛出一个带有错误信息的Error对象;否则返回一个包含压缩后代码和空映射(map)对象的结果。
  4. export default function uglifyPlugin() { ... }: 这是整个插件导出的默认函数。当其他地方导入这个插件时,实际上导入了这个默认函数。该函数返回一个包含namerenderChunk()方法的对象,作为Rollup插件的配置。

rollup.config.mjs

import { defineConfig } from"rollup";
importuglifyPluginfrom'./plugins/rollup-plugin-uglify.js'exportdefaultdefineConfig({
input: "src/index.js",
output: {
dir: "dist",
format: "esm",
sourcemap: true,
  },
plugins: [
uglifyPlugin(),
  ],
});

打包大小和时间示例

该插件在构建开始时记录开始时间,在生成最终输出文件时统计文件大小,并在打包完成后计算并打印出打包时间。

rollup-plugin-bundle-stats

exportdefaultfunctionbundleStats() {
letstartTime;
return {
name: "bundle-stats",
options() { 
startTime=Date.now();
    },
generateBundle(_, bundle) { 
constfileSizes= {};
for(const [fileName, output] ofObject.entries(bundle)) { 
if(output.type==="chunk") { 
constcontent=output.code;
constsize=Buffer.byteLength(content, "utf-8");
constsizeKB= (size/1024).toFixed(2);
fileSizes[fileName] =sizeKB+" KB";
        }
      }
console.table(fileSizes);
    },
closeBundle() { 
consttotalTime=Date.now() -startTime;
console.log("打包时间:"+totalTime+"ms");
    }
  }
}
  1. options(): 这个函数是Rollup插件中的一个钩子函数,在构建开始时执行。在这段代码中,它被用来记录构建开始的时间,以便后续计算打包时间。
  2. generateBundle(_, bundle): 这个函数也是Rollup插件中的一个钩子函数,在生成最终输出文件时执行。它接受两个参数,第一个参数_表示当前构建选项,我们在这里不使用它;第二个参数bundle表示生成的bundle对象,包含了所有输出文件的信息。 在这段代码中,它被用来遍历bundle对象,并计算每个chunk文件的大小。对于每个chunk文件,它获取其代码内容并使用Buffer.byteLength()函数计算其字节长度。然后将字节长度转换为KB,并将结果存储在fileSizes对象中。 最后,使用console.table()函数将文件大小以表格形式打印出来。
  3. closeBundle(): 这个函数也是Rollup插件中的一个钩子函数,在打包完成后执行。在这段代码中,它被用来计算并打印出整个打包过程所花费的时间。

rollup.config.mjs

import { defineConfig } from"rollup";
importbundleStatsfrom'./plugins/rollup-plugin-bundle-stats.js'exportdefaultdefineConfig({
input: "src/index.js",
output: {
dir: "dist",
format: "esm",
sourcemap: true,
  },
plugins: [
bundleStats(),
  ],
});

输出结果

总结

输出钩子插件在Rollup构建过程中起到了关键作用。它们可以对生成的输出文件进行处理、优化或者添加额外的功能。以下是对输出钩子插件的作用进行总结:

  1. 代码压缩:输出钩子插件可以使用压缩工具(如uglify-js)对生成的代码进行压缩,以减小文件大小并提高加载速度。
  2. 文件大小统计:输出钩子插件可以统计生成的输出文件的大小,以便开发者了解每个文件的占用空间,并进行优化和调整。
  3. 文件格式转换:输出钩子插件可以将生成的代码转换为不同的格式,如将ES6模块转换为CommonJS模块,或将JavaScript代码转换为其他语言(如TypeScript)。
  4. 代码分割和合并:输出钩子插件可以根据需求对生成的代码进行分割和合并,以优化加载性能和减少网络请求。
  5. 添加额外功能:输出钩子插件可以在生成的输出文件中添加额外的功能或元数据,如添加版本号、注入环境变量等。
  6. 打包时间统计:输出钩子插件可以记录构建过程中打包所花费的时间,并将结果打印出来,以便开发者了解构建性能和优化构建流程。

总之,输出钩子插件可以在生成最终输出文件的过程中对代码进行处理和优化,以满足开发者的需求,并提供更好的性能和功能。

目录
相关文章
|
11月前
|
Linux 网络安全 数据安全/隐私保护
在CentOS 7.9中安装sshpass教程
如果在控制台显示出sshpass的使用方法,那就说明我们的大餐已经准备好,sshpass已经成功安装。 以上就是在 CentOS 7.9 中安装 sshpass 的彩色步骤,专业而生动,就像大厨在厨房一样顺利。
477 8
|
JSON 前端开发 JavaScript
Vite 共享配置
本文介绍了 Vite 配置中的 `base`、`mode`、`plugins`、`resolve` 和 `css` 等关键配置项。`base` 用于设置公共基础路径,`mode` 指定环境模式,默认为 `development` 和 `production`。`plugins` 注册项目中使用的插件。`resolve` 包含别名配置、去重依赖项和模块入口字段等选项。`css` 配置 CSS 预处理器及其选项,如导入样式变量文件。
347 6
|
数据可视化 编译器 Python
Manim:数学可视化的强大工具 | python小知识
Manim(Manim Community Edition)是由3Blue1Brown的Grant Sanderson开发的数学动画引擎,专为数学和科学可视化设计。它结合了Python的灵活性与LaTeX的精确性,支持多领域的内容展示,能生成清晰、精确的数学动画,广泛应用于教育视频制作。安装简单,入门容易,适合教育工作者和编程爱好者使用。
3275 7
|
前端开发 JavaScript UED
CSS滚动效果和视差滚动的原理、应用及其对用户体验的影响。从平滑滚动到元素跟随,再到滚动触发动画
本文探讨了CSS滚动效果和视差滚动的原理、应用及其对用户体验的影响。从平滑滚动到元素跟随,再到滚动触发动画,这些效果增强了页面的吸引力和互动性。视差滚动通过不同层次元素的差异化移动,增加了页面的深度感和沉浸感。文章还讨论了实现方法、性能优化及案例分析,旨在为设计师和开发者提供实用指导。
382 7
|
运维 监控 Cloud Native
运维之道:从基础到进阶的实战指南
【10月更文挑战第20天】 在数字化时代,运维作为保障系统稳定运行的重要环节,其重要性不言而喻。本文将带你深入探索运维的核心领域,从基础概念解析到进阶技能提升,通过一系列实用的技巧和策略,帮助你构建高效、可靠的运维体系,确保业务连续性和数据安全。
908 6
|
缓存 JavaScript 前端开发
JavaScript模块化:CommonJS与ES Modules的对比与使用
【4月更文挑战第22天】本文探讨了JavaScript模块化的两种规范——CommonJS和ES Modules。CommonJS适用于Node.js,通过`require`同步加载模块,而ES Modules(ES6模块)用于前端,支持异步加载和静态导入导出。CommonJS有缓存,ES Modules无缓存。在选择时,Node.js环境常用CommonJS,但趋势正转向ES Modules,前端项目推荐使用ES Modules以利用其优化性能的优势。
1295 0
|
前端开发 开发者
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。本文阐述 DefinePlugin 的原理、用法及案例,包括安装配置、具体示例(如动态加载资源、配置接口地址)和注意事项,帮助开发者更好地利用此插件优化项目。
489 0
|
JavaScript 前端开发 Go
微前端之qiankun 介绍和简单使用
微前端之qiankun 介绍和简单使用
7275 0
|
缓存 NoSQL JavaScript
从入门到精通:.gitlab-ci.yml文件的完整指南
从入门到精通:.gitlab-ci.yml文件的完整指南
1359 2
|
存储 Go Python
[golang]使用gopsutil获取系统信息
[golang]使用gopsutil获取系统信息
544 0