Skip to content

Commit a81106b

Browse files
elliott-with-the-longest-name-on-githubdummdidummConduitry
authored
feat: Add a speedier script tag for prerendered redirects (#9911)
* feat: Add a script redirect to prerendered pages * changeset * Update .changeset/hungry-rocks-hunt.md Co-authored-by: Simon H <[email protected]> * fix test * feat: Update string escaping * Update .changeset/hungry-rocks-hunt.md Co-authored-by: Conduitry <[email protected]> --------- Co-authored-by: Simon H <[email protected]> Co-authored-by: Conduitry <[email protected]>
1 parent b061166 commit a81106b

File tree

9 files changed

+36
-6
lines changed

9 files changed

+36
-6
lines changed

.changeset/hungry-rocks-hunt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
perf: add `<script>` to prerendered redirects for faster redirects

packages/kit/src/core/postbuild/prerender.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { get_route_segments } from '../../utils/routing.js';
1212
import { queue } from './queue.js';
1313
import { crawl } from './crawl.js';
1414
import { forked } from '../../utils/fork.js';
15+
import * as devalue from 'devalue';
1516

1617
export default forked(import.meta.url, prerender);
1718

@@ -340,7 +341,11 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
340341

341342
writeFileSync(
342343
dest,
343-
`<meta http-equiv="refresh" content=${escape_html_attr(`0;url=${location}`)}>`
344+
`<script>location.href=${devalue.uneval(
345+
location
346+
)};</script><meta http-equiv="refresh" content=${escape_html_attr(
347+
`0;url=${location}`
348+
)}>`
344349
);
345350

346351
written.add(file);

packages/kit/test/prerendering/basics/src/routes/redirect-encoded/+page.svelte

Whitespace-only changes.

packages/kit/test/prerendering/basics/src/routes/redirect-malicious/+page.svelte

Whitespace-only changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { redirect } from '@sveltejs/kit';
2+
3+
/** @type {import('@sveltejs/kit').Load} */
4+
export function load() {
5+
throw redirect(301, '/env');
6+
}

packages/kit/test/prerendering/basics/src/routes/redirect-server/+page.svelte

Whitespace-only changes.

packages/kit/test/prerendering/basics/src/routes/redirect/+page.svelte

Whitespace-only changes.

packages/kit/test/prerendering/basics/test/tests.spec.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ test('renders a redirect', () => {
1616
const content = read('redirect.html');
1717
assert.equal(
1818
content,
19-
'<meta http-equiv="refresh" content="0;url=https://example.com/redirected">'
19+
'<script>location.href="https:\\u002F\\u002Fexample.com\\u002Fredirected";</script><meta http-equiv="refresh" content="0;url=https://example.com/redirected">'
2020
);
2121
});
2222

2323
test('renders a server-side redirect', () => {
2424
const html = read('redirect-server.html');
25-
assert.equal(html, '<meta http-equiv="refresh" content="0;url=https://example.com/redirected">');
25+
assert.equal(
26+
html,
27+
'<script>location.href="https:\\u002F\\u002Fexample.com\\u002Fredirected";</script><meta http-equiv="refresh" content="0;url=https://example.com/redirected">'
28+
);
2629

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

@@ -36,15 +39,23 @@ test('does not double-encode redirect locations', () => {
3639
const content = read('redirect-encoded.html');
3740
assert.equal(
3841
content,
39-
'<meta http-equiv="refresh" content="0;url=https://example.com/redirected?returnTo=%2Ffoo%3Fbar%3Dbaz">'
42+
'<script>location.href="https:\\u002F\\u002Fexample.com\\u002Fredirected?returnTo=%2Ffoo%3Fbar%3Dbaz";</script><meta http-equiv="refresh" content="0;url=https://example.com/redirected?returnTo=%2Ffoo%3Fbar%3Dbaz">'
4043
);
4144
});
4245

4346
test('escapes characters in redirect', () => {
4447
const content = read('redirect-malicious.html');
4548
assert.equal(
4649
content,
47-
'<meta http-equiv="refresh" content="0;url=https://example.com/</script>alert(&quot;pwned&quot;)">'
50+
'<script>location.href="https:\\u002F\\u002Fexample.com\\u002F\\u003C\\u002Fscript\\u003Ealert(\\"pwned\\")";</script><meta http-equiv="refresh" content="0;url=https://example.com/</script>alert(&quot;pwned&quot;)">'
51+
);
52+
});
53+
54+
test('renders a relative redirect', () => {
55+
const content = read('redirect-relative.html');
56+
assert.equal(
57+
content,
58+
'<script>location.href="\\u002Fenv";</script><meta http-equiv="refresh" content="0;url=/env">'
4859
);
4960
});
5061

packages/kit/test/prerendering/paths-base/test/tests.spec.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ test('prerenders /path-base', () => {
1414

1515
test('prerenders /path-base/redirect', () => {
1616
const content = read('redirect.html');
17-
assert.equal(content, '<meta http-equiv="refresh" content="0;url=/path-base/dynamic/foo">');
17+
assert.equal(
18+
content,
19+
'<script>location.href="\\u002Fpath-base\\u002Fdynamic\\u002Ffoo";</script><meta http-equiv="refresh" content="0;url=/path-base/dynamic/foo">'
20+
);
1821
});
1922

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

0 commit comments

Comments
 (0)