vite-plugin-capo
Version:
Reorders HTML <head> elements in Vite projects at build time using capo.js guidelines to improve page load performance.
121 lines (120 loc) • 2.72 kB
JavaScript
import { parse as N, serialize as P } from "parse5";
const h = (t) => t.nodeName !== "#text" && "tagName" in t, n = {
Async: "async",
Charset: "charset",
Defer: "defer",
HttpEquiv: "http-equiv",
Name: "name",
Rel: "rel",
Type: "type"
}, c = {
DnsPrefetch: "dns-prefetch",
ModulePreload: "modulepreload",
Preconnect: "preconnect",
Prefetch: "prefetch",
Preload: "preload",
Prerender: "prerender",
Stylesheet: "stylesheet"
}, l = {
Base: "base",
Link: "link",
Meta: "meta",
Script: "script",
Style: "style",
Title: "title"
}, S = [
"accept-ch",
"content-security-policy",
"content-type",
"default-style",
"delegate-ch",
"origin-trial",
"x-dns-prefetch-control"
], a = (t, s) => t.attrs.find((p) => p.name === s)?.value, g = (t) => {
const s = [], p = [], o = [], r = [], f = [], m = [], d = [], y = [], b = [], k = [], u = [];
for (const e of t) {
if (!h(e)) {
u.push(e);
continue;
}
switch (e.tagName) {
case l.Base: {
s.push(e);
break;
}
case l.Link: {
switch (a(e, n.Rel)) {
case c.DnsPrefetch:
case c.Prefetch:
case c.Prerender:
k.push(e);
break;
case c.ModulePreload:
case c.Preload:
y.push(e);
break;
case c.Preconnect:
o.push(e);
break;
case c.Stylesheet:
d.push(e);
break;
default:
u.push(e);
break;
}
break;
}
case l.Meta: {
const i = a(e, n.HttpEquiv);
i && S.includes(i) || a(e, n.Charset) || a(e, n.Name) === "viewport" ? s.push(e) : u.push(e);
break;
}
case l.Script: {
a(e, n.Async) ? r.push(e) : a(e, n.Defer) || a(e, n.Type) === "module" ? b.push(e) : m.push(e);
break;
}
case l.Style: {
e.childNodes.some((i) => i.nodeName === "#text" && "value" in i && i.value.includes("@import")) ? f.push(e) : d.push(e);
break;
}
case l.Title: {
p.push(e);
break;
}
default: {
u.push(e);
break;
}
}
}
return [
...s,
...p,
...o,
...r,
...f,
...m,
...d,
...y,
...b,
...k,
...u
];
}, v = (t) => {
const s = N(t), o = s.childNodes.find((r) => h(r) && r.tagName === "html")?.childNodes.find((r) => h(r) && r.tagName === "head");
return o ? (o.childNodes = g(o.childNodes), P(s)) : t;
};
function T() {
return {
name: "vite-plugin-capo",
enforce: "post",
apply: "build",
transformIndexHtml(t) {
return v(t);
}
};
}
export {
T as capo
};