Nuxt module to prune html before sending it to the browser (it removes elements matching CSS selector(s)), useful for boosting performance showing a different HTML for bots by removing all the scripts with dynamic rendering.
Due to the versatility of Nuxt (and of the SSR in general), a website generated (or served) via node, has everything it needs already injected (in the HTML, ex. styles). So, usually, for a bot or for a human, the website its almost visually the same without Javascript.
These library was born to remove the scripts injected in the HTML only if a visitor is a Bot or a "Chrome Lighthouse". This should speed up (blazing fast) your nuxt-website up to a value of ~95 in performance during an Audit because it cheats various scenarios.
Obviously this could cause some unexpected behaviors.
N.B. : Valid for Bots, PageSpeed Insights, Google Measure and Lighthouse Audits. This is known as Dynamic Rendering
Cons:
- no SPA navigation;
- no lazy-load for images (only if native, or with a custom
script
or withselectorToKeep
); - no
<client-only>
html.
Pro:
- some of these features aren't "used by" a Bot or a Lighthouse Audit, so you don't really need them (ex. Bots doesn't need
SPA navigation
,client-only
tags could lead in a slower TTI); - less HTML;
- BOTS only have the Javascript they need;
- PageSpeed Insights, Measure and Lighthouse Audit in Chrome are already triggered by the plugin without the needing of change any value;
- fast TTI, fast FCP, fast FMP, fast all.
Inspired by this rcfs and this issue.
- Before setting up the module, try to Disable JavaScript With Chrome DevTools while navigate your website, this is how your website appear to a Bot (with this module activated);
- If you
generate
your site it's not possibile to check the user-agent, so i choose to always prune HTML (you can disable this behavior by setting thehookGeneratePage
configuration value tofalse
); - If you use some
<client-only>
components, you should prepare a version that is visually the same with the placeholder slot; - This plugin was thought for Bots and uses only the
remove()
method ofCheerio
; - You can check the website as a GoogleBot, following this guide.
- It use the MobileDetect library to check if
.is( 'bot' )
,.match( options.lighthouseUserAgent )
or.match( options.matchUserAgent )
; - Nuxt hooks, so the plugin has access to
req.headers[ 'user-agent' ]
only if the project is running as a server (ex.nuxt start
); - It use Cheerio, jQuery for servers, library to prune the html.
- Add
@luxdamore/nuxt-prune-html
dependency to your project; - Add
@luxdamore/nuxt-prune-html
in themodules
section of yournuxt.config.js
;
yarn add @luxdamore/nuxt-prune-html # or npm install --save @luxdamore/nuxt-prune-html
N.B. : the config is only shallow merged, not deep merged.
// nuxt.config.js
export default {
// Module installation
modules: [ '@luxdamore/nuxt-prune-html' ],
// Module config
pruneHtml: {
hideErrorsInConsole: false,
hideGenericMessagesInConsole: false, // Disabled in production
enabled: false, // Disabled in dev-mode due to the hot reload (is client-side)
selectors: [ // Css selectors to prune
'link[rel="preload"][as="script"]',
'script:not([type="application/ld+json"])',
],
selectorToKeep: null, // Disallow pruning of scripts with this class, N.B.: this selector will be appended to every selectors, `ex. script:not([type="application/ld+json"]):not(__VALUE__)`
script: [], // Inject custom scripts only for matched UA (BOTS-only)
link: [], // Inject custom links only for matched UA (BOTS-only)
cheerio: { // It use Cheerio under the hood, so this is the config passed in the cheerio.load() method
xmlMode: false,
},
ignoreBotOrLighthouse: false, // Remove selectors in any case, not depending on Bot or Lighthouse
isBot: true, // Remove selectors if is a bot
isLighthouse: true, // Remove selectors if match the Lighthouse UserAgent
matchUserAgent: null, // Remove selectors if this userAgent is matched, either as String or RegExp (a string will be converted to a case-insensitive RegExp in the MobileDetect library)
hookRenderRoute: true, // Activate the prune during the `hook:render:route`
hookGeneratePage: true, // Activate the prune during the `hook:generate:page`
lighthouseUserAgent: 'lighthouse', // Value of the Lighthouse UserAgent, either as String or RegExp (a string will be converted to a case-insensitive RegExp in the MobileDetect library)
headerName: 'user-agent', // Value of a custom header name passed from a Lambda Edge function, or similar
},
};
With link
and script
it's possibile to add one or more objects ex.:
export default {
pruneHtml: {
script: [
{
src: '/my-custom-lazy-load-for-bots.js',
lazy: true,
defer: true,
},
],
link: [
{
src: '/my-custom-lazy-load-for-bots.js',
rel: 'preload',
as: 'script',
position: 'phead', // Default value is 'body' --> Other allowed values are: 'phead', 'head' and 'pbody'
},
],
},
};
- Clone this repository;
- Install dependencies using
yarn install
ornpm install
; - Start development server using
yarn dev
ornpm run dev
; - Build Github Pages using
yarn generate
ornpm run generate
(the content is automatically generated into the/docs
folder).
Please make sure to read the Issue Reporting Checklist before opening an issue. Issues not conforming to the guidelines may be closed immediately.
Please make sure to read the Contributing Guide before making a pull request.
Details changes for each release are documented in the release notes.
MIT License // Copyright (Β©) 2019-present Luca Iaconelli
Do you want to share a beer? We can be good friends.. Paypal // Patreon
It's always a good day to be magnanimous - cit