Research
Security News
Malicious PyPI Package ‘pycord-self’ Targets Discord Developers with Token Theft and Backdoor Exploit
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
perfume.js
Advanced tools
JavaScript library that measures First (Contentful) Paint (FP/FCP) and First Input Delay (FID). Annotates components’ performance for Vanilla and Angular applications, into the DevTools timeline. Reports all the results to Google Analytics or your favorit
A flexible library for measuring First Contentful Paint (FP/FCP), First Input Delay (FID) and components lifecycle performance. Report real user measurements to Google Analytics or your ideal tracking tool.
English | 简体中文
Perfume leverage the latest W3C Performance Drafts (like PerformanceObserver), for measuring performance that matters! ⚡️
npm (https://www.npmjs.com/package/perfume.js):
npm install perfume.js --save-dev
You can import the generated bundle to use the whole library generated by this starter:
import Perfume from 'perfume.js';
Universal Module Definition:
import Perfume from 'node_modules/perfume.js/dist/perfume.umd.min.js';
FP is the exact time the browser renders anything as visually different from what was on the screen before navigation, e.g. a background change after a long blank white screen time.
const perfume = new Perfume({
firstPaint: true
});
// Perfume.js: First Paint 1482.00 ms
FCP is the exact time the browser renders the first bit of content from the DOM, which can be anything from an important image, text, or even the small SVG at the bottom of the page.
const perfume = new Perfume({
firstContentfulPaint: true
});
// Perfume.js: First Contentful Paint 2029.00 ms
FID measures the time from when a user first interacts with your site (i.e. when they click a link, tap on a button) to the time 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
Performance.mark (User Timing API) is used to create an application-defined peformance entry in the browser's performance entry buffer.
perfume.start('fibonacci');
fibonacci(400);
perfume.end('fibonacci');
// Perfume.js: fibonacci 0.14 ms
This metric mark the point, immediately after creating a new component, when the browser renders pixels to the screen.
perfume.start('togglePopover');
$(element).popover('toggle');
perfume.endPaint('togglePopover');
// Perfume.js: togglePopover 10.54 ms
Save the duration and print it out exactly the way you want it.
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.14 ms
Wth the Angular framework, we can start configuring Perfume to collect the initial performance metrics (eg. FCP, FID). Make sure to import the PefumeModule
at first inside the NgModule
to let the PerformanceObserver work correctly.
In a large application use the @PerfumeAfterViewInit()
decorator to monitor the rendering performance of the most complex components. Avoid using it inside a NgFor, instead focus on components that include a collection of smaller components.
The NgPerfume
service exposes all the methods and property of the perfume
instance, you can annotate component lifecycles combined with APIs calls to measure how long it takes to paint the component.
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 measure component time to paint
this.perfume.start('AppComponentAfterPaint');
}
ngAfterViewInit() {
this.loadAwesomeData();
}
loadAwesomeData = async () => {
await AppApi.loadAmazingData();
this.data = AppApi.loadAwesomeData();
// End measure component time to paint
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 {}
In combination with the React framework, we can start configuring Perfume to collect the initial performance metrics (eg. FCP, FID).
Use perfume.start()
and perfume.endPaint()
into a component lifecycle mixed with APIs calls to measure how long it takes to paint 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 measure component time to paint
perfume.start('AppAfterPaint');
}
loadData = async () => {
await AppApi.loadAmazingData();
await AppApi.loadAwesomeData();
// End measure component time to paint
perfume.endPaint('AppAfterPaint');
}
render() {
const data = this.loadData();
return (
<div>
<h2>Awesome App</h2>
<div>{data}</div>
</div>
);
}
}
To enable Perfume to send your measures to Google Analytics User timing, set the option enable:true
and a custom user timing variable timingVar:"name"
.
const perfume = new Perfume({
googleAnalytics: {
enable: true,
timingVar: 'userId'
}
});
Configurable analytics callback to use Perfume.js with any platform.
const perfume = new Perfume({
analyticsTracker: (metricName, duration, browser) => {
myAnalyticsTool.track(metricName, duration, browser.name, browser.os);
})
});
Default options provided to Perfume.js 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,
};
Perfume.js expose some methods and properties which may be useful to people 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 Custom User timing measure to Google Analytics
perfume.sendTiming(metricName, durationFCP);
npm start
: Run npm 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 codeMade with ☕️ by @zizzamia and I want to thank some friends and projects for the work they did:
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 |
FAQs
Web performance library for measuring all User-centric performance metrics, including the latest Web Vitals.
The npm package perfume.js receives a total of 11,396 weekly downloads. As such, perfume.js popularity was classified as popular.
We found that perfume.js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.
Security News
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.