astro-ghostcms/.pnpm-store/v3/files/58/c579b80ee78ef252e2c6106eebc...

111 lines
3.9 KiB
Plaintext

const EXTERNAL_URL_REGEX = /^(?:[a-z+]+:)?\/\//i;
const perf = [
{
code: "perf-use-image-component",
title: "Use the Image component",
message: "This image could be replaced with the Image component to improve performance.",
selector: "img:not([data-image-component])",
async match(element) {
const src = element.getAttribute("src");
if (!src)
return false;
if (src.startsWith("data:"))
return false;
if (!EXTERNAL_URL_REGEX.test(src)) {
const imageData = await fetch(src).then((response) => response.blob());
if (imageData.size < 20480)
return false;
}
return true;
}
},
{
code: "perf-use-loading-lazy",
title: 'Use the loading="lazy" attribute',
message: (element) => `This ${element.nodeName} tag is below the fold and could be lazy-loaded to improve performance.`,
selector: 'img:not([loading]), img[loading="eager"], iframe:not([loading]), iframe[loading="eager"]',
match(element) {
const htmlElement = element;
if (htmlElement.offsetTop < window.innerHeight)
return false;
return true;
}
},
{
code: "perf-use-loading-eager",
title: 'Use the loading="eager" attribute',
message: (element) => `This ${element.nodeName} tag is above the fold and could be eagerly-loaded to improve performance.`,
selector: 'img[loading="lazy"], iframe[loading="lazy"]',
match(element) {
const htmlElement = element;
if (htmlElement.offsetTop > window.innerHeight)
return false;
return true;
}
},
{
code: "perf-use-videos",
title: "Use videos instead of GIFs for large animations",
message: "This GIF could be replaced with a video to reduce its file size and improve performance.",
selector: 'img[src$=".gif"]',
async match(element) {
const src = element.getAttribute("src");
if (!src)
return false;
if (EXTERNAL_URL_REGEX.test(src))
return false;
if (!EXTERNAL_URL_REGEX.test(src)) {
const imageData = await fetch(src).then((response) => response.blob());
if (imageData.size < 102400)
return false;
}
return true;
}
},
{
code: "perf-slow-component-server-render",
title: "Server-rendered component took a long time to render",
message: (element) => `This component took an unusually long time to render on the server (${getCleanRenderingTime(
element.getAttribute("server-render-time")
)}). This might be a sign that it's doing too much work on the server, or something is blocking rendering.`,
selector: "astro-island[server-render-time]",
match(element) {
const serverRenderTime = element.getAttribute("server-render-time");
if (!serverRenderTime)
return false;
const renderingTime = parseFloat(serverRenderTime);
if (Number.isNaN(renderingTime))
return false;
return renderingTime > 500;
}
},
{
code: "perf-slow-component-client-hydration",
title: "Client-rendered component took a long time to hydrate",
message: (element) => `This component took an unusually long time to render on the server (${getCleanRenderingTime(
element.getAttribute("client-render-time")
)}). This could be a sign that something is blocking the main thread and preventing the component from hydrating quickly.`,
selector: "astro-island[client-render-time]",
match(element) {
const clientRenderTime = element.getAttribute("client-render-time");
if (!clientRenderTime)
return false;
const renderingTime = parseFloat(clientRenderTime);
if (Number.isNaN(renderingTime))
return false;
return renderingTime > 500;
}
}
];
function getCleanRenderingTime(time) {
if (!time)
return "unknown";
const renderingTime = parseFloat(time);
if (Number.isNaN(renderingTime))
return "unknown";
return renderingTime.toFixed(2) + "s";
}
export {
perf
};