Feel-good tool for FP, FCP, FID performance categories and component lifecycle performance, written by Google Development team engineer Leonardo Zizzamia. Personally feel good, translated Readme and PR has been merged into the main branch.
Perfume.js
A flexible library that measures the time of first DOM generation (FP/FCP), earliest user operable time (FID), and component lifecycle performance. Report actual user measurements to Google Analytics or your preferred tracking tool.
English | simplified Chinese
Why Perfume.js?
- ⏰ Get accurate performance information with the latest apis
- 🔨 Cross-browser testing
- 🚿 Filter spurious results
- 🔭 browser tracker built in
- 🤙 supports async/await syntax
- 🛰 Flexible tracking tool
- ⚡️ Built-in Idle Until Urgent policy, 0 ms waste
User-centric performance metrics
Perfume takes advantage of the latest W3C Performance proposals, such as PerformanceObserver, to test important Performance information! ⚡ ️
- First drawing (FP)
- First Content Rendering (FCP)
- First input delay (FID)
- Framework and component life cycle monitoring
The installation
NPM (www.npmjs.com/package/per)… :
npm install perfume.js --save-dev
Copy the code
The introduction of
You can import the entire library directly.
import Perfume from 'perfume.js';
Copy the code
It can also be imported directly using Universal Module Definition (UMD).
import Perfume from 'node_modules/perfume.js/dist/perfume.umd.min.js';
Copy the code
Start measuring
First drawing (FP)
FP marks the point at which the browser renders any content that is visually different from the content of the screen before navigation
const perfume = new Perfume({
firstPaint: true
});
// Perfume.js: First Paint 1482.00 ms
Copy the code
First content drawing (FCP)
FCP marks the point at which the browser renders the first content from the DOM, which could be text, image, SVG, or even a
const perfume = new Perfume({
firstContentfulPaint: true
});
// Perfume.js: First Contentful Paint 2029.00 ms
Copy the code
First input delay (FID)
FID measures the delay between when a user first interacts with the site (that is, when they click a link, click a button, or use a custom, javascript-driven control) and when the browser is actually able to respond to that interaction.
const perfume = new Perfume({
firstInputDelay: true
});
// Perfume.js: First Input Delay 3.20 ms
Copy the code
Mark metrics in developer tools
Performance tags (Custom time measurement API) are used to create custom performance tags in the browser’s performance entries.
perfume.start('fibonacci');
fibonacci(400);
perfume.end('fibonacci');
// Perfume.js: fibonacci 0.14 ms
Copy the code
Component first render
When the browser renders the pixel to the screen, this metric marks the point as soon as the new component is created.
perfume.start('togglePopover');
$(element).popover('toggle');
perfume.endPaint('togglePopover');
// Perfume.js: togglePopover 10.54 ms
Copy the code
Custom logging
Keep it for a while and print it out the way you want
const perfume = new Perfume({
logPrefix: '🍹 HayesValley. Js:'
});
perfume.start('fibonacci');
fibonacci(400);
const duration = this.perfume.end('fibonacci');
perfume.log('Custom logging', duration);
// 🍹 hayesvalley.js: Custom logging 0.14ms
Copy the code
The framework
Angular
In the Angular framework, we first configure Perfume to collect initialization performance metrics (such as FCP,FID), and first make sure to introduce PefumeModule in the NgModule to make the PerformanceObserver work.
Use the @perfumeAfterViewinit () decorator in large applications to listen for the rendering performance of complex components. Avoid using it in NgFor and focus on components that contain smaller sets of components.
NgPerfume exposes methods and attributes for all Perfume instances, allowing you to tag the lifecycle of the component and monitor how long it takes to draw the component using 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) {
// Start measuring the component time to draw
this.perfume.start('AppComponentAfterPaint');
}
ngAfterViewInit() {
this.loadAwesomeData();
}
loadAwesomeData = async() = > {await AppApi.loadAmazingData();
this.data = AppApi.loadAwesomeData();
// Finish measuring component drawing time
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 {}
Copy the code
React
With the React framework, we can start configuring Perfume to collect initial performance metrics (such as FCP,FID).
The perfume.start() and perfume.endpaint () apis are used for the life cycle of the component to measure the time it takes to draw the component.
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() {
// Start measuring the component time to draw
perfume.start('AppAfterPaint');
}
loadData = async() = > {await AppApi.loadAmazingData();
await AppApi.loadAwesomeData();
// Finish measuring component drawing time
perfume.endPaint('AppAfterPaint');
}
render() {
const data = this.loadData();
return (
<div>
<h2>Awesome App</h2>
<div>{data}</div>
</div>); }}Copy the code
Analysis of the
Google Analytics
If you want to send Perfume results to Google Analytics User Timing, set enable: True and custom User timing variable timingVar:”name”.
const perfume = new Perfume({
googleAnalytics: {
enable: true.timingVar: 'userId'}});Copy the code
Common analysis platform support
Configure callbacks in Perfume. Js to support any platform
const perfume = new Perfume({
analyticsTracker: (metricName, duration, browser) = >{ myAnalyticsTool.track(metricName, duration, browser.name, browser.os); })});Copy the code
Custom & toolset
The default option
Give Perfume. Js a default option in the constructor.
const options = {
// Metrics
firstContentfulPaint: false.firstPaint: false.firstInputDelay: false.// Analytics
analyticsTracker: undefined.browserTracker: false.googleAnalytics: {
enable: false.timingVar: 'name',},// Logging
logPrefix: 'Perfume.js:'.logging: true.maxMeasureTime: 15000.warning: false.debugging: false};Copy the code
Tool set
Perfume. Js exposes a number of methods and properties that might be useful to anyone extending the library.
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;
// Send the custom user time id to Google Analytics
perfume.sendTiming(metricName, durationFCP);
Copy the code
The development of
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
The article
- First (Contentful) Paint with a touch of Perfume(.js)
- Time to Interactive with RUM