Skip to content

Commit 882e75f

Browse files
authored
perf: cache dynamic imports of nodes (#10080)
it seems that Node spends a considerable amount of time inside its own module cache, so memoizing those ourselves is faster
1 parent 47d8048 commit 882e75f

File tree

4 files changed

+33
-6
lines changed

4 files changed

+33
-6
lines changed

.changeset/wild-mice-end.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: cache dynamic imports of nodes

packages/kit/src/core/generate_manifest/index.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export function generate_manifest({ build_data, relative_path, routes }) {
4444
);
4545

4646
/** @type {(path: string) => string} */
47-
const loader = (path) => `() => import('${path}')`;
47+
const loader = (path) => `__memo(() => import('${path}'))`;
4848

4949
const assets = build_data.manifest_data.assets.map((asset) => asset.file);
5050
if (build_data.service_worker) {
@@ -65,8 +65,8 @@ export function generate_manifest({ build_data, relative_path, routes }) {
6565

6666
// prettier-ignore
6767
// String representation of
68-
/** @type {import('@sveltejs/kit').SSRManifest} */
69-
return dedent`
68+
/** @template {import('@sveltejs/kit').SSRManifest} T */
69+
const manifest_expr = dedent`
7070
{
7171
appDir: ${s(build_data.app_dir)},
7272
appPath: ${s(build_data.app_path)},
@@ -97,10 +97,26 @@ export function generate_manifest({ build_data, relative_path, routes }) {
9797
}).filter(Boolean).join(',\n')}
9898
],
9999
matchers: async () => {
100-
${Array.from(matchers).map(type => `const { match: ${type} } = await import ('${(join_relative(relative_path, `/entries/matchers/${type}.js`))}')`).join('\n')}
100+
${Array.from(
101+
matchers,
102+
type => `const { match: ${type} } = await import ('${(join_relative(relative_path, `/entries/matchers/${type}.js`))}')`
103+
).join('\n')}
101104
return { ${Array.from(matchers).join(', ')} };
102105
}
103106
}
104107
}
105108
`;
109+
110+
// Memoize the loaders to prevent Node from doing unnecessary work
111+
// on every dynamic import call
112+
return dedent`
113+
(() => {
114+
function __memo(fn) {
115+
let value;
116+
return () => value ??= (value = fn());
117+
}
118+
119+
return ${manifest_expr}
120+
})()
121+
`;
106122
}

packages/kit/src/exports/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,12 @@ const encoder = new TextEncoder();
8686
export function text(body, init) {
8787
const headers = new Headers(init?.headers);
8888
if (!headers.has('content-length')) {
89-
headers.set('content-length', encoder.encode(body).byteLength.toString());
89+
const encoded = encoder.encode(body);
90+
headers.set('content-length', encoded.byteLength.toString());
91+
return new Response(encoded, {
92+
...init,
93+
headers
94+
});
9095
}
9196

9297
return new Response(body, {

packages/kit/src/exports/vite/build/build_server.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli
5050

5151
if (node.component && client_manifest) {
5252
exports.push(
53-
`export const component = async () => (await import('../${
53+
'let component_cache;',
54+
`export const component = async () => component_cache ??= (await import('../${
5455
resolve_symlinks(server_manifest, node.component).chunk.file
5556
}')).default;`
5657
);

0 commit comments

Comments
 (0)