Web Performance Calendar

The speed geek's favorite time of year
2022 Edition
ABOUT THE AUTHOR

Stoyan (@stoyanstefanov) is an engineer on the WebPageTest.org team, formerly at Facebooks and Yahoo!, writer ("JavaScript Patterns", "React: Up and Running"), speaker (JSConf, Velocity, Perf.now()), toolmaker (Smush.it, YSlow 2.0) and a guitar hero wannabe.


Seeing is believing. It can also help unearth helpful strategies. And one can never have too many ways of visualizing data. What one tool misses, another one finds. And here’s yet another tool for your toolbox.

Lighthouse treemap

Lighthouse comes with a treemap viewer tool (example) that Lighthouse itself uses to visualize JavaScript files and their sizes. But:

  • why stop there and not show CSS, images, fonts…?
  • and you don’t need to run LH in order to reap the visual benefits

screenshot of Lighthouse's treemap tool

You can run the treemap tool in two ways: point it to a local JSON file or pass one in the URL.

Minimum viable JSON

The tool accepts a complete LH report but for our purposes that’s a little:

  • too much work and requires you need to run LH prior to using the tool
  • too much data and this is unacceptable to the performance-minded audience of this Calendar

After some trial and error and peeking at the code I was able to deduce a minimal viable piece of JSON structure that will allow us to adopt the tool for our benefits.

Here goes:

{
  "requestedUrl": "https://www.example.org",
  "audits": {
   "script-treemap-data": {
      "details": {
        "type": "treemap-data",
        "nodes": [
          {
            "name": "https://www.example.org/",
            "resourceBytes": 100000
          },
          {
            "name": "https://www.example.org/one.css",
            "resourceBytes": 200000
          }
        ]
      }
    }
  },
  "configSettings": {
    "locale": "en-US"
  }
}

The nodes array is where you pass the items to visualize defined by name and resourceBytes.

Hitting the URL of the tool https://googlechrome.github.io/lighthouse/treemap/ without a query string gives you UI where you can pick or paste the above JSON:

screenshot of treemap welcome screen

And here is how the above JSON looks like, visualized:

screenshot of minum viable JSON visualization

Note: You can also pass unusedBytes if your data happen to have and can benefit from such a nugget.

As you can see from the simple JSON example, you’re not limited to visualizing only scripts. The sky is the limit. Any resource size can be inspected. Actually any data that has a size will do.

Passing the data in the URL

If you’re building a tool that can use the treeview programmatically, it’s borderline criminal to just generate a JSON and expect your CEO to open treeview and pick a file. URL param to the rescue.

You can link to a treeview with a URL that looks like:

https://github.com/GoogleChrome/lighthouse/tree/main/treemap?gzip=1#Base64EncodedAndGzippedJSON

The gzip-ing is optional but need I remind you of the performance-minded audience of this Calendar? So no, gzip is most certainly not optional.

Oh, and one important note: you need to wrap the Minimum-Viable JSON in a lhr key, otherwise you’ll be like me and lose precious time losing your mind, trying to figure out what on earth you’re doing wrong with your base64-ing and/or gzip-ing.

So the MV-JSON if used with the URL becomes:

{
  "lhr": {
    "requestedUrl": "https://www.example.org",
    "audits": {
      "script-treemap-data": {
        "details": {
          "type": "treemap-data",
          "nodes": [
            {
              "name": "https://www.example.org/",
              "resourceBytes": 100000
            },
            {
              "name": "https://www.example.org/one.css",
              "resourceBytes": 200000
            }
          ]
        }
      }
    },
    "configSettings": {
      "locale": "en-US"
    }
  }
}

Encoding in PHP

Now this JSON needs to be doubly-encoded: base64 and gzip. PHP makes this easy as a shortbread cookie. Here’s a complete example:

$treemap = [
    'lhr' => [
        'requestedUrl' => $url,
        'audits' => [
            'script-treemap-data' => [
                'details' => [
                  'type' => "treemap-data",
                  'nodes' => [/* insert nodes here */]
                ]
            ],
        ],
        'configSettings' => [
            'locale' => "en-US"
        ]
    ]
];

// boy is this a lot of encode-ing!
$treemap = base64_encode(gzencode(json_encode($treemap)));

$url = 'https://googlechrome.github.io/lighthouse/treemap/?gzip=1#' . $treemap;

Encoding in JavaScript

  • JSON: JSON.stringify() (I heard in a presentation Douglas Crockford expressing regret about the cheeky function name, instead of “encode”)
  • Base64: atob()
  • Gzip: CompressionStream, if supported or a library, e.g. pako

And just like that…

A new tool for you to integrate and visualize your resources!

Note: talk to your friendly security professional to see if passing sensitive information in the URL is right for you. The tool itself is all client side, but you are passing data in a URL #hash.

So here we are, it was a little annoying that I didn’t see any documentation on the gzip/mvjson/base64 so a bit of reverse engineering was required. But that happens with tools, even open source ones. The outcomes are usually two:

  • a friendly user writes a blog post for others to learn
  • a friendly toolmaker says: duh! and points to the docs

What do you want to share with the fellow perfplanet calendar readers? There’s still time!