一个灵活的库,用于测量第一个dom生成的时间(FP/FCP)、用户最早可操作时间(fid)和组件的生命周期性能。向Google Analytics或您理想的跟踪工具报告实际用户测量值。
English | 简体中文
- ⏰ 用最新的API获取精准的性能信息
- 🔨 跨浏览器测试
- 🚿 过滤虚假的结果
- 🔭 浏览器跟踪器内置
- 🤙 支持 async/await 语法
- 🛰 灵活的跟踪工具
- ⚡️ 内置requestIdleCallback策略,0 毫秒浪费
Perfume 利用最新的 W3C Performance 提案 (比如 PerformanceObserver), 来测试重要的性能信息! ⚡️
npm (https://www.npmjs.com/package/perfume.js):
npm install perfume.js --save-dev
你可以直接将整个库导入。
import Perfume from 'perfume.js';
也可以直接使用umd(Universal Module Definition)方式引入。
import Perfume from 'node_modules/perfume.js/dist/perfume.umd.min.js';
首次绘制 (FP)
FP 标记浏览器渲染任何在视觉上不同于导航前屏幕内容之内容的时间点
const perfume = new Perfume({
firstPaint: true
});
// Perfume.js: First Paint 1482.00 ms
首次内容绘制 (FCP)
FCP 标记的是浏览器渲染来自 DOM 第一位内容的时间点,该内容可能是文本、图像、SVG 甚至 <canvas>
元素。
const perfume = new Perfume({
firstContentfulPaint: true
});
// Perfume.js: First Contentful Paint 2029.00 ms
FID 测量用户首次与站点交互时(即,当他们单击链接,点击按钮或使用自定义的,由JavaScript驱动的控件)到浏览器实际能够回应这种互动的延时。
const perfume = new Perfume({
firstInputDelay: true
});
// Perfume.js: First Input Delay 3.20 ms
性能标记 (自定义时间测量API ) 用于在浏览器的性能条目中创建自定义性能标记。
perfume.start('fibonacci');
fibonacci(400);
perfume.end('fibonacci');
// Perfume.js: fibonacci 0.14 ms
当浏览器将像素渲染到屏幕时,此指标会在创建新组件后立即标记该点。
perfume.start('togglePopover');
$(element).popover('toggle');
perfume.endPaint('togglePopover');
// Perfume.js: togglePopover 10.54 ms
保存一段时间并且按照想要的方式打印出来
const perfume = new Perfume({
logPrefix: '🍹 HayesValley.js:'
});
perfume.start('fibonacci');
fibonacci(400);
const duration = this.perfume.end('fibonacci');
// 🍹 HayesValley.js: Custom logging 0.14 ms
在 Angular 框架中,我们首先配置Perfume
来收集初始化性能指标(比如 FCP,FID),首先确保在NgModule
中引入PefumeModule
,使PerformanceObserver
能正常工作。
在大型应用中使用@PerfumeAfterViewInit()
装饰器来监听复杂组件的渲染性能,避免在 NgFor
中使用它,应该关注包含较小组件集合的组件。
NgPerfume
服务公开了所有的Perfume
实例的方法和属性,您可以对组件的生命周期进行标记,并结合APIs来监测组件绘制所需要的时间。
import { NgPerfume, PerfumeModule, PerfumeAfterViewInit } from 'perfume.js/angular';
import { AppComponent } from './app.component';
import { AppApi } from './app-api';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.less'],
})
@PerfumeAfterViewInit('AppComponent')
export class AppComponent implements AfterViewInit {
data: AwesomeType;
constructor(public perfume: NgPerfume) {
// 开始测量要绘制的组件时间
this.perfume.start('AppComponentAfterPaint');
}
ngAfterViewInit() {
this.loadAwesomeData();
}
loadAwesomeData = async () => {
await AppApi.loadAmazingData();
this.data = AppApi.loadAwesomeData();
// 结束测量部件绘制时间
this.perfume.endPaint('AppComponentAfterPaint');
}
}
// Perfume.js config, supports AOT and DI
export const PerfumeConfig = {
firstContentfulPaint: true,
firstInputDelay: true,
};
@NgModule({
declarations: [AppComponent],
imports: [PerfumeModule.forRoot(PerfumeConfig), BrowserModule],
bootstrap: [AppComponent],
})
export class AppModule {}
结合React 框架,我们可以开始配置Perfume
来收集初始化性能指标(比如 FCP,FID)。
将perfume.start()
和 perfume.endPaint()
API用于组件的生命周期,已测量绘制组件所需要的时间。
import React from 'react';
import Perfume from 'perfume.js';
import { AppApi } from './AppApi';
const perfume = new Perfume({
firstContentfulPaint: true,
firstInputDelay: true
});
export default class App extends React.Component {
constructor() {
// 开始测量要绘制的组件时间
perfume.start('AppAfterPaint');
}
loadData = async () => {
await AppApi.loadAmazingData();
await AppApi.loadAwesomeData();
// 结束测量部件绘制时间
perfume.endPaint('AppAfterPaint');
}
render() {
const data = this.loadData();
return (
<div>
<h2>Awesome App</h2>
<div>{data}</div>
</div>
);
}
}
在Perfume.js
配置回调以支持任意平台
const perfume = new Perfume({
analyticsTracker: ({ metricName, data, duration, browser }) => {
myAnalyticsTool.track(metricName, duration, browser.name, browser.os);
})
});
在构造函数中提供给Perfume.js默认选项。
const options = {
// Metrics
firstContentfulPaint: false,
firstPaint: false,
firstInputDelay: false,
dataConsumption: false,
navigationTiming: false,
// Analytics
analyticsTracker: options => {},
browserTracker: false,
// Logging
logPrefix: 'Perfume.js:',
logging: true,
maxMeasureTime: 15000,
warning: false,
debugging: false,
};
Perfume.js 公开了一些方法和属性,这些方法和属性可能对扩展这个库的人有用。
const perfume = new Perfume({
firstContentfulPaint: true,
firstInputDelay: true,
});
// Values
perfume.firstPaintDuration;
perfume.firstContentfulPaintDuration;
perfume.firstInputDelayDuration;
// Aync Values
const durationFCP = await perfume.observeFirstContentfulPaint;
const durationFID = await perfume.observeFirstInputDelay;
// 将自定义用户时间标识发送到Google Analytics
perfume.sendTiming(metricName, durationFCP);
npm start
: Runnpm run build
in watch modenpm run test
: Run test suitenpm run test:watch
: Run test suite in interactive watch modenpm run build
: Generate bundles and typingsnpm run lint
: Lints code
Made with ☕️ by @zizzamia and I want to thank some friends and projects for the work they did:
- Leveraging the Performance Metrics that Most Affect User Experience for documenting this new User-centric performance metrics;
- Performance Timeline Level 2 the definition of PerformanceObserver in that specification;
- The Contributors for their much appreciated Pull Requests and bug reports;
- you for the star you'll give this project 😉 and for supporting me by giving my project a try 😄
This project exists thanks to all the people who contribute.
Thank you to all our backers! 🙏 [Become a backer]
Code and documentation copyright 2019 Leonardo Zizzamia. Code released under the MIT license. Docs released under Creative Commons.
Leonardo Zizzamia |