Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/plugins/prerender-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ export function prerenderPlugin({ prerenderScript, renderTarget, additionalPrere
};

/** @type {import('./types.d.ts').Head} */
let head = { lang: '', title: '', elements: new Set() };
let head = { lang: '', title: '', elements: new Set(), startElements: new Set() };

let prerender;
try {
Expand Down Expand Up @@ -435,7 +435,7 @@ export function prerenderPlugin({ prerenderScript, renderTarget, additionalPrere

// Reset HTML doc & head data
const htmlDoc = htmlParse(tpl, { comment: true });
head = { lang: '', title: '', elements: new Set() };
head = { lang: '', title: '', elements: new Set(), startElements: new Set() };

// Add any discovered links to the list of routes to pre-render:
if (result.links) {
Expand Down Expand Up @@ -480,6 +480,16 @@ export function prerenderPlugin({ prerenderScript, renderTarget, additionalPrere
htmlDoc.querySelector('html').setAttribute('lang', enc(head.lang));
}

if (head.startElements) {
// Inject HTML links at the start of <head> for any stylesheets injected during rendering of the page:
htmlHead.insertAdjacentHTML(
'afterbegin',
Array.from(
new Set(Array.from(head.startElements).map(serializeElement)),
).join('\n'),
);
}

if (head.elements) {
// Inject HTML links at the end of <head> for any stylesheets injected during rendering of the page:
htmlHead.insertAdjacentHTML(
Expand Down
7 changes: 7 additions & 0 deletions src/plugins/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ export interface HeadElement {
export interface Head {
lang: string;
title: string;
/**
* Which elements should be injected in the **start** of <head>
*/
startElements: Set<HeadElement>;
/**
* Which elements should be injected in the **end** of <head>
*/
elements: Set<HeadElement>;
}

Expand Down
23 changes: 23 additions & 0 deletions tests/prerender-api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,29 @@ test('Should support `head.title` property', async () => {
assert.match(prerenderedHtml, '<title>My Prerendered Site</title>');
});

test('Should support `head.startElements` property', async () => {
await loadFixture('simple', env);
await writeEntry(
env.tmp.path,
`
export async function prerender() {
return {
html: '<h1>Hello, World!</h1>',
head: {
startElements: new Set([
{ type: 'link', props: { rel: 'stylesheet', href: 'foo.css' } },
]),
},
};
}
`,
);
await viteBuild(env.tmp.path);

const prerenderedHtml = await getOutputFile(env.tmp.path, 'index.html');
assert.match(prerenderedHtml, '<link rel="stylesheet" href="foo.css">');
});

test('Should support `head.elements` property', async () => {
await loadFixture('simple', env);
await writeEntry(env.tmp.path, `
Expand Down