ResourceTiming compression and decompression
npm install resourcetiming-compressionv1.4.0
Licensed under the MIT license
resourcetiming-compression.js compresses data from ResourceTiming. A
companion script, resourcetiming-decompression.js, converts the compressed data back to the original form.
ResourceTiming is a W3C WebPerf API that exposes all of the page's resources' network timing information (and additional details) to JavaScript, and is available in most modern browsers.
The interface performance.getEntriesByType('resource') returns a list of resources with information about each resource's URL, inititor, timestamps, size information and more.
Collecting this information is easy, but beaconing all of the data back to a data warehouse can be a challenge because of the amount of data available for each resource.
On a typical page, which might have over 100 resources, the browser could easily generate 50 KB+ of ResourceTiming data per page-load.
resourcetiming-compression.js applies several data-compression techniques to reduce the size of your serialized
ResourceTiming data to about 15% of it's original size in many cases. See
this nicj.net blog post for a description of these techniques.
resourcetiming-decompression.js is a companion script that will take the compressed ResourceTiming data and
rebuilds the ResourceTiming structures (eg. performance.getEntriesByType('resource')) for analysis.
NOTE: resourcetiming-compression.js is the same code that drives the restiming.js plugin for
Boomerang, but also includes the resourcetiming-decompression.js component.
Releases are available for download from GitHub.
Development: resourcetiming-compression.js - 57kb
Production: resourcetiming-compression.min.js
- 4.7kb (minified / gzipped)
Development: resourcetiming-decompression.js - 40kb
Production: resourcetiming-decompression.min.js
- 3.3kb (minified / gzipped)
resourcetiming-compression.js is also available as the npm resourcetiming-compression module. You can install
using Node Package Manager (npm):
npm install resourcetiming-compression
resourcetiming-compression.js is also available via bower. You can install using:
bower install resourcetiming-compression
Please see the W3C ResourceTiming API Reference for details on how to use the
ResourceTiming API.
To include resourcetiming-compression.js, simply include it via a script tag:
``html`
Once included in the page, a top-level ResourceTimingCompression object is available on window. If AMD
or CommonJS environments are detected, it will simply expose itself via those methods.
From the NPM module:
`js`
var ResourceTimingCompression = require("resourcetiming-compression").ResourceTimingCompression;
To get all of the compressed resources, you can simply call:
`js`
var {restiming, servertiming} = ResourceTimingCompression.getResourceTiming();
To include resourcetiming-decompression.js, simply include it via a script tag:
`html`
Once included in the page, a top-level ResourceTimingDecompression object is available on window. If AMD
or CommonJS environments are detected, it will simply expose itself via those methods.
From the NPM module:
`js`
var ResourceTimingDecompression = require("resourcetiming-compression").ResourceTimingDecompression;
To decompress your resources, you can simply call:
`js`
var original = ResourceTimingDecompression.decompressResources(restiming, servertiming);
Please see this blog post for a more detailed description of the compression
format.
Each ResourceTiming entry (e.g. URL) is first combined into an optimized Trie:
`json`
{
"http://": {
"foo.com/": {
"|": "0,a",
"js/foo.js": "370,1z,1c|390,1,2",
"css/foo.css": "48c,5k,14*0a"
}
}
}
The above Trie contains data for the following URLs:
* http://foo.com/ (the | leaf node)http://foo.com/js/foo.js
* (contains two entries as designated by | in the middle of the value)http://foo.com/css/foo.css
*
Some notes:
* A leaf node _key_ of | means an entry for the Trie up to that point.|
This may happen if a URL is a common prefix of other entries.
The URL would not contain the .|
* A _value_ containing means the URL has multiple entries (e.g. the same URL has multiple hits)[n]
A _value_ containing means "special data" is encoded for that URL, such as dimensions, sizes, Server Timing, etc.
See below for more details.
The very first character for every ResourceTiming entry is its initiatorType.
For example:
`json`
{
"http://foo.com/js/foo.js": "370,1z,1c"
}
3 is the initiator of foo.js, which maps to script.
The mapping is defined as:
`js`
INITIATOR_TYPES = {
"other": 0,
"img": 1,
"link": 2,
"script": 3,
"css": 4,
"xmlhttprequest": 5,
"html": 6,
"image": 7,
"beacon": 8,
"fetch": 9,
"iframe": "a",
"subdocument": "a",
"body": "b",
"input": "c",
"frame": "a",
"object": "d",
"video": "e",
"audio": "f",
"source": "g",
"track": "h",
"embed": "i",
"eventsource": "j",
"navigation": 6,
"early-hints": "k",
"ping": "l",
"font": "m"
}
After the initiatorType, each entry contains the resource's timestamps in the following order:
`text`
[initiatorType][startTime],[responseEnd],[responseStart],
[requestStart],[connectEnd],[secureConnectionStart],[connectStart],
[domainLookupEnd],[domainLookupStart],[redirectEnd],[redirectStart]
Each entry is Base36 encoded.
startTime is the Base36 value of the startTime timestamp.
All of the other timestamps are the Base36 value of their offset from startTime.
All trailing ,0s are removed and can be assumed to be the same as 0 or missing when decoding.
For example:
`json`
{
"http://foo.com/js/foo.js": "370,1z,1c"
}
Results in:
`json`
{
"name": "http://blah.com/js/foo.js",
"initiatorType": "script",
"startTime": 252,
"responseEnd": 323,
"responseStart": 300
}
With every other timestamp being 0.
Additional information about each resource is encoded with special "special data" delimiters (*[type]).
The special data types are:
* 0: Dimensions1
* : Sizes2
* :