feat: defer mode
Motivation
Webpack JS assets are added to the page using defer, making them less "critical" for the browser.
As Docusaurus v2 can almost work without any JS, we can see React hydration as non-mandatory progressive enhancement
For now it's just a POC
[V2]
| Name | Link |
|---|---|
| Latest commit | 0423acf493662f31d5b95ac7214279e55dd375ad |
| Latest deploy log | https://app.netlify.com/sites/docusaurus-2/deploys/624fda5d3d15550008e0395a |
| Deploy Preview | https://deploy-preview-3237--docusaurus-2.netlify.app |
| Preview on mobile | Toggle QR Code...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify site settings.
I am highly interested in this, I was thinking of implementing the exact same thing. Is there any drawback you can think of?
Also, it might be interesting to let the user defer the main stylesheet. One could optimise their website by inlining the critical CSS and relying on the full stylesheet later in the rendering process in order to optimise the FCP.
Hi,
Unfortunately I'm not a perf expert. Using http://web.dev/measure I get highly variable results but I don't see any significant improvement (at least in score) by deferring the scripts, so not sure how to reliably measure that it improves anything.
If that interests you, here are 3 Docusaurus deployments I used for my tests:
No JS at all: https://5f2d50ba7316ec0008f830a9--docusaurus-2.netlify.app/build/
JS low priority (end of body, defer) https://5f2d4cfb5ac4740007ff0684--docusaurus-2.netlify.app/build/
JS high priority (preload + no defer) https://5f2d193a5609540008fb969c--docusaurus-2.netlify.app/build/
If this is useful, I'd find it cool to be able to specific which one of the 3 modes you want :)
The "no js" is likely to have some issues currently but this seems fixable (can't expand sidebar categories etc...)
Hi Sébastien,
Thanks for taking the time to do that. Here are Lighthouse performance results for each page:
-
No JS at all:

-
JS low priority (end of body, defer)

-
JS high priority (preload + no defer)

My take on the results:
-
This is obviously the best, although FCP is higher than in 2. this is still better because the total blocking time is 0ms. That being said, this is probably not a practical solution for many Docusaurus V2 users, I am sure many people rely on client side rendering. This also breaks Algolia's search.
-
Extremely good FCP, more than 2x faster than 3. while still keeping client side JS, this is the perfect solution IMO.
-
Current situation, no matter was you do (I tested with: HTTP2, brotli compression, CDN and a blank page!), FCP will be mediocre at best, the blocking JS is the limiting factor.
-
=> some users might not use the classic theme and won't necessarily have a search. If they really want the classic theme they can eventually not use the Algolia search at all, so I wouldn't see this widely used but I think it makes sense.
-
3). I also think 2 is theoretically better, but in my experience running tests using https://web.dev/measure/ (to not have my own computer as a bias), I get very random results, some runs get 2 better, some others get 3 better...
Maybe you could share me how you get these scores? are they consistent across multiple runs? My scores are very random , all 3 gives between 60 and 95 quite randomly so it's hard to do anything with that...
Note, React is working on progressive hydration, afaik this is not ready but this would be an interesting feature to get 3 perform better.
Yes you are right, the results are changing quite a lot between runs. I will script this and run 100 tests per version, I will keep you updated once I have the results.
I still think 2. would be a great option: no downside and bench results seem to be better, let's prove it with reliable numbers :slightly_smiling_face:.
Thanks :) that's something I wanted to do but didn't have time.
For 100 runs (using Lighthouse programmatically), I get:
No JS: 99.55
Defer: 96.69
Preload: 92.63
If you want to reproduce the results yourself, you can check the code on this repo.
EDIT: I re-ran the script with 100 benchmarks (50 before) per scenario and updated the results accordingly.
After 1000 runs:
No JS: 99.336
Defer: 95.886
Preload: 90.453
⚡️ Lighthouse report for the changes in this PR:
| Category | Score |
|---|---|
| 🟠 Performance | 86 |
| 🟢 Accessibility | 100 |
| 🟢 Best practices | 100 |
| 🟢 SEO | 100 |
| 🟠 PWA | 80 |
Lighthouse ran on https://deploy-preview-3237--docusaurus-2.netlify.app/
Size Change: -256 B (0%)
Total Size: 805 kB
| Filename | Size | Change |
|---|---|---|
website/build/index.html |
38.3 kB | -256 B (-1%) |
ℹ️ View Unchanged
| Filename | Size |
|---|---|
website/.docusaurus/globalData.json |
49.9 kB |
website/build/assets/css/styles.********.css |
105 kB |
website/build/assets/js/main.********.js |
612 kB |
to be continued after React 18 upgrade: we need time sliced hydration
https://twitter.com/ryanflorence/status/1547959632663961602