Rollup插件
Rollup插件就是一个具有属性、输入钩子、输出钩子的对象; 如下所示
export default function myExample () {
return {
name: 'my-example', // 此名称将出现在警告和错误中
resolveId ( source ) {
if (source === 'virtual-module') {
// 这表示 rollup 不应询问其他插件或
// 从文件系统检查以找到此 ID
return source;
}
return null; // 其他ID应按通常方式处理
},
load ( id ) {
if (id === 'virtual-module') {
// "virtual-module"的源代码
return 'export default "This is virtual!"';
}
return null; // 其他ID应按通常方式处理
}
};
}
属性
插件的属性基本就是name, version,来描述插件的名称和版本
Rollup构建打包工作流
整个Rollup打包构建阶段,可以分为两个阶段build阶段和output阶段,所以所谓的构建钩子,指的就是Rollup构建阶段暴露出来的钩子;同理,输出钩子,就是Rollup输出阶段暴露出来的钩子;
构建钩子
先来看看Rollup构建阶段,重点说一下几个重要的钩子,其他可以在官网里面查询Rollup中文文档
| buildStart | 构建开始钩子; |
|---|---|
| resolveld | 文件路径解析钩子; |
| load | 加载模块内容钩子 |
| transform | 文件内容转换,比如babel转译等; |
输出钩子
在构建阶段,将模块依赖分析完毕以后,就可以进入输出阶段,可以简要看看输出阶段的工作流,讲解下几个重点的工作流
| outputOptions | 对output配置进行转换钩子; |
|---|---|
| renderStart | 开始正式打包钩子; |
| renderChunk | 开始生成chunk钩子 |
| generateBundle | 开始整合chunk钩子,可以对chunk进行一些删减等操作; |
| writeBundle | 输出构建产出到磁盘钩子 |
常见rollup-plugin源码分析
rollup-plugin-alias
别名处理的插件,类似于webpack中的Reslove.alias,可以改写资源的引入方式,将路径引入更加简便, 比如@用来简要路径
import alias from '@rollup/plugin-alias';
export default {
input: ["./src/index.js"],
output: {
file: "bundle.js",
format: 'es'
},
plugins: [
alias({
entries: [{
find: '@', replacement: '.'
}]
}),
]
}
实现原理大致是在构建resolveId阶段,识别需要替换的路经,用replacement做替换;下面是rollup-plugin-alias源码
export default function alias(options: RollupAliasOptions = {}): Plugin {
const entries = getEntries(options);
if (entries.length === 0) {
return {
name: 'alias',
resolveId: () => null
};
}
return {
name: 'alias',
resolveId(importee, importer, resolveOptions) {
const matchedEntry = entries.find((entry) => matches(entry.find, importee));
if (!matchedEntry) {
return null;
}
// 针对传入的路径用replacement来替换
const updatedId = importee.replace(matchedEntry.find, matchedEntry.replacement);
if (matchedEntry.resolverFunction) {
return matchedEntry.resolverFunction.call(this, updatedId, importer, resolveOptions);
}
// 这个rollup祖代的路径解析算法, 返回资源对象,资源对象是一个带id的对象;
return this.resolve(
updatedId,
importer,
Object.assign({ skipSelf: true }, resolveOptions)
).then((resolved) => {
if (resolved) return resolved;
// 如果不是绝对路径就报错
if (!path.isAbsolute(updatedId)) {
this.warn(
`rewrote ${importee} to ${updatedId} but was not an abolute path and was not handled by other plugins. ` +
`This will lead to duplicated modules for the same path. ` +
`To avoid duplicating modules, you should resolve to an absolute path.`
);
}
return { id: updatedId };
});
}
};
}
@rollup/plugin-image
图片解析插件,在webpack打包构建过程,针对除js之外的资源,需要loader来解析;rollup中也是这样,对于图片资源需要进行资源转换,这里采用@rollup/plugin-image来进行图片资源的转换处理
import image from "@rollup/plugin-image";
import alias from '@rollup/plugin-alias';
export default {
input: ["./src/index.js"],
output: {
file: "bundle.js",
format: 'es'
},
plugins: [
image()
]
}
实现原理大致就是,在构建阶段,load加载资源的钩子过程中,读取图片的资源,用import的方式来进行重写;可以看下源码实现;
const constTemplate = ({ dataUri }) => `
var img = "${dataUri}";
export default img;
`;
export default function image(opts = {}) {
const options = Object.assign({}, defaults, opts);
const filter = createFilter(options.include, options.exclude);
return {
name: 'image',
load(id) {
if (!filter(id)) {
return null;
}
const mime = mimeTypes[extname(id)];
if (!mime) {
// not an image
return null;
}
this.addWatchFile(id);
const isSvg = mime === mimeTypes['.svg'];
const format = isSvg ? 'utf-8' : 'base64';
// 如果格式不是svg,就用base64来加载读取图片资源;
const source = readFileSync(id, format).replace(/[\r\n]+/gm, '');
const dataUri = getDataUri({ format, isSvg, mime, source });
// 如果没有定义需要dom方式,就利用ES module来加载解析图片资源;
const code = options.dom ? domTemplate({ dataUri }) : constTemplate({ dataUri });
return code.trim();
}
};
}
总结
以上从Rollup插件就是一个带有属性,构建钩子,输出钩子的对象,简要分析了Rollup整个打包构建的工作流,来分析了什么是构建钩子,什么是输出钩子