nuxt-vitalizer
Version:
Instantly better LCP scores in Google Lighthouse
86 lines (82 loc) • 2.61 kB
JavaScript
import { defineNuxtModule, useLogger, createResolver, addComponent, addTemplate } from '@nuxt/kit';
import { genImport } from 'knitwork';
import { defu } from 'defu';
const name = "nuxt-vitalizer";
const module = defineNuxtModule({
meta: {
name,
configKey: "vitalizer"
},
defaults: {
disablePrefetchLinks: "dynamicImports",
disablePreloadLinks: false,
disableStylesheets: false,
delayHydration: {}
},
async setup(options, nuxt) {
const moduleName = name;
const logger = useLogger(name);
const { resolve } = createResolver(import.meta.url);
options = defu(options, {
delayHydration: {
hydrateOnEvents: ["mousemove", "scroll", "keydown", "click", "touchstart", "wheel"],
idleCallbackTimeout: 8e3,
postIdleTimeout: 4e3
}
});
nuxt.options.build.transpile.push(resolve("runtime"));
await addComponent({
name: "DelayHydration",
filePath: resolve("runtime/components/DelayHydration")
});
await addComponent({
name: "SkipHydration",
filePath: resolve("runtime/components/SkipHydration")
});
addTemplate({
filename: `module/${moduleName}.mjs`,
getContents() {
return `
export const delayHydrationOptions = ${JSON.stringify(options.delayHydration, void 0, 2)}
`.trimStart();
}
});
addTemplate({
filename: `module/${moduleName}.d.ts`,
getContents() {
return `
${genImport(resolve("module"), ["ModuleOptions"])}
export declare const delayHydrationOptions: Required<Required<ModuleOptions>['delayHydration']>
`.trimStart();
}
});
if (nuxt.options._prepare || nuxt.options.dev)
return;
nuxt.hooks.hook("build:manifest", (manifest) => {
for (const item of Object.values(manifest)) {
if (options.disablePrefetchLinks) {
item.dynamicImports = [];
}
if (options.disablePrefetchLinks === true) {
item.prefetch = false;
}
if (options.disablePreloadLinks) {
item.preload = false;
}
if (nuxt.options.features.inlineStyles) {
if (options.disableStylesheets === "entry" && item.isEntry && item.css) {
for (let i = item.css.length - 1; i >= 0; i--) {
if (item.css[i].startsWith("entry")) {
item.css.splice(i, 1);
}
}
} else if (options.disableStylesheets && item.resourceType === "script") {
item.css = [];
}
}
}
});
logger.success("Optimized Web Vitals");
}
});
export { module as default };