Ways of Frontend performance auditing with Lighthouse
Yaprak Ayazoglu
Node Conference NL, Amsterdam
7th of June, 2019
https://slides.com/yaprakayazoglu/lighthouse-audits/
Freelance Frontend Engineer
Yaprak Ayazoglu
- Google Developer Expert in Web Technologies
- Living in NL
- Mentoring @LoncaWorks
I am...
I liked...
I like...
Agenda
-
Establishing a performance culture
-
Define performance requirements
-
Available tools
-
Lighthouse
-
Ways to add Lighthouse to your pipeline
Begin with establishing the performance culture
How?
Create awareness about performance benefits.
Real User Data
-
Share real user data
-
Pingdom
-
Page Speed Insights
-
-
Simulate limited resources
Manual Tests
Share results with your team members.
Automation
Share results with your team members.
Increase the reach
Make it company wide
Following steps
-
Define metrics & budgets
-
Improve the tooling
- Page with a session
- Multiple pages
Lighthouse
-
Lighthouse is an open-source, automated tool for improving the quality of web pages.
-
You can run it against any web page, public or requiring authentication.
Chrome Dev Tools
Chrome Dev Tools
Command Line
$ npm install -g lighthouse
$ lighthouse https://example.com/
# outputs an html file
$ lighthouse https://example.com/ --output=json --output-path report.json
# outputs a json file
"scripts": {
"lighthouse": "lighthouse --output-path=./report.html \
--chrome-flags='--headless' https://example.com"
}
npm package
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
function launchChromeAndRunLighthouse(url, opts, config = null) {
return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
opts.port = chrome.port;
return lighthouse(url, opts, config).then(results => {
return chrome.kill().then(() => results.lhr)
});
});
}
const opts = {
chromeFlags: ['--show-paint-rects']
};
// Usage:
launchChromeAndRunLighthouse('https://example.com', opts).then(results => {
// Use results!
});
Lighthouse Report
Multiple Urls
const ReportGeneratorV2 =
require('./node_modules/lighthouse/lighthouse-core/report/report-generator');
const pug = require('pug');
const urlsToTest = [
'https://example.com',
];
const reports = urlsToTest.map(async (url, index) => {
try {
const results = await runLighthouse(url, opts);
const reportInHtml = ReportGeneratorV2.generateReportHtml(results);
fs.writeFileSync(outputPath, reportInHtml);
return results;
} catch (e) {
// Exit
}
});
const rootReport = pug.renderFile('rootReportTemplate.pug', {
reports: reports,
});
fs.writeFileSync(outputPath, rootReport);
Performance budget
const categoriesByBudgets = require('./thresholds/performance-budgets');
isPassed(results) {
const categoryByResults = results.categories;
return Object.keys(categoriesByBudgets).every((category) => {
const threshold = categoriesByBudgets[category];
const categoryResult = categoryByResults[category];
return categoryResult.score >= threshold;
});
}
runLighthouseTests(urls, opts, customConfig).then(results => {
const fileName = 'report.html';
const outputPath = `./${REPORTS_DIR}/${fileName}`;
const reportInHtml = ReportGeneratorV2.generateReportHtml(results);
fs.outputFile(outputPath, reportInHtml);
const passed = isPassed(results);
if (!passed) {
process.exit(1);
}
})
.catch(error => {
throw new Error('Lighthouse error: ' + error);
process.exit(1);
});
Want more tests?
// custom-config.js
module.exports = {
extends: 'lighthouse:default',
// Add gatherer
passes: [{
passName: 'defaultPass',
gatherers: [
'custom-gatherer',
],
}],
// 3. Add custom audit
audits: [
'custom-audit',
],
// 4. Create a new 'Custom metrics' category
categories: {
'custom-metrics': {
title: 'Custom Tests',
description: 'Custom tests',
auditRefs: [
{id: 'custom-audit', weight: 1},
]}}};
Architecture
Gatherers
const { Gatherer } = require('lighthouse');
class CustomGatherer extends Gatherer {
beforePass(options) {/* ... *//}
pass(options) {/* ... *//}
afterPass(options) {
const driver = options.driver;
return driver
.evaluateAsync('window.myPerformanceMetrics')
}
}
module.exports = CustomGatherer;
Audits
const Audit = require('lighthouse').Audit;
class CustomAudit extends Audit {
static get meta() {
return {
id: 'custom-audit',
title: 'CustomAudit',
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
failureTitle: 'Custom test failed',
description: 'Custom tests in detail',
requiredArtifacts: ['CustomGatherer'],
};
}
static audit(artifacts) {
const measure = artifacts.CustomGatherer;
return {
rawValue: measure,
score: measure,
displayValue: `Custom test result is ${measure}`
};
}
}
module.exports = CustomAudit;
As Mocha Tests?
describe('Performance tests', function() {
let result = null;
before('Run Lighthouse base test', (done) => {
lighthouse(urlToTest, lighthouseOptions, customAuditConfig)
.then((res) => {
result = subsetOfMetrics.prepareData(res);
done();
});
});
it('should have time to interactive < MAX_TTI', (done) => {
let tti = result.preparedResults.find(r => {
return r.name === 'tti';
});
assert.isBelow(tti.value, MAX_TTI);
done();
});
Custom Config
{
"passes": [{
"recordNetwork": true,
"recordTrace": true,
"gatherers": [
"url",
"service-worker",
"offline"]
}],
"audits": [
"first-meaningful-paint",
"time-to-interactive",
"service-worker"
],
"aggregations": [{
/* ... */
}]
}]
}
Integration to CI
- Jenkins (Github, Bitbucket, Gitlab, etc.)
- Travis + Github
- Gitlab + Gitlab CI
- Bitbucket + Bitbucket Pipelines
Github + Travis
- Jenkins (Github, Bitbucket, Gitlab, etc.)
- Travis + Github
- Gitlab + Gitlab CI
- Bitbucket + Bitbucket Pipelines
GitHub & Travis
Bitbucket & Jenkins
Wrap up
-
Start with small steps and aim for the long run
-
Lighthouse is a powerful building block
References
Thank you...
Yaprak Ayazoglu
Node Conference NL, Amsterdam
7th of June, 2019
https://slides.com/yaprakayazoglu/lighthouse-audits/
lighthouse-audits
By Yaprak Ayazoglu
lighthouse-audits
Lighthouse is an automated tool for improving the quality of web pages. It provides audits for performance, accessibility, progressive webapps, SEO, etc. and provide guidance to how to improve it. This Docker container uses Lighthouse to audit your frontend performance. There are several ways to incorporate Lighthouse. Among those ways, we picked the solution to allow the teams create their own custom tests performance tests.
- 1,653