引言
--
Rollup是一个JavaScript模块打包器,它可以将多个模块打包成一个单独的文件,以便在浏览器中使用。与其他打包工具相比,Rollup的主要优势在于它可以生成更小、更快的代码。在本文中,我们将深入了解Rollup的插件输出生成钩子。
输出生成钩子
输出生成钩子可以提供有关生成的产物的信息并在构建完成后修改构建。它们的工作方式和类型与 构建钩子 相同,但是对于每个调用 bundle.generate(outputOptions)
或 bundle.write(outputOptions)
,它们都会单独调用。仅使用输出生成钩子的插件也可以通过输出选项传递,并且因此仅针对某些输出运行。
输出生成阶段的第一个钩子是 outputOptions
,最后一个钩子是 generateBundle
(如果通过 bundle.generate(...)
成功生成输出),writeBundle
(如果通过 bundle.write(...)
成功生成输出),或 renderError
(如果在输出生成期间的任何时候发生错误)。
此外,closeBundle
可以作为最后一个钩子调用,但是用户有责任手动调用 bundle.close()
来触发此操作。CLI 将始终确保这一点。
输出钩子执行顺序
outputOptions
钩子函数,对 output
配置进行转换renderStart
,该钩子读取所有outputOptions钩子的转换之后的输出选项动态import
语句执行 renderDynamicImport
钩子,让开发者能自定义动态import
的内容与行为banner、footer、intro、outro
钩子,这四个钩子功能简单,就是往打包产物的固定位置(比如头部和尾部)插入一些自定义的内容,比如版本号、作者、内容、项目介绍等等import.meta
语句,没有就直接进入下一步,否则:对于import.meta.url
调用 resolveFileUrl
来自定义 url 解析逻辑。对于import.meta
调用 resolveImportMeta
来进行自定义元信息解析renderChunk
钩子,便于在该钩子中进行自定义操作。如果生成的chunk文件有hash值,执行 augmentChunkHash
钩子,来决定是否更改 chunk
的哈希值。generateBundle
钩子,这个钩子的入参里面会包含所有的打包产物信息,包括 chunk
(打包后的代码)、asset
(最终的静态资源文件)。在这个钩子中你做自定义自己的操作,比如:可以在这里删除一些 chunk
或者 asset
,最终被删除的内容将不会作为产物输出rollup.rollup
方法会返回一个bundle
对象,bundle
对象的write方法,会触发writeBundle
钩子,传入所有的打包产物信息,包括 chunk
和 asset
,与generateBundle
钩子非常相似。唯一的区别是writeBundle
钩子执行的时候,产物已经输出了。而 generateBundle
执行的时候产物还并没有输出。简单来说,顺序是:generateBundle--->输出并保存产物到磁盘--->writeBundle
bundle
的close
方法被调用时,会触发closeBundle
钩子,这个output阶段结束代码压缩插件示例
安装uglify-js
npm install uglify-js -D
rollup-plugin-uglify
import { minify } from 'uglify-js';
export default function uglifyPlugin() {
return {
name: 'uglify',
renderChunk(code) {
const result = minify(code);
if (result.error) {
throw new Error(`minify error: ${result.error}`);
}
return {
code: result.code,
map: { mappings: '' }
};
},
};
}
这段代码是一个使用uglify-js库进行代码压缩的Rollup插件。
minify(code)
: 这个函数来自于uglify-js库,用于对给定的JavaScript代码进行压缩。它接受一个字符串参数code
,表示要压缩的JavaScript代码,然后返回一个对象,包含压缩后的代码和可能的错误信息。throw new Error(message)
: 这个语句用于抛出一个错误。在这段代码中,如果压缩过程中出现错误,就会抛出一个带有错误信息的Error对象。renderChunk(code)
: 这是Rollup插件中定义的一个钩子函数,用于处理每个chunk(模块)生成最终输出文件时的逻辑。在这段代码中,它接受一个参数code
,表示当前chunk的源代码。然后使用minify()
函数对源代码进行压缩,并检查是否有错误发生。如果有错误,则抛出一个带有错误信息的Error对象;否则返回一个包含压缩后代码和空映射(map)对象的结果。export default function uglifyPlugin() { ... }
: 这是整个插件导出的默认函数。当其他地方导入这个插件时,实际上导入了这个默认函数。该函数返回一个包含name
和renderChunk()
方法的对象,作为Rollup插件的配置。rollup.config.mjs
import { defineConfig } from "rollup";
import uglifyPlugin from './plugins/rollup-plugin-uglify.js'
export default defineConfig({
input: "src/index.js",
output: {
dir: "dist",
format: "esm",
sourcemap: true,
},
plugins: [
uglifyPlugin(),
],
});
打包大小和时间示例
该插件在构建开始时记录开始时间,在生成最终输出文件时统计文件大小,并在打包完成后计算并打印出打包时间。
rollup-plugin-bundle-stats
export default function bundleStats() {
let startTime;
return {
name: "bundle-stats",
options() {
startTime = Date.now();
},
generateBundle(_, bundle) {
const fileSizes = {};
for(const [fileName, output] of Object.entries(bundle)) {
if(output.type === "chunk") {
const content = output.code;
const size = Buffer.byteLength(content, "utf-8");
const sizeKB = (size / 1024).toFixed(2);
fileSizes[fileName] = sizeKB + " KB";
}
}
console.table(fileSizes);
},
closeBundle() {
const totalTime = Date.now() - startTime;
console.log("打包时间:" + totalTime + "ms");
}
}
}
options()
: 这个函数是Rollup插件中的一个钩子函数,在构建开始时执行。在这段代码中,它被用来记录构建开始的时间,以便后续计算打包时间。generateBundle(_, bundle)
: 这个函数也是Rollup插件中的一个钩子函数,在生成最终输出文件时执行。它接受两个参数,第一个参数_
表示当前构建选项,我们在这里不使用它;第二个参数bundle
表示生成的bundle对象,包含了所有输出文件的信息。 在这段代码中,它被用来遍历bundle对象,并计算每个chunk文件的大小。对于每个chunk文件,它获取其代码内容并使用Buffer.byteLength()
函数计算其字节长度。然后将字节长度转换为KB,并将结果存储在fileSizes
对象中。 最后,使用console.table()
函数将文件大小以表格形式打印出来。closeBundle()
: 这个函数也是Rollup插件中的一个钩子函数,在打包完成后执行。在这段代码中,它被用来计算并打印出整个打包过程所花费的时间。rollup.config.mjs
import { defineConfig } from "rollup";
import bundleStats from './plugins/rollup-plugin-bundle-stats.js'
export default defineConfig({
input: "src/index.js",
output: {
dir: "dist",
format: "esm",
sourcemap: true,
},
plugins: [
bundleStats(),
],
});
输出结果
总结
--
输出钩子插件在Rollup构建过程中起到了关键作用。它们可以对生成的输出文件进行处理、优化或者添加额外的功能。以下是对输出钩子插件的作用进行总结:
总之,输出钩子插件可以在生成最终输出文件的过程中对代码进行处理和优化,以满足开发者的需求,并提供更好的性能和功能。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。