Skip to content

Commit 729aa7d

Browse files
authored
chore: centralize page node logic into a class (#13550)
1 parent 75efd88 commit 729aa7d

File tree

7 files changed

+137
-122
lines changed

7 files changed

+137
-122
lines changed

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

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
11
import { join } from 'node:path';
22
import { pathToFileURL } from 'node:url';
3-
import { get_option } from '../../utils/options.js';
4-
import {
5-
validate_layout_exports,
6-
validate_layout_server_exports,
7-
validate_page_exports,
8-
validate_page_server_exports,
9-
validate_server_exports
10-
} from '../../utils/exports.js';
3+
import { validate_server_exports } from '../../utils/exports.js';
114
import { load_config } from '../config/index.js';
125
import { forked } from '../../utils/fork.js';
136
import { installPolyfills } from '../../exports/node/polyfills.js';
147
import { ENDPOINT_METHODS } from '../../constants.js';
158
import { filter_private_env, filter_public_env } from '../../utils/env.js';
169
import { has_server_load, resolve_route } from '../../utils/routing.js';
17-
import { get_page_config } from '../../utils/route_config.js';
1810
import { check_feature } from '../../utils/features.js';
1911
import { createReadableStream } from '@sveltejs/kit/node';
12+
import { PageNodes } from '../../utils/page_nodes.js';
2013

2114
export default forked(import.meta.url, analyse);
2215

@@ -190,25 +183,18 @@ function analyse_endpoint(route, mod) {
190183
* @param {import('types').SSRNode} leaf
191184
*/
192185
function analyse_page(layouts, leaf) {
193-
for (const layout of layouts) {
194-
if (layout) {
195-
validate_layout_server_exports(layout.server, layout.server_id);
196-
validate_layout_exports(layout.universal, layout.universal_id);
197-
}
198-
}
199-
200186
/** @type {Array<'GET' | 'POST'>} */
201187
const methods = ['GET'];
202188
if (leaf.server?.actions) methods.push('POST');
203189

204-
validate_page_server_exports(leaf.server, leaf.server_id);
205-
validate_page_exports(leaf.universal, leaf.universal_id);
190+
const nodes = new PageNodes([...layouts, leaf]);
191+
nodes.validate();
206192

207193
return {
208-
config: get_page_config([...layouts, leaf]),
194+
config: nodes.get_config(),
209195
entries: leaf.universal?.entries ?? leaf.server?.entries,
210196
methods,
211-
prerender: get_option([...layouts, leaf], 'prerender') ?? false
197+
prerender: nodes.prerender()
212198
};
213199
}
214200

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

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
import { load_data, load_server_data } from './load_data.js';
1414
import { render_response } from './render.js';
1515
import { respond_with_error } from './respond_with_error.js';
16-
import { get_option } from '../../../utils/options.js';
1716
import { get_data_json } from '../data/index.js';
1817
import { DEV } from 'esm-env';
1918

@@ -28,7 +27,7 @@ const MAX_DEPTH = 10;
2827
* @param {import('types').SSROptions} options
2928
* @param {import('@sveltejs/kit').SSRManifest} manifest
3029
* @param {import('types').SSRState} state
31-
* @param {Array<import('types').SSRNode | undefined>} nodes
30+
* @param {import('../../../utils/page_nodes.js').PageNodes} nodes
3231
* @param {import('types').RequiredResolveOptions} resolve_opts
3332
* @returns {Promise<Response>}
3433
*/
@@ -46,7 +45,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
4645
}
4746

4847
try {
49-
const leaf_node = /** @type {import('types').SSRNode} */ (nodes.at(-1));
48+
const leaf_node = /** @type {import('types').SSRNode} */ (nodes.page());
5049

5150
let status = 200;
5251

@@ -68,16 +67,10 @@ export async function render_page(event, page, options, manifest, state, nodes,
6867
}
6968
}
7069

71-
const should_prerender_data = nodes.some(
72-
// prerender in case of trailingSlash because the client retrieves that value from the server
73-
(node) => node?.server?.load || node?.server?.trailingSlash !== undefined
74-
);
75-
const data_pathname = add_data_suffix(event.url.pathname);
76-
7770
// it's crucial that we do this before returning the non-SSR response, otherwise
7871
// SvelteKit will erroneously believe that the path has been prerendered,
7972
// causing functions to be omitted from the manifest generated later
80-
const should_prerender = get_option(nodes, 'prerender') ?? false;
73+
const should_prerender = nodes.prerender();
8174
if (should_prerender) {
8275
const mod = leaf_node.server;
8376
if (mod?.actions) {
@@ -94,13 +87,16 @@ export async function render_page(event, page, options, manifest, state, nodes,
9487
// inherit the prerender option of the page
9588
state.prerender_default = should_prerender;
9689

90+
const should_prerender_data = nodes.should_prerender_data();
91+
const data_pathname = add_data_suffix(event.url.pathname);
92+
9793
/** @type {import('./types.js').Fetched[]} */
9894
const fetched = [];
9995

10096
// renders an empty 'shell' page if SSR is turned off and if there is
10197
// no server data to prerender. As a result, the load functions and rendering
10298
// only occur client-side.
103-
if (get_option(nodes, 'ssr') === false && !(state.prerendering && should_prerender_data)) {
99+
if (nodes.ssr() === false && !(state.prerendering && should_prerender_data)) {
104100
// if the user makes a request through a non-enhanced form, the returned value is lost
105101
// because there is no SSR or client-side handling of the response
106102
if (DEV && action_result && !event.request.headers.has('x-sveltekit-action')) {
@@ -121,7 +117,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
121117
fetched,
122118
page_config: {
123119
ssr: false,
124-
csr: get_option(nodes, 'csr') ?? true
120+
csr: nodes.csr()
125121
},
126122
status,
127123
error: null,
@@ -140,7 +136,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
140136
let load_error = null;
141137

142138
/** @type {Array<Promise<import('types').ServerDataNode | null>>} */
143-
const server_promises = nodes.map((node, i) => {
139+
const server_promises = nodes.data.map((node, i) => {
144140
if (load_error) {
145141
// if an error happens immediately, don't bother with the rest of the nodes
146142
throw load_error;
@@ -175,10 +171,10 @@ export async function render_page(event, page, options, manifest, state, nodes,
175171
});
176172
});
177173

178-
const csr = get_option(nodes, 'csr') ?? true;
174+
const csr = nodes.csr();
179175

180176
/** @type {Array<Promise<Record<string, any> | null>>} */
181-
const load_promises = nodes.map((node, i) => {
177+
const load_promises = nodes.data.map((node, i) => {
182178
if (load_error) throw load_error;
183179
return Promise.resolve().then(async () => {
184180
try {
@@ -209,8 +205,8 @@ export async function render_page(event, page, options, manifest, state, nodes,
209205
for (const p of server_promises) p.catch(() => {});
210206
for (const p of load_promises) p.catch(() => {});
211207

212-
for (let i = 0; i < nodes.length; i += 1) {
213-
const node = nodes[i];
208+
for (let i = 0; i < nodes.data.length; i += 1) {
209+
const node = nodes.data[i];
214210

215211
if (node) {
216212
try {
@@ -298,7 +294,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
298294
});
299295
}
300296

301-
const ssr = get_option(nodes, 'ssr') ?? true;
297+
const ssr = nodes.ssr();
302298

303299
return await render_response({
304300
event,
@@ -307,7 +303,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
307303
state,
308304
resolve_opts,
309305
page_config: {
310-
csr: get_option(nodes, 'csr') ?? true,
306+
csr: nodes.csr(),
311307
ssr
312308
},
313309
status,

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { render_response } from './render.js';
22
import { load_data, load_server_data } from './load_data.js';
33
import { handle_error_and_jsonify, static_error_page, redirect_response } from '../utils.js';
4-
import { get_option } from '../../../utils/options.js';
54
import { Redirect } from '../../control.js';
65
import { get_status } from '../../../utils/error.js';
6+
import { PageNodes } from '../../../utils/page_nodes.js';
77

88
/**
99
* @typedef {import('./types.js').Loaded} Loaded
@@ -40,8 +40,9 @@ export async function respond_with_error({
4040
try {
4141
const branch = [];
4242
const default_layout = await manifest._.nodes[0](); // 0 is always the root layout
43-
const ssr = get_option([default_layout], 'ssr') ?? true;
44-
const csr = get_option([default_layout], 'csr') ?? true;
43+
const nodes = new PageNodes([default_layout]);
44+
const ssr = nodes.ssr();
45+
const csr = nodes.csr();
4546

4647
if (ssr) {
4748
state.error = true;

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

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,13 @@ import { exec } from '../../utils/routing.js';
1111
import { redirect_json_response, render_data } from './data/index.js';
1212
import { add_cookies_to_headers, get_cookies } from './cookie.js';
1313
import { create_fetch } from './fetch.js';
14+
import { PageNodes } from '../../utils/page_nodes.js';
1415
import { HttpError, Redirect, SvelteKitError } from '../control.js';
15-
import {
16-
validate_layout_exports,
17-
validate_layout_server_exports,
18-
validate_page_exports,
19-
validate_page_server_exports,
20-
validate_server_exports
21-
} from '../../utils/exports.js';
22-
import { get_option } from '../../utils/options.js';
16+
import { validate_server_exports } from '../../utils/exports.js';
2317
import { json, text } from '../../exports/index.js';
2418
import { action_json_redirect, is_action_json_request } from './page/actions.js';
2519
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
2620
import { get_public_env } from './env_module.js';
27-
import { get_page_config } from '../../utils/route_config.js';
2821
import { resolve_route } from './page/server_routing.js';
2922
import { validateHeaders } from './validate-headers.js';
3023
import {
@@ -172,8 +165,8 @@ export async function respond(request, options, manifest, state) {
172165
}
173166
}
174167

175-
/** @type {import('types').TrailingSlash | void} */
176-
let trailing_slash = undefined;
168+
/** @type {import('types').TrailingSlash} */
169+
let trailing_slash = 'never';
177170

178171
/** @type {Record<string, string>} */
179172
const headers = {};
@@ -236,8 +229,10 @@ export async function respond(request, options, manifest, state) {
236229
};
237230

238231
try {
239-
/** @type {Array<import('types').SSRNode | undefined> | undefined} */
240-
const page_nodes = route?.page ? await load_page_nodes(route.page, manifest) : undefined;
232+
/** @type {PageNodes|undefined} */
233+
const page_nodes = route?.page
234+
? new PageNodes(await load_page_nodes(route.page, manifest))
235+
: undefined;
241236

242237
// determine whether we need to redirect to add/remove a trailing slash
243238
if (route) {
@@ -247,40 +242,19 @@ export async function respond(request, options, manifest, state) {
247242
trailing_slash = 'always';
248243
} else if (page_nodes) {
249244
if (DEV) {
250-
const layouts = page_nodes.slice(0, -1);
251-
const page = page_nodes.at(-1);
252-
253-
for (const layout of layouts) {
254-
if (layout) {
255-
validate_layout_server_exports(
256-
layout.server,
257-
/** @type {string} */ (layout.server_id)
258-
);
259-
validate_layout_exports(
260-
layout.universal,
261-
/** @type {string} */ (layout.universal_id)
262-
);
263-
}
264-
}
265-
266-
if (page) {
267-
validate_page_server_exports(page.server, /** @type {string} */ (page.server_id));
268-
validate_page_exports(page.universal, /** @type {string} */ (page.universal_id));
269-
}
245+
page_nodes.validate();
270246
}
271-
272-
trailing_slash = get_option(page_nodes, 'trailingSlash');
247+
trailing_slash = page_nodes.trailing_slash();
273248
} else if (route.endpoint) {
274249
const node = await route.endpoint();
275-
trailing_slash = node.trailingSlash;
276-
250+
trailing_slash = node.trailingSlash ?? 'never';
277251
if (DEV) {
278252
validate_server_exports(node, /** @type {string} */ (route.endpoint_id));
279253
}
280254
}
281255

282256
if (!is_data_request) {
283-
const normalized = normalize_path(url.pathname, trailing_slash ?? 'never');
257+
const normalized = normalize_path(url.pathname, trailing_slash);
284258

285259
if (normalized !== url.pathname && !state.prerendering?.fallback) {
286260
return new Response(undefined, {
@@ -307,8 +281,8 @@ export async function respond(request, options, manifest, state) {
307281
config = node.config ?? config;
308282
prerender = node.prerender ?? prerender;
309283
} else if (page_nodes) {
310-
config = get_page_config(page_nodes) ?? config;
311-
prerender = get_option(page_nodes, 'prerender') ?? false;
284+
config = page_nodes.get_config() ?? config;
285+
prerender = page_nodes.prerender();
312286
}
313287

314288
if (state.before_handle) {
@@ -329,7 +303,7 @@ export async function respond(request, options, manifest, state) {
329303
const { cookies, new_cookies, get_cookie_header, set_internal } = get_cookies(
330304
request,
331305
url,
332-
trailing_slash ?? 'never'
306+
trailing_slash
333307
);
334308

335309
cookies_to_add = new_cookies;
@@ -425,7 +399,7 @@ export async function respond(request, options, manifest, state) {
425399

426400
/**
427401
* @param {import('@sveltejs/kit').RequestEvent} event
428-
* @param {Array<import('types').SSRNode | undefined> | undefined} page_nodes
402+
* @param {PageNodes | undefined} page_nodes
429403
* @param {import('@sveltejs/kit').ResolveOptions} [opts]
430404
*/
431405
async function resolve(event, page_nodes, opts) {
@@ -467,7 +441,7 @@ export async function respond(request, options, manifest, state) {
467441
manifest,
468442
state,
469443
invalidated_data_nodes,
470-
trailing_slash ?? 'never'
444+
trailing_slash
471445
);
472446
} else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
473447
response = await render_endpoint(event, await route.endpoint(), state);

packages/kit/src/utils/options.js

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

0 commit comments

Comments
 (0)