I wanted to see if it would be possible to track web page performance across different JS frameworks. I knew that WPT already supported Wappalyzer, but was super glad to stumble on @paulcalvano’s excellent analysis of CPU times grouped by framework by extracting it’s data.
Extending the query that he used previously to now find the median FP, FCP, FMP and TTI for desktop:
SELECT jsframework,
count(*) freq,
ROUND(APPROX_QUANTILES(firstPaint, 100)[SAFE_ORDINAL(50)]) firstPaint,
APPROX_QUANTILES(firstContentfulPaint, 100)[SAFE_ORDINAL(50)] firstContentfulPaint,
APPROX_QUANTILES(firstMeaningfulPaint, 100)[SAFE_ORDINAL(50)] firstMeaningfulPaint,
APPROX_QUANTILES(timeToInteractive, 100)[SAFE_ORDINAL(50)] timeToInteractive
FROM (
SELECT REGEXP_REPLACE(
JSON_EXTRACT(payload,"$._detected.JavaScript Frameworks"),
r"([0-9.\"\s]+)",
"") jsframework,
CAST(JSON_EXTRACT(payload, "$['_firstPaint']") as FLOAT64) firstPaint,
CAST(JSON_EXTRACT(payload, "$['_firstContentfulPaint']") as INT64) firstContentfulPaint,
CAST(JSON_EXTRACT(payload, "$['_firstMeaningfulPaint']") as INT64) firstMeaningfulPaint,
CAST(JSON_EXTRACT(payload, "$['_TimeToInteractive']") as INT64) timeToInteractive
FROM `httparchive.pages.2018_09_01_desktop`
)
GROUP BY jsframework
ORDER BY freq DESC
Now if we filter for popular frameworks and query against mobile:
SELECT jsFramework,
count(*) freq,
ROUND(APPROX_QUANTILES(firstPaint, 100)[SAFE_ORDINAL(50)]) firstPaint,
APPROX_QUANTILES(firstContentfulPaint, 100)[SAFE_ORDINAL(50)] firstContentfulPaint,
APPROX_QUANTILES(firstMeaningfulPaint, 100)[SAFE_ORDINAL(50)] firstMeaningfulPaint,
APPROX_QUANTILES(timeToInteractive, 100)[SAFE_ORDINAL(50)] timeToInteractive
FROM (
SELECT REGEXP_REPLACE(
JSON_EXTRACT(payload,"$._detected.JavaScript Frameworks"),
r"([0-9.\"\s]+)",
"") jsFramework,
CAST(JSON_EXTRACT(payload, "$['_firstPaint']") as FLOAT64) firstPaint,
CAST(JSON_EXTRACT(payload, "$['_firstContentfulPaint']") as INT64) firstContentfulPaint,
CAST(JSON_EXTRACT(payload, "$['_firstMeaningfulPaint']") as INT64) firstMeaningfulPaint,
CAST(JSON_EXTRACT(payload, "$['_TimeToInteractive']") as INT64) timeToInteractive
FROM `httparchive.pages.2018_09_01_mobile`
)
WHERE
jsFramework='React' OR
jsFramework='AngularJS' OR
jsFramework='Angular' OR
jsFramework='Angular,Zonejs' OR
jsFramework='Vuejs' OR
jsFramework='Polymer'
GROUP BY jsFramework
ORDER BY freq DESC
Some interesting things here :
• Angular,Zonejs
has significantly more entries than Angular
so I assume Wappalyzer mostly uses this to categorize Angular 2+ applications?
• Polymer results are a bit shocking. ~27s TTI? I would have assumed significantly better results here.
We can extend the SELECT clause to 50/75/95 percentiles:
SELECT jsFramework,
count(*) freq,
ROUND(APPROX_QUANTILES(firstPaint, 100)[SAFE_ORDINAL(50)]) firstPaint50,
ROUND(APPROX_QUANTILES(firstPaint, 100)[SAFE_ORDINAL(75)]) firstPaint75,
ROUND(APPROX_QUANTILES(firstPaint, 100)[SAFE_ORDINAL(95)]) firstPaint95,
APPROX_QUANTILES(firstContentfulPaint, 100)[SAFE_ORDINAL(50)] firstContentfulPaint50,
APPROX_QUANTILES(firstContentfulPaint, 100)[SAFE_ORDINAL(75)] firstContentfulPaint75,
APPROX_QUANTILES(firstContentfulPaint, 100)[SAFE_ORDINAL(95)] firstContentfulPaint95,
APPROX_QUANTILES(firstMeaningfulPaint, 100)[SAFE_ORDINAL(50)] firstMeaningfulPaint50,
APPROX_QUANTILES(firstMeaningfulPaint, 100)[SAFE_ORDINAL(75)] firstMeaningfulPaint75,
APPROX_QUANTILES(firstMeaningfulPaint, 100)[SAFE_ORDINAL(95)] firstMeaningfulPaint95,
APPROX_QUANTILES(timeToInteractive, 100)[SAFE_ORDINAL(50)] timeToInteractive50,
APPROX_QUANTILES(timeToInteractive, 100)[SAFE_ORDINAL(75)] timeToInteractive75,
APPROX_QUANTILES(timeToInteractive, 100)[SAFE_ORDINAL(95)] timeToInteractive95
....