Skip to content

Commit

Permalink
🎯
Browse files Browse the repository at this point in the history
  • Loading branch information
paulirish committed Aug 24, 2016
0 parents commit f71001c
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
@@ -0,0 +1,9 @@
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
28 changes: 28 additions & 0 deletions bin/cli.js
@@ -0,0 +1,28 @@
#!/usr/bin/env node

const PWMetrics = require('..');

const argv = process.argv.slice(2);
const url = argv.filter(f => !f.startsWith('-')).shift();

const flags = {};
argv
.filter(f => f.startsWith('-'))
.forEach(f => {
var keyValue = f.split('=');
const flagKey = keyValue[0].replace(/-*/, '');
flags[flagKey] = keyValue[1] || true;
});

const p = new PWMetrics(url, flags);
Promise.resolve(p)
.then(data => {
data && process.stdout.write(data);
process.stdout.write('\n');
process.exit(0);
})
.catch(err => {
console.error(err);
return process.exit(1);
});

136 changes: 136 additions & 0 deletions index.js
@@ -0,0 +1,136 @@

const lighthouse = require('lighthouse');
const Chart = require('cli-chart');
const util = require('util');
const fs = require('fs');
const path = require('path');

const perfConfig = require('lighthouse/lighthouse-core/config/perf.example-custom.json')

class PWMetrics {

constructor(url, opts) {
this.url = url;
this.opts = opts;

if (this.opts.data) {
const filename = this.opts.data;
const savedResults = JSON.parse(fs.readFileSync(path.join(__dirname, filename), 'utf8'));
return this.displayResults(savedResults.audits);
}

if (!this.url) {
return new Error('Please provide a URL');
}

return this.recordLighthouseTrace();
}

recordLighthouseTrace() {
const lhOpts = {mobile: true, loadPage: true};
return lighthouse(this.url, lhOpts, perfConfig)
.then(res => this.prepareData(res))

This comment has been minimized.

Copy link
@hemanth

hemanth Aug 24, 2016

Peeps to check if he can steal something from here for is-pwa 🤔

This comment has been minimized.

Copy link
@paulirish

paulirish Aug 29, 2016

Author Owner

TBH i think is-pwa could be this simple:

module.exports = function(url){

    const getTotalScore = aggregation => {
      const totalScore = aggregation.score.reduce((total, s) => {
        return total + s.overall;
      }, 0) / aggregation.score.length;

      return Math.round(totalScore * 100);
    };

    return lighthouse(url,  {mobile: true, loadPage: true})
      .then(data => { 
         const agg = data.aggregations.find(a => a.name === "Progressive Web App");
         const totalScore = getTotalScore(agg);
         return totalScore > 85; // more or less.  this is debatable. :)
     });
};

This comment has been minimized.

Copy link
@hemanth

hemanth Aug 30, 2016

tJeTfLOfl98Mo

This comment has been minimized.

Copy link
@hemanth

hemanth Aug 30, 2016

Would it be worth making a module for the below?

chrome  --remote-debugging-port=9222 --no-first-run --user-data-dir=$(mktemp -d -t pwm.XXXXX)

This comment has been minimized.

Copy link
@paulirish

paulirish Aug 30, 2016

Author Owner

maybe...

can also do

npm explore lighthouse -- npm run chrome

This comment has been minimized.

Copy link
@paulirish

paulirish Aug 30, 2016

Author Owner

but i'm open to suggestions.

This comment has been minimized.

Copy link
@hemanth

hemanth Aug 30, 2016

lighthouse-core/scripts/launch-chrome.sh makes sense. Probably put it in the bg for is-pwa.

This comment has been minimized.

Copy link
@hemanth

hemanth Aug 30, 2016

So far...

.then(data => this.displayOutput(data));
}


prepareData(res) {
res = res.audits;

const resFMP = res['first-meaningful-paint'];
const resFMPext = resFMP.extendedInfo;
const resSI = res['speed-index-metric'];
const resSIext = resSI.extendedInfo;
const resTTI = res['time-to-interactive'];
const resTTIext = resTTI.extendedInfo;

const colorP0 = 'yellow';
const colorP2 = 'green';
const colorVisual = 'blue';

const timestamps = [
resFMPext && resFMPext.value.timings.navStart
];
const timings = [{
name: 'First Contentful Paint',
value: resFMPext && resFMPext.value.timings.fCP,
color: colorP2
}, {
name: 'First Meaningful Paint',
value: resFMP.rawValue,
color: colorP0
}, {
name: 'Median Visual Completion',
value: resSI.rawValue,
color: colorVisual
}, {
name: 'First Visual Change',
value: resSIext && resSIext.value.first,
color: colorVisual
}, {
name: 'Visually Complete 100%',
value: resSIext && resSIext.value.complete,
color: colorVisual
}, {
name: 'Time to Interactive',
value: resTTI.rawValue,
color: colorP0
}, {
name: 'Visually Complete 85%',
value: resTTIext && resTTIext.value.timings.visuallyReady,
color: colorVisual
}, {
name: 'Navigation Start',
value: 0 // naturally.
}
];
return {
timings,
timestamps
};
}

spitJSON(data) {
var resultsStr = JSON.stringify(data, null, 2);
return resultsStr;
}

displayOutput(data) {
if (this.opts.json) {
return this.spitJSON(data);
}

data = data.timings.sort((a,b) => b.value - a.value);
const chart_width = 80;
const fullWidthInMs = 7000;
const maxLabelWidth = Math.max.apply(Math, data.map(r => r.name.length));

data.forEach(r => {
if (r.value === undefined) {
console.error(`Sorry, ${r.name} metric is unavailable`);
}
})

const chartOps = {
width: process.stdout.columns * 0.8,
xlabel: 'Time (ms) since navigation start',
xmax: fullWidthInMs,
lmargin: maxLabelWidth + 1,
height: data.length * 2,
step: 2,
direction: 'x',
};

var chart = new Chart(chartOps);
data.forEach(result => {
chart.addBar({
size: result.value,
label: result.name,
color: result.color
})
});
chart.draw();
}
}

module.exports = PWMetrics;
32 changes: 32 additions & 0 deletions package.json
@@ -0,0 +1,32 @@
{
"name": "pwmetrics",
"version": "1.0.0",
"description": "Gather progressive web metrics for a url. CLI & lib",
"main": "index.js",
"bin": {
"pwmetrics": "bin/cli.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Paul Irish",
"license": "Apache-2.0",
"dependencies": {
"cli-chart": "^0.3.1",
"lighthouse": "github:googlechrome/lighthouse"
},
"devDependencies": {},
"repository": {
"type": "git",
"url": "git+https://github.com/paulirish/pwmetrics.git"
},
"keywords": [
"metrics",
"performance",
"lighthouse"
],
"bugs": {
"url": "https://github.com/paulirish/pwmetrics/issues"
},
"homepage": "https://github.com/paulirish/pwmetrics#readme"
}

0 comments on commit f71001c

Please sign in to comment.