引言
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
来进行自定义元信息解析 -
生成chunk调用
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
bash
npm install uglify-js -D
rollup-plugin-uglify
javascript
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
js
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
js
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
js
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构建过程中起到了关键作用。它们可以对生成的输出文件进行处理、优化或者添加额外的功能。以下是对输出钩子插件的作用进行总结:
-
代码压缩:输出钩子插件可以使用压缩工具(如uglify-js)对生成的代码进行压缩,以减小文件大小并提高加载速度。
-
文件大小统计:输出钩子插件可以统计生成的输出文件的大小,以便开发者了解每个文件的占用空间,并进行优化和调整。
-
文件格式转换:输出钩子插件可以将生成的代码转换为不同的格式,如将ES6模块转换为CommonJS模块,或将JavaScript代码转换为其他语言(如TypeScript)。
-
代码分割和合并:输出钩子插件可以根据需求对生成的代码进行分割和合并,以优化加载性能和减少网络请求。
-
添加额外功能:输出钩子插件可以在生成的输出文件中添加额外的功能或元数据,如添加版本号、注入环境变量等。
-
打包时间统计:输出钩子插件可以记录构建过程中打包所花费的时间,并将结果打印出来,以便开发者了解构建性能和优化构建流程。
总之,输出钩子插件可以在生成最终输出文件的过程中对代码进行处理和优化,以满足开发者的需求,并提供更好的性能和功能。