Skip to content

Commit 0f82298

Browse files
authored
chore: avoid loading page nodes three times (#13540)
1 parent c808f3c commit 0f82298

File tree

3 files changed

+41
-33
lines changed

3 files changed

+41
-33
lines changed

packages/kit/src/runtime/server/page/index.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { render_response } from './render.js';
1515
import { respond_with_error } from './respond_with_error.js';
1616
import { get_option } from '../../../utils/options.js';
1717
import { get_data_json } from '../data/index.js';
18-
import { load_page_nodes } from './load_page_nodes.js';
1918
import { DEV } from 'esm-env';
2019

2120
/**
@@ -29,10 +28,11 @@ const MAX_DEPTH = 10;
2928
* @param {import('types').SSROptions} options
3029
* @param {import('@sveltejs/kit').SSRManifest} manifest
3130
* @param {import('types').SSRState} state
31+
* @param {Array<import('types').SSRNode | undefined>} nodes
3232
* @param {import('types').RequiredResolveOptions} resolve_opts
3333
* @returns {Promise<Response>}
3434
*/
35-
export async function render_page(event, page, options, manifest, state, resolve_opts) {
35+
export async function render_page(event, page, options, manifest, state, nodes, resolve_opts) {
3636
if (state.depth > MAX_DEPTH) {
3737
// infinite request cycle detected
3838
return text(`Not found: ${event.url.pathname}`, {
@@ -46,8 +46,6 @@ export async function render_page(event, page, options, manifest, state, resolve
4646
}
4747

4848
try {
49-
const nodes = await load_page_nodes(page, manifest);
50-
5149
const leaf_node = /** @type {import('types').SSRNode} */ (nodes.at(-1));
5250

5351
let status = 200;

packages/kit/src/runtime/server/page/load_page_nodes.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

packages/kit/src/runtime/server/respond.js

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import { json, text } from '../../exports/index.js';
2424
import { action_json_redirect, is_action_json_request } from './page/actions.js';
2525
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
2626
import { get_public_env } from './env_module.js';
27-
import { load_page_nodes } from './page/load_page_nodes.js';
2827
import { get_page_config } from '../../utils/route_config.js';
2928
import { resolve_route } from './page/server_routing.js';
3029
import { validateHeaders } from './validate-headers.js';
@@ -237,18 +236,19 @@ export async function respond(request, options, manifest, state) {
237236
};
238237

239238
try {
239+
/** @type {Array<import('types').SSRNode | undefined> | undefined} */
240+
const page_nodes = route?.page ? await load_page_nodes(route.page, manifest) : undefined;
241+
240242
// determine whether we need to redirect to add/remove a trailing slash
241243
if (route) {
242244
// if `paths.base === '/a/b/c`, then the root route is `/a/b/c/`,
243245
// regardless of the `trailingSlash` route option
244246
if (url.pathname === base || url.pathname === base + '/') {
245247
trailing_slash = 'always';
246-
} else if (route.page) {
247-
const nodes = await load_page_nodes(route.page, manifest);
248-
248+
} else if (page_nodes) {
249249
if (DEV) {
250-
const layouts = nodes.slice(0, -1);
251-
const page = nodes.at(-1);
250+
const layouts = page_nodes.slice(0, -1);
251+
const page = page_nodes.at(-1);
252252

253253
for (const layout of layouts) {
254254
if (layout) {
@@ -269,7 +269,7 @@ export async function respond(request, options, manifest, state) {
269269
}
270270
}
271271

272-
trailing_slash = get_option(nodes, 'trailingSlash');
272+
trailing_slash = get_option(page_nodes, 'trailingSlash');
273273
} else if (route.endpoint) {
274274
const node = await route.endpoint();
275275
trailing_slash = node.trailingSlash;
@@ -306,10 +306,9 @@ export async function respond(request, options, manifest, state) {
306306
const node = await route.endpoint();
307307
config = node.config ?? config;
308308
prerender = node.prerender ?? prerender;
309-
} else if (route.page) {
310-
const nodes = await load_page_nodes(route.page, manifest);
311-
config = get_page_config(nodes) ?? config;
312-
prerender = get_option(nodes, 'prerender') ?? false;
309+
} else if (page_nodes) {
310+
config = get_page_config(page_nodes) ?? config;
311+
prerender = get_option(page_nodes, 'prerender') ?? false;
313312
}
314313

315314
if (state.before_handle) {
@@ -349,7 +348,7 @@ export async function respond(request, options, manifest, state) {
349348
const response = await options.hooks.handle({
350349
event,
351350
resolve: (event, opts) =>
352-
resolve(event, opts).then((response) => {
351+
resolve(event, page_nodes, opts).then((response) => {
353352
// add headers/cookies here, rather than inside `resolve`, so that we
354353
// can do it once for all responses instead of once per `return`
355354
for (const key in headers) {
@@ -426,9 +425,10 @@ export async function respond(request, options, manifest, state) {
426425

427426
/**
428427
* @param {import('@sveltejs/kit').RequestEvent} event
428+
* @param {Array<import('types').SSRNode | undefined> | undefined} page_nodes
429429
* @param {import('@sveltejs/kit').ResolveOptions} [opts]
430430
*/
431-
async function resolve(event, opts) {
431+
async function resolve(event, page_nodes, opts) {
432432
try {
433433
if (opts) {
434434
resolve_opts = {
@@ -472,8 +472,18 @@ export async function respond(request, options, manifest, state) {
472472
} else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
473473
response = await render_endpoint(event, await route.endpoint(), state);
474474
} else if (route.page) {
475-
if (page_methods.has(method)) {
476-
response = await render_page(event, route.page, options, manifest, state, resolve_opts);
475+
if (!page_nodes) {
476+
throw new Error('page_nodes not found. This should never happen');
477+
} else if (page_methods.has(method)) {
478+
response = await render_page(
479+
event,
480+
route.page,
481+
options,
482+
manifest,
483+
state,
484+
page_nodes,
485+
resolve_opts
486+
);
477487
} else {
478488
const allowed_methods = new Set(allowed_page_methods);
479489
const node = await manifest._.nodes[route.page.leaf]();
@@ -499,9 +509,8 @@ export async function respond(request, options, manifest, state) {
499509
}
500510
}
501511
} else {
502-
// a route will always have a page or an endpoint, but TypeScript
503-
// doesn't know that
504-
throw new Error('This should never happen');
512+
// a route will always have a page or an endpoint, but TypeScript doesn't know that
513+
throw new Error('Route is neither page nor endpoint. This should never happen');
505514
}
506515

507516
// If the route contains a page and an endpoint, we need to add a
@@ -578,3 +587,15 @@ export async function respond(request, options, manifest, state) {
578587
}
579588
}
580589
}
590+
591+
/**
592+
* @param {import('types').PageNodeIndexes} page
593+
* @param {import('@sveltejs/kit').SSRManifest} manifest
594+
*/
595+
export function load_page_nodes(page, manifest) {
596+
return Promise.all([
597+
// we use == here rather than === because [undefined] serializes as "[null]"
598+
...page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
599+
manifest._.nodes[page.leaf]()
600+
]);
601+
}

0 commit comments

Comments
 (0)