深入了解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. 打包时间统计:输出钩子插件可以记录构建过程中打包所花费的时间,并将结果打印出来,以便开发者了解构建性能和优化构建流程。

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

目录
相关文章
|
6月前
|
JavaScript
Vue组件选项编写代码的特点和注意事项
Vue组件选项编写代码的特点和注意事项
35 2
|
2月前
|
前端开发 JavaScript 区块链
react18函数组件+antd使用指南-使用代码集合以及报错记录汇总
本文介绍了多个React开发中常见的问题及其解决方案,包括但不限于:1)`useForm`实例未连接到任何`Form`元素的警告及解决方法;2)监听页面滚动事件的实现方式;3)React 18与antd 5.8.6中定制主题的方法;4)React结合antd 4.x版本自定义主题色的步骤;5)解决`ResizeObserver loop`相关报错的技巧;6)处理React设计表单时遇到的CDN资源加载失败问题;7)解决onClick事件传参问题;8)修复类型错误等。每部分均提供详细分析与实用代码示例,帮助开发者快速定位并解决问题。
48 2
|
4月前
|
JavaScript
Vue卸载eslint的写法,单独安装eslint,单独卸载eslint
Vue卸载eslint的写法,单独安装eslint,单独卸载eslint
|
6月前
|
JavaScript
Vue Steps步骤组件用法
Vue Steps步骤组件用法
194 0
|
6月前
|
JavaScript
组件中写选项的顺序(vue的问题)
组件中写选项的顺序(vue的问题)
35 0
|
6月前
|
JSON 前端开发 JavaScript
深入了解rollup(四)插件开发示例
Rollup是一个JavaScript模块打包器,它可以将多个模块打包成一个单独的文件,以便在浏览器中使用。与其他打包工具相比,Rollup的主要优势在于它可以生成更小、更快的代码。在本文中,我们将深入了解Rollup的插件开发。
88 1
|
6月前
|
缓存 前端开发 JavaScript
深入了解rollup(三)插件机制
Rollup 插件是一个对象,具有属性]、构建钩子 和 输出生成钩子 中的一个或多个,并遵循我们的约定。插件应作为一个导出一个函数的包进行发布,该函数可以使用插件特定的选项进行调用并返回此类对象。 插件允许你通过例如在打包之前进行转译代码或在node_modules文件夹中查找第三方模块来自定义 Rollup 的行为。
137 1
|
6月前
|
存储 JavaScript
vue3 setup语法糖 多条件搜索(带时间范围)
vue3 setup语法糖 多条件搜索(带时间范围)
218 0
|
JavaScript
vue项目发布时去除console语句
vue项目发布时去除console语句
53 0
使用 react.lazy 打包之后得文件如何不显示数字 #67
使用 react.lazy 打包之后得文件如何不显示数字 #67
55 0