文章目录
输入 rollup 配置
- 初始化计时器,构建完成时输出每个阶段的耗时、内存占用等信息,会 wrapper 相应 hook 方法,添加计时相关功能
java
复制代码
initialiseTimers(inputOptions);
根据用户配置开启插件性能分析
javascript
复制代码
export function initialiseTimers(inputOptions: NormalizedInputOptions): void {
if (inputOptions.perf) { // 开启插件性能分析
timers = new Map();
timeStart = timeStartImpl;
timeEnd = timeEndImpl;
inputOptions.plugins = inputOptions.plugins!.map(getPluginWithTimers);
} else {
timeStart = NOOP;
timeEnd = NOOP;
}
}
性能分析函数实现
- 通过 node 相关 Api 获取堆栈信息,process.memoryUsage()
javascript
复制代码
let timers = new Map<string, Timer>();
// 记录开始
function timeStartImpl(label: string, level = 3): void {
label = getPersistedLabel(label, level);
const startMemory = process.memoryUsage().heapUsed;
const startTime = performance.now();
const timer = timers.get(label);
if (timer === undefined) { // 初始化创建对应标签
timers.set(label, {
memory: 0,
startMemory,
startTime,
time: 0,
totalMemory: 0
});
} else {
timer.startMemory = startMemory;
timer.startTime = startTime;
}
}
// 记录结束
function timeEndImpl(label: string, level = 3): void {
label = getPersistedLabel(label, level);
const timer = timers.get(label);
if (timer !== undefined) {
const currentMemory = process.memoryUsage().heapUsed;
timer.memory += currentMemory - timer.startMemory;
timer.time += performance.now() - timer.startTime;
timer.totalMemory = Math.max(timer.totalMemory, currentMemory);
}
}
分级输出结果
javascript
复制代码
function getPersistedLabel(label: string, level: number): string {
switch (level) {
case 1: {
return `# ${label}`;
}
case 2: {
return `## ${label}`;
}
case 3: {
return label;
}
default: {
return `${' '.repeat(level - 4)}- ${label}`;
}
}
}
装饰器模式拓展组件
- 枚举需要性能分析的插件 hookName ,添加timeStart、timeEnd 分析功能
javascript
复制代码
export function initialiseTimers(inputOptions: NormalizedInputOptions): void {
if (inputOptions.perf) { // 是否开启性能分析
timers = new Map();
timeStart = timeStartImpl; // 记录开始
timeEnd = timeEndImpl; // 记录结束
inputOptions.plugins = inputOptions.plugins!.map(getPluginWithTimers);
} else {
timeStart = NOOP;
timeEnd = NOOP;
}
}
javascript
复制代码
const TIMED_PLUGIN_HOOKS: readonly (keyof PluginHooks)[] = [
'augmentChunkHash',
'buildEnd',
'buildStart',
'...',
'writeBundle'
];
function getPluginWithTimers(plugin: any, index: number): Plugin {
// 遍历需要分析的组件
for (const hook of TIMED_PLUGIN_HOOKS) {
if (hook in plugin) {
let timerLabel = `plugin ${index}`;
if (plugin.name) {
timerLabel += ` (${plugin.name})`;
}
timerLabel += ` - ${hook}`; // 设置对应标签名
// 在调用原插件方法前后增加性能分析
const handler = function (this: any, ...parameters: readonly unknown[]) {
timeStart(timerLabel, 4);
const result = hookFunction.apply(this, parameters);
timeEnd(timerLabel, 4);
return result;
};
let hookFunction: any;
// 格式化插件配置
if (typeof plugin[hook].handler === 'function') {
hookFunction = plugin[hook].handler;
plugin[hook].handler = handler;
} else {
hookFunction = plugin[hook];
plugin[hook] = handler;
}
}
}
return plugin;
}