page-load-type
Version:
Determines page load type for websites using Signed Exchanges
166 lines (114 loc) • 6.42 kB
Markdown
# Page load type
A JavaScript library for page load type detection supporting Signed Exchanges (SXG),
prefetching, Cloudflare cache, Early Hints, and browser cache.
## The problem it solves
When the browser loads a page, you may want to:
- Report failures in loading of Signed Exchanges subresources
- Compare performance metrics (such as LCP) of different load types
- Track the load type in web analytics
- Adjust page behavior based on type (e.g., play videos for fully prefetched websites
or display fallback images otherwise)
You will find more information in my blog post on
[how to measure and monitor SXG](https://www.pawelpokrywka.com/p/measuring-signed-exchanges-impact).
## Detected page load types
The library recognizes the following page load types:
### SXG
The page was loaded using SXG:
- `sxg_complete_prefetch` - Page was prefetched along with subresources
- `sxg_document_prefetch` - Only the HTML document was prefetched; subresources had to be loaded normally
- `sxg_document_on_demand` - Same as above, but instead of prefetching, SXG was loaded on demand
The browser tried to retrieve SXG but failed because the document was missing from the Google cache.
A fallback mechanism was activated, resulting in the browser being client-side redirected to the website:
- `sxg_fallback_on_demand_edge` - The page was served from Cloudflare cache
- `sxg_fallback_on_demand_hints` - The page was served from the origin, but Early Hints were used
- `sxg_fallback_on_demand_origin` - The page was served from the origin without Early Hints
### Prefetched/cached HTML
- `document_prefetch` - The HTML document was prefetched on the referring site
- `browser_cache` - The page was visited before and the browser used the cached version
(subresources may or may not be cached)
### Normal loading
The page was loaded normally. It's still possible to determine if:
- `document_on_demand_edge` - The page was served from Cloudflare cache
- `document_on_demand_hints` - The page was served from the origin, but Early Hints were used
- `document_on_demand_origin` - The page was served from the origin without Early Hints
## Page load type performance rating
Page load types tiers, rated from the best performance to the worst according to my measurements:
1. `sxg_complete_prefetch` / `browser_cache`
2. `sxg_fallback_on_demand_edge` / `sxg_fallback_on_demand_hints` / `document_on_demand_edge` / `document_on_demand_hints`
3. `sxg_document_prefetch` / `sxg_fallback_on_demand_origin` / `document_prefetch` / `document_on_demand_origin`
4. `sxg_document_on_demand`
Note that the 1st tier is much faster, while the 2nd, 3rd, and 4th tiers are quite similar to each other
in terms of speed. For a full explanation and details, see my blog post about
[measuring SXG](https://www.pawelpokrywka.com/p/measuring-signed-exchanges-impact).
## Installation & setup
1. Set Cloudflare to proxy your site and enable the **Automatic Signed Exchanges** feature
2. Follow my [SXG tutorial](https://www.pawelpokrywka.com/p/how-i-took-lcp-down-under-350ms) on how to
adjust your app code and web server configuration. Read at least the first 2 parts for basic functionality,
but to correctly handle SXG quirks, I recommend reading parts 3-6 as well
3. Deploy [SXG Status](https://github.com/pepawel/sxg-status) worker to your Cloudflare account and mount it under
`/sxg/resolve-status.js`
4. Near the top of your `<head>` section, before the first `<script>` element, add:
```html
<script data-issxg-var>window.isSXG = false</script>
<template data-sxg-only>
<link as='script' href='/sxg/resolve-status.js' rel='preload'>
</template>
```
If you use `npm` to manage dependencies in your app, add the `page-load-type` package:
```shell
npm install page-load-type
```
Adjust accordingly if you use `yarn` or another dependency manager.
## Usage
### getPageLoadType()
`getPageLoadType()` returns a Promise with the page load type. You can use `await` to retrieve it:
```js
import getPageLoadType from "page-load-type";
const loadType = await getPageLoadType();
```
Optionally, you can provide an object with configuration. By default, it looks like this:
```js
{
sxgStatusConfig = {
scriptPath: '/sxg/resolve-status.js',
eventName: 'SxgStatusResolved',
eventProperty: 'subresources',
}
}
```
The `sxgStatusConfig` key allows you to use a customized [SXG Status](https://github.com/pepawel/sxg-status) worker,
if needed for some reason.
### resolveSxgStatus()
If the only thing that interests you is SXG subresources status, then you can use the `resolveSxgStatus()` function.
It returns a Promise which *resolves* if SXG subresources were correctly loaded and *rejects* otherwise.
```js
import { resolveSxgStatus } from "page-load-type";
resolveSxgStatus()
.then(() => console.log('subresources loaded with SXG'))
.catch(() => console.log('subresources failed to load with SXG'));
```
This function also accepts a configuration object with the `sxgStatusConfig` key.
For example usage, see the `example.html` file.
This file is meant to be placed in an SXG enabled website to function properly.
## How it works
The code combines information from various sources:
- SXG document load status provided by Cloudflare ASX in `window.isSXG`
- SXG subresources load status provided by [SXG Status](https://github.com/pepawel/sxg-status) worker
- Browser cache usage retrieved using the `PerformanceNavigationTiming` interface
- Early Hints usage retrieved using the `PerformanceResourceTiming` interface
- Cloudflare cache usage provided by Cloudflare and retrieved using the `PerformanceServerTiming` interface
- Google SXG cache fallback detection by parsing HTTP referrer
For more details, please refer to my blog post about
[measuring SXG](https://www.pawelpokrywka.com/p/measuring-signed-exchanges-impact).
You can also check the `getPageLoadType()` implementation - the function body takes about 40 lines of code.
## Testing
Run tests with:
```shell
npm run test
```
## Author
My name is Paweł Pokrywka and I'm the author of the `Page Load Type` library.
If you want to contact me or get to know me better, check out [my blog](https://www.pawelpokrywka.com).
Thank you for your interest in this project :)
## License
The software is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).