Skip to content
Merged
5 changes: 5 additions & 0 deletions .changeset/hungry-rocks-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

perf: add a script to prerendered redirects for faster redirects
6 changes: 5 additions & 1 deletion packages/kit/src/core/postbuild/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,11 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {

writeFileSync(
dest,
`<meta http-equiv="refresh" content=${escape_html_attr(`0;url=${location}`)}>`
`<script>location.href="${encodeURI(
decodeURIComponent(location)
)}";</script><meta http-equiv="refresh" content=${escape_html_attr(
`0;url=${location}`
)}>`
);

written.add(file);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { redirect } from '@sveltejs/kit';

/** @type {import('@sveltejs/kit').Load} */
export function load() {
throw redirect(301, '/env');
}
Empty file.
19 changes: 15 additions & 4 deletions packages/kit/test/prerendering/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ test('renders a redirect', () => {
const content = read('redirect.html');
assert.equal(
content,
'<meta http-equiv="refresh" content="0;url=https://example.com/redirected">'
'<script>location.href="https://example.com/redirected";</script><meta http-equiv="refresh" content="0;url=https://example.com/redirected">'
);
});

test('renders a server-side redirect', () => {
const html = read('redirect-server.html');
assert.equal(html, '<meta http-equiv="refresh" content="0;url=https://example.com/redirected">');
assert.equal(
html,
'<script>location.href="https://example.com/redirected";</script><meta http-equiv="refresh" content="0;url=https://example.com/redirected">'
);

const data = JSON.parse(read('redirect-server/__data.json'));

Expand All @@ -37,15 +40,23 @@ test('does not double-encode redirect locations', () => {
const content = read('redirect-encoded.html');
assert.equal(
content,
'<meta http-equiv="refresh" content="0;url=https://example.com/redirected?returnTo=%2Ffoo%3Fbar%3Dbaz">'
'<script>location.href="https://example.com/redirected?returnTo=/foo?bar=baz";</script><meta http-equiv="refresh" content="0;url=https://example.com/redirected?returnTo=%2Ffoo%3Fbar%3Dbaz">'
);
});

test('escapes characters in redirect', () => {
const content = read('redirect-malicious.html');
assert.equal(
content,
'<meta http-equiv="refresh" content="0;url=https://example.com/</script>alert(&quot;pwned&quot;)">'
'<script>location.href="https://example.com/%3C/script%3Ealert(%22pwned%22)";</script><meta http-equiv="refresh" content="0;url=https://example.com/</script>alert(&quot;pwned&quot;)">'
);
});

test('renders a relative redirect', () => {
const content = read('redirect-relative.html');
assert.equal(
content,
'<script>location.href="/env";</script><meta http-equiv="refresh" content="0;url=/env">'
);
});

Expand Down
5 changes: 4 additions & 1 deletion packages/kit/test/prerendering/paths-base/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ test('prerenders /path-base', () => {

test('prerenders /path-base/redirect', () => {
const content = read('redirect.html');
assert.equal(content, '<meta http-equiv="refresh" content="0;url=/path-base/dynamic/foo">');
assert.equal(
content,
'<script>location.href="/path-base/dynamic/foo";</script><meta http-equiv="refresh" content="0;url=/path-base/dynamic/foo">'
);
});

test('prerenders /path-base/dynamic/foo', () => {
Expand Down