Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
nuxt-delay-hydration-v2
Advanced tools
Improve your Nuxt.js Google Lighthouse score by delaying hydration ⚡️
Status: Stable v2 v0 ✅ , v3 main ✅ Made possible by my Sponsor Program 💖 Follow me @harlan_zw 🐦 |
Delaying hydration is a technique to hint to Google that our scripts are not required for our app to function.
By delaying hydration we improve the Google Lighthouse score by reducing your "Blocking Time" metric.
Previously you may have used vue-lazy-hydration which works well. However, it is just a more verbose way of providing hints to Google, like we're doing with this module.
A progressively enhanced app is one that is designed to work without JavaScript, and then progressively enhanced with JavaScript.
Your scripts should not be required to use your website, this is what we're hinting to Google by delaying the hydration.
To do that you can ensure:
The idle CPU time hints to Google that these scripts are not required for your app to run.
For example:
Keep in mind, this is a hacky solution. Until Google can recognise progressive script enhancements, we'll need to rely on this approach.
If you're using Nuxt 2.x, please follow the docs on the v0 branch.
yarn add -D nuxt-delay-hydration
# npm i -D nuxt-delay-hydration
# pnpm add -D nuxt-delay-hydration
Requirement: Progressively enhanced SSR or SSG Nuxt app.
:warn: This module is experimental
// nuxt.config.ts
export default {
modules: [
'nuxt-delay-hydration',
],
delayHydration: {
// enables nuxt-delay-hydration in dev mode for testing
debug: process.env.NODE_ENV === 'development'
}
}
Note: The module will not run in development unless you have enabled debug.
By default, no mode is selected, you will need to select how you would the module to work.
Type: init
| mount
| manual
| false
Default: false
Type | Description | Use Case |
---|---|---|
false default | Disable the module | Testing |
init | Delays all scripts from loading. | Zero or minimal plugins/modules. |
mount recommended | Delays Nuxt while it's mounting. Plugins and some third-party scripts will work. | Minimal non-critical plugins and third-party plugins. |
manual | Delay is provided by the DelayHydration component. | All other apps |
Regardless of the mode you choose, please read further optimisations.
This mode delays all scripts from loading until the hydration promise is resolved.
It does this by hooking into the HTML rendering, removing all script tags and adding them back after the hydration promise is resolved.
This will provide the biggest speed improvements however is the riskiest.
Pros: Provides the biggest blocking time reduction
Cons: Risky if you have critical third party scripts
Benchmark: ~90-100% reduction
export default {
delayHydration: {
mode: 'init'
}
}
This mode delays Nuxt while it's mounting. Plugins and some third-party scripts will work.
This delays your layout and page components.
Pros: Safer and still provides good improvements
Cons: May still break certain layouts if they are js dependent.
Benchmark: ~70% reduction
export default {
delayHydration: {
mode: 'mount'
}
}
Using the manual mode, you manually specify what part of your app you'd like to delay. Useful for when you need some part of the page to always hydrate immediately, such as a navigation drawer.
Pros: Safest way to optimise
Cons: Speed improvement based on usage
export default {
delayHydration: {
mode: 'manual'
}
}
Once you have set the mode, you need to use the component.
<template>
<div>
<DelayHydration>
<div>
<LazyMyExpensiveComponent />
</div>
</DelayHydration>
</div>
</template>
To make sure the module is doing what you expect, there is a debug
mode, which when enabled will log behaviour in the console.
It might be a good idea to always debug on your local environment, in that instance you could do:
export default {
delayHydration: {
debug: process.env.NODE_ENV === 'development',
},
}
To make things easier, there is a component HydrationStatus
which will tell you what's going on.
<template>
<div>
<MyHeader />
<DelayHydration>
<div>
<!-- Show the hydration status, only for debugging -->
<HydrationStatus />
<main>
<nuxt />
</main>
<my-footer />
</div>
</DelayHydration>
</div>
</template>
Use my audit tool: https://unlighthouse.dev/
The best fix for this is to write your HTML in a way that doesn't need Javascript to be interactive.
However, there are use cases where you need to use Javascript and responding to the first click is important. In those instances, you can enable the replay of the click.
export default {
delayHydration: {
replayClick: true
},
}
This is an experimental configuration, you should test this option yourself before implementing it into your production app.
This will decrease all of your performance metrics. It's recommended you use async imports for these components.
Run nuxi analyze
to find large components. When loading them, prefix them with Lazy
.
Configuration should be provided on the delayHydration
key within your Nuxt config.
If you're finding the lab or field data is not performing, you may want to tinker with this advanced configuration.
Using the include
and exclude
options, you can specify which routes you'd like to delay hydration on.
// nuxt.config.ts
export default {
delayHydration: {
include: [
'/blog/**',
],
exclude: [
'/admin/**'
],
},
}
You can provide a glob pattern similar to route rules or a regex.
hydrateOnEvents
string[]
[ 'mousemove', 'scroll', 'keydown', 'click', 'touchstart', 'wheel' ]
Controls which browser events should trigger the hydration to resume. By default, it is quite aggressive to avoid possible user experience issues.
replayClick
boolean
false
If the trigger for hydration was a click, you can replay it. Replaying it will re-execute the event when it is presumed your app is hydrated.
For example, if a user clicks a hamburger icon and hydration is required to open the menu, it would replay the click once hydrated.
⚠️ This is experimental, use with caution.
idleCallbackTimeout
number
(milliseconds)7000
When waiting for an idle callback, it's possible to define a max amount of time to wait in milliseconds. This is useful when there are a lot of network requests happening.
postIdleTimeout
{ mobile: number, desktop: number }
(milliseconds){ mobile: 5000, desktop: 4000, }
How many to wait (in milliseconds) after the idle callback before we resume the hydration. This extra timeout is required to avoid the standard "blocking", we need to provide real idle time to lighthouse.
Mobile should always be higher than desktop as the CPU capacity will generally be a lot less than a desktop.
Note: The default will likely be customised in the future based on further benchmarking.
debug
boolean
false
Log details in the console on when hydration is blocked and when and why it becomes unblocked.
Live examples
MIT License © 2022 - Present Harlan Wilton
FAQs
Improve your Nuxt.js Google Lighthouse score by delaying hydration ⚡️
The npm package nuxt-delay-hydration-v2 receives a total of 1 weekly downloads. As such, nuxt-delay-hydration-v2 popularity was classified as not popular.
We found that nuxt-delay-hydration-v2 demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.