@sveltejs/kit 1.2.10 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/adapt/builder.js +6 -14
- package/src/core/adapt/index.js +4 -2
- package/src/core/config/options.js +5 -1
- package/src/core/generate_manifest/index.js +2 -2
- package/src/core/postbuild/analyse.js +135 -0
- package/src/core/postbuild/prerender.js +66 -55
- package/src/core/sync/sync.js +2 -4
- package/src/core/sync/ts.js +6 -0
- package/src/core/sync/write_client_manifest.js +54 -13
- package/src/core/sync/write_server.js +5 -4
- package/src/core/sync/write_tsconfig.js +44 -36
- package/src/core/sync/write_types/index.js +1 -7
- package/src/exports/vite/build/build_server.js +32 -94
- package/src/exports/vite/build/build_service_worker.js +16 -19
- package/src/exports/vite/index.js +158 -157
- package/src/runtime/client/ambient.d.ts +1 -1
- package/src/runtime/client/client.js +16 -5
- package/src/runtime/client/parse.js +1 -1
- package/src/runtime/server/ambient.d.ts +1 -1
- package/src/runtime/server/index.js +1 -1
- package/src/utils/filesystem.js +5 -0
- package/src/utils/fork.js +76 -0
- package/types/index.d.ts +8 -0
- package/types/internal.d.ts +20 -20
- package/src/core/postbuild/index.js +0 -113
- package/src/core/sync/write_matchers.js +0 -25
package/package.json
CHANGED
|
@@ -17,13 +17,14 @@ const pipe = promisify(pipeline);
|
|
|
17
17
|
* @param {{
|
|
18
18
|
* config: import('types').ValidatedConfig;
|
|
19
19
|
* build_data: import('types').BuildData;
|
|
20
|
+
* server_metadata: import('types').ServerMetadata;
|
|
20
21
|
* routes: import('types').RouteData[];
|
|
21
22
|
* prerendered: import('types').Prerendered;
|
|
22
23
|
* log: import('types').Logger;
|
|
23
24
|
* }} opts
|
|
24
25
|
* @returns {import('types').Builder}
|
|
25
26
|
*/
|
|
26
|
-
export function create_builder({ config, build_data, routes, prerendered, log }) {
|
|
27
|
+
export function create_builder({ config, build_data, server_metadata, routes, prerendered, log }) {
|
|
27
28
|
return {
|
|
28
29
|
log,
|
|
29
30
|
rimraf,
|
|
@@ -53,18 +54,9 @@ export function create_builder({ config, build_data, routes, prerendered, log })
|
|
|
53
54
|
async createEntries(fn) {
|
|
54
55
|
/** @type {import('types').RouteDefinition[]} */
|
|
55
56
|
const facades = routes.map((route) => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (route.page) {
|
|
60
|
-
methods.add('GET');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (route.endpoint) {
|
|
64
|
-
for (const method of build_data.server.methods[route.endpoint.file]) {
|
|
65
|
-
methods.add(method);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
57
|
+
const methods =
|
|
58
|
+
/** @type {import('types').HttpMethod[]} */
|
|
59
|
+
(server_metadata.routes.get(route.id)?.methods);
|
|
68
60
|
|
|
69
61
|
return {
|
|
70
62
|
id: route.id,
|
|
@@ -74,7 +66,7 @@ export function create_builder({ config, build_data, routes, prerendered, log })
|
|
|
74
66
|
content: segment
|
|
75
67
|
})),
|
|
76
68
|
pattern: route.pattern,
|
|
77
|
-
methods
|
|
69
|
+
methods
|
|
78
70
|
};
|
|
79
71
|
});
|
|
80
72
|
|
package/src/core/adapt/index.js
CHANGED
|
@@ -4,11 +4,12 @@ import { create_builder } from './builder.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* @param {import('types').ValidatedConfig} config
|
|
6
6
|
* @param {import('types').BuildData} build_data
|
|
7
|
+
* @param {import('types').ServerMetadata} server_metadata
|
|
7
8
|
* @param {import('types').Prerendered} prerendered
|
|
8
9
|
* @param {import('types').PrerenderMap} prerender_map
|
|
9
|
-
* @param {
|
|
10
|
+
* @param {import('types').Logger} log
|
|
10
11
|
*/
|
|
11
|
-
export async function adapt(config, build_data, prerendered, prerender_map,
|
|
12
|
+
export async function adapt(config, build_data, server_metadata, prerendered, prerender_map, log) {
|
|
12
13
|
const { name, adapt } = config.kit.adapter;
|
|
13
14
|
|
|
14
15
|
console.log(colors.bold().cyan(`\n> Using ${name}`));
|
|
@@ -16,6 +17,7 @@ export async function adapt(config, build_data, prerendered, prerender_map, { lo
|
|
|
16
17
|
const builder = create_builder({
|
|
17
18
|
config,
|
|
18
19
|
build_data,
|
|
20
|
+
server_metadata,
|
|
19
21
|
routes: build_data.manifest_data.routes.filter((route) => {
|
|
20
22
|
if (!route.page && !route.endpoint) return false;
|
|
21
23
|
|
|
@@ -226,6 +226,10 @@ const options = object(
|
|
|
226
226
|
files: fun((filename) => !/\.DS_Store/.test(filename))
|
|
227
227
|
}),
|
|
228
228
|
|
|
229
|
+
typescript: object({
|
|
230
|
+
config: fun((config) => config)
|
|
231
|
+
}),
|
|
232
|
+
|
|
229
233
|
version: object({
|
|
230
234
|
name: string(Date.now().toString()),
|
|
231
235
|
pollInterval: number(0)
|
|
@@ -362,7 +366,7 @@ function list(options, fallback = options[0]) {
|
|
|
362
366
|
}
|
|
363
367
|
|
|
364
368
|
/**
|
|
365
|
-
* @param {(
|
|
369
|
+
* @param {(...args: any) => any} fallback
|
|
366
370
|
* @returns {Validator}
|
|
367
371
|
*/
|
|
368
372
|
function fun(fallback) {
|
|
@@ -86,7 +86,7 @@ export function generate_manifest({ build_data, relative_path, routes }) {
|
|
|
86
86
|
assets: new Set(${s(assets)}),
|
|
87
87
|
mimeTypes: ${s(get_mime_lookup(build_data.manifest_data))},
|
|
88
88
|
_: {
|
|
89
|
-
entry: ${s(build_data.
|
|
89
|
+
entry: ${s(build_data.client_entry)},
|
|
90
90
|
nodes: [
|
|
91
91
|
${(node_paths).map(loader).join(',\n\t\t\t\t')}
|
|
92
92
|
],
|
|
@@ -103,7 +103,7 @@ export function generate_manifest({ build_data, relative_path, routes }) {
|
|
|
103
103
|
pattern: ${route.pattern},
|
|
104
104
|
params: ${s(route.params)},
|
|
105
105
|
page: ${route.page ? `{ layouts: ${get_nodes(route.page.layouts)}, errors: ${get_nodes(route.page.errors)}, leaf: ${reindexed.get(route.page.leaf)} }` : 'null'},
|
|
106
|
-
endpoint: ${route.endpoint ? loader(join_relative(relative_path, resolve_symlinks(build_data.
|
|
106
|
+
endpoint: ${route.endpoint ? loader(join_relative(relative_path, resolve_symlinks(build_data.server_manifest, route.endpoint.file).chunk.file)) : 'null'}
|
|
107
107
|
}`;
|
|
108
108
|
}).filter(Boolean).join(',\n\t\t\t\t')}
|
|
109
109
|
],
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { pathToFileURL } from 'url';
|
|
3
|
+
import { get_option } from '../../runtime/server/utils.js';
|
|
4
|
+
import {
|
|
5
|
+
validate_common_exports,
|
|
6
|
+
validate_page_server_exports,
|
|
7
|
+
validate_server_exports
|
|
8
|
+
} from '../../utils/exports.js';
|
|
9
|
+
import { load_config } from '../config/index.js';
|
|
10
|
+
import { forked } from '../../utils/fork.js';
|
|
11
|
+
import { should_polyfill } from '../../utils/platform.js';
|
|
12
|
+
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
13
|
+
|
|
14
|
+
export default forked(import.meta.url, analyse);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {{
|
|
18
|
+
* manifest_path: string;
|
|
19
|
+
* env: Record<string, string>
|
|
20
|
+
* }} opts
|
|
21
|
+
*/
|
|
22
|
+
async function analyse({ manifest_path, env }) {
|
|
23
|
+
/** @type {import('types').SSRManifest} */
|
|
24
|
+
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
|
|
25
|
+
|
|
26
|
+
/** @type {import('types').ValidatedKitConfig} */
|
|
27
|
+
const config = (await load_config()).kit;
|
|
28
|
+
|
|
29
|
+
const server_root = join(config.outDir, 'output');
|
|
30
|
+
|
|
31
|
+
/** @type {import('types').ServerInternalModule} */
|
|
32
|
+
const internal = await import(pathToFileURL(`${server_root}/server/internal.js`).href);
|
|
33
|
+
|
|
34
|
+
if (should_polyfill) {
|
|
35
|
+
installPolyfills();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// configure `import { building } from '$app/environment'` —
|
|
39
|
+
// essential we do this before analysing the code
|
|
40
|
+
internal.set_building(true);
|
|
41
|
+
|
|
42
|
+
// set env, in case it's used in initialisation
|
|
43
|
+
const entries = Object.entries(env);
|
|
44
|
+
const prefix = config.env.publicPrefix;
|
|
45
|
+
internal.set_private_env(Object.fromEntries(entries.filter(([k]) => !k.startsWith(prefix))));
|
|
46
|
+
internal.set_public_env(Object.fromEntries(entries.filter(([k]) => k.startsWith(prefix))));
|
|
47
|
+
|
|
48
|
+
/** @type {import('types').ServerMetadata} */
|
|
49
|
+
const metadata = {
|
|
50
|
+
nodes: [],
|
|
51
|
+
routes: new Map()
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// analyse nodes
|
|
55
|
+
for (const loader of manifest._.nodes) {
|
|
56
|
+
const node = await loader();
|
|
57
|
+
|
|
58
|
+
metadata.nodes.push({
|
|
59
|
+
has_server_load: node.server?.load !== undefined
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// analyse routes
|
|
64
|
+
for (const route of manifest._.routes) {
|
|
65
|
+
/** @type {Set<import('types').HttpMethod>} */
|
|
66
|
+
const methods = new Set();
|
|
67
|
+
|
|
68
|
+
/** @type {import('types').PrerenderOption | undefined} */
|
|
69
|
+
let prerender = undefined;
|
|
70
|
+
|
|
71
|
+
if (route.endpoint) {
|
|
72
|
+
const mod = await route.endpoint();
|
|
73
|
+
if (mod.prerender !== undefined) {
|
|
74
|
+
validate_server_exports(mod, route.id);
|
|
75
|
+
|
|
76
|
+
if (mod.prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Cannot prerender a +server file with POST, PATCH, PUT, or DELETE (${route.id})`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
prerender = mod.prerender;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (mod.GET) methods.add('GET');
|
|
86
|
+
if (mod.POST) methods.add('POST');
|
|
87
|
+
if (mod.PUT) methods.add('PUT');
|
|
88
|
+
if (mod.PATCH) methods.add('PATCH');
|
|
89
|
+
if (mod.DELETE) methods.add('DELETE');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (route.page) {
|
|
93
|
+
const nodes = await Promise.all(
|
|
94
|
+
[...route.page.layouts, route.page.leaf].map((n) => {
|
|
95
|
+
if (n !== undefined) return manifest._.nodes[n]();
|
|
96
|
+
})
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const layouts = nodes.slice(0, -1);
|
|
100
|
+
const page = nodes.at(-1);
|
|
101
|
+
|
|
102
|
+
for (const layout of layouts) {
|
|
103
|
+
if (layout) {
|
|
104
|
+
validate_common_exports(layout.server, route.id);
|
|
105
|
+
validate_common_exports(layout.universal, route.id);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (page) {
|
|
110
|
+
methods.add('GET');
|
|
111
|
+
if (page.server?.actions) methods.add('POST');
|
|
112
|
+
|
|
113
|
+
validate_page_server_exports(page.server, route.id);
|
|
114
|
+
validate_common_exports(page.universal, route.id);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const should_prerender = get_option(nodes, 'prerender');
|
|
118
|
+
prerender =
|
|
119
|
+
should_prerender === true ||
|
|
120
|
+
// Try prerendering if ssr is false and no server needed. Set it to 'auto' so that
|
|
121
|
+
// the route is not removed from the manifest, there could be a server load function.
|
|
122
|
+
// People can opt out of this behavior by explicitly setting prerender to false
|
|
123
|
+
(should_prerender !== false && get_option(nodes, 'ssr') === false && !page?.server?.actions
|
|
124
|
+
? 'auto'
|
|
125
|
+
: should_prerender ?? false);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
metadata.routes.set(route.id, {
|
|
129
|
+
prerender,
|
|
130
|
+
methods: Array.from(methods)
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return metadata;
|
|
135
|
+
}
|
|
@@ -1,68 +1,72 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
-
import { dirname, join } from 'path';
|
|
3
|
-
import {
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
5
5
|
import { mkdirp, posixify, walk } from '../../utils/filesystem.js';
|
|
6
6
|
import { should_polyfill } from '../../utils/platform.js';
|
|
7
7
|
import { is_root_relative, resolve } from '../../utils/url.js';
|
|
8
|
-
import { queue } from './queue.js';
|
|
9
|
-
import { crawl } from './crawl.js';
|
|
10
8
|
import { escape_html_attr } from '../../utils/escape.js';
|
|
11
9
|
import { logger } from '../utils.js';
|
|
12
10
|
import { load_config } from '../config/index.js';
|
|
13
11
|
import { get_route_segments } from '../../utils/routing.js';
|
|
12
|
+
import { queue } from './queue.js';
|
|
13
|
+
import { crawl } from './crawl.js';
|
|
14
|
+
import { forked } from '../../utils/fork.js';
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
* @template {{message: string}} T
|
|
17
|
-
* @template {Omit<T, 'message'>} K
|
|
18
|
-
* @param {import('types').Logger} log
|
|
19
|
-
* @param {'fail' | 'warn' | 'ignore' | ((details: T) => void)} input
|
|
20
|
-
* @param {(details: K) => string} format
|
|
21
|
-
* @returns {(details: K) => void}
|
|
22
|
-
*/
|
|
23
|
-
function normalise_error_handler(log, input, format) {
|
|
24
|
-
switch (input) {
|
|
25
|
-
case 'fail':
|
|
26
|
-
return (details) => {
|
|
27
|
-
throw new Error(format(details));
|
|
28
|
-
};
|
|
29
|
-
case 'warn':
|
|
30
|
-
return (details) => {
|
|
31
|
-
log.error(format(details));
|
|
32
|
-
};
|
|
33
|
-
case 'ignore':
|
|
34
|
-
return () => {};
|
|
35
|
-
default:
|
|
36
|
-
// @ts-expect-error TS thinks T might be of a different kind, but it's not
|
|
37
|
-
return (details) => input({ ...details, message: format(details) });
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const OK = 2;
|
|
42
|
-
const REDIRECT = 3;
|
|
16
|
+
export default forked(import.meta.url, prerender);
|
|
43
17
|
|
|
44
18
|
/**
|
|
45
|
-
*
|
|
46
19
|
* @param {{
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* verbose: string;
|
|
53
|
-
* env: Record<string, string>;
|
|
20
|
+
* out: string;
|
|
21
|
+
* manifest_path: string;
|
|
22
|
+
* metadata: import('types').ServerMetadata;
|
|
23
|
+
* verbose: boolean;
|
|
24
|
+
* env: Record<string, string>
|
|
54
25
|
* }} opts
|
|
55
|
-
* @returns
|
|
56
26
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
27
|
+
async function prerender({ out, manifest_path, metadata, verbose, env }) {
|
|
28
|
+
/** @type {import('types').SSRManifest} */
|
|
29
|
+
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
|
|
30
|
+
|
|
31
|
+
/** @type {import('types').ServerInternalModule} */
|
|
32
|
+
const internal = await import(pathToFileURL(`${out}/server/internal.js`).href);
|
|
33
|
+
|
|
34
|
+
/** @type {import('types').ServerModule} */
|
|
35
|
+
const { Server } = await import(pathToFileURL(`${out}/server/index.js`).href);
|
|
36
|
+
|
|
37
|
+
// configure `import { building } from '$app/environment'` —
|
|
38
|
+
// essential we do this before analysing the code
|
|
39
|
+
internal.set_building(true);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @template {{message: string}} T
|
|
43
|
+
* @template {Omit<T, 'message'>} K
|
|
44
|
+
* @param {import('types').Logger} log
|
|
45
|
+
* @param {'fail' | 'warn' | 'ignore' | ((details: T) => void)} input
|
|
46
|
+
* @param {(details: K) => string} format
|
|
47
|
+
* @returns {(details: K) => void}
|
|
48
|
+
*/
|
|
49
|
+
function normalise_error_handler(log, input, format) {
|
|
50
|
+
switch (input) {
|
|
51
|
+
case 'fail':
|
|
52
|
+
return (details) => {
|
|
53
|
+
throw new Error(format(details));
|
|
54
|
+
};
|
|
55
|
+
case 'warn':
|
|
56
|
+
return (details) => {
|
|
57
|
+
log.error(format(details));
|
|
58
|
+
};
|
|
59
|
+
case 'ignore':
|
|
60
|
+
return () => {};
|
|
61
|
+
default:
|
|
62
|
+
// @ts-expect-error TS thinks T might be of a different kind, but it's not
|
|
63
|
+
return (details) => input({ ...details, message: format(details) });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const OK = 2;
|
|
68
|
+
const REDIRECT = 3;
|
|
69
|
+
|
|
66
70
|
/** @type {import('types').Prerendered} */
|
|
67
71
|
const prerendered = {
|
|
68
72
|
pages: new Map(),
|
|
@@ -71,6 +75,15 @@ export async function prerender({
|
|
|
71
75
|
paths: []
|
|
72
76
|
};
|
|
73
77
|
|
|
78
|
+
/** @type {import('types').PrerenderMap} */
|
|
79
|
+
const prerender_map = new Map();
|
|
80
|
+
|
|
81
|
+
for (const [id, { prerender }] of metadata.routes) {
|
|
82
|
+
if (prerender !== undefined) {
|
|
83
|
+
prerender_map.set(id, prerender);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
74
87
|
/** @type {Set<string>} */
|
|
75
88
|
const prerendered_routes = new Set();
|
|
76
89
|
|
|
@@ -78,9 +91,7 @@ export async function prerender({
|
|
|
78
91
|
const config = (await load_config()).kit;
|
|
79
92
|
|
|
80
93
|
/** @type {import('types').Logger} */
|
|
81
|
-
const log = logger({
|
|
82
|
-
verbose: verbose === 'true'
|
|
83
|
-
});
|
|
94
|
+
const log = logger({ verbose });
|
|
84
95
|
|
|
85
96
|
if (should_polyfill) {
|
|
86
97
|
installPolyfills();
|
|
@@ -134,7 +145,7 @@ export async function prerender({
|
|
|
134
145
|
return file;
|
|
135
146
|
}
|
|
136
147
|
|
|
137
|
-
const files = new Set(walk(
|
|
148
|
+
const files = new Set(walk(`${out}/client`).map(posixify));
|
|
138
149
|
const seen = new Set();
|
|
139
150
|
const written = new Set();
|
|
140
151
|
|
package/src/core/sync/sync.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import create_manifest_data from './create_manifest_data/index.js';
|
|
3
3
|
import { write_client_manifest } from './write_client_manifest.js';
|
|
4
|
-
import { write_matchers } from './write_matchers.js';
|
|
5
4
|
import { write_root } from './write_root.js';
|
|
6
5
|
import { write_tsconfig } from './write_tsconfig.js';
|
|
7
6
|
import { write_types, write_all_types } from './write_types/index.js';
|
|
@@ -27,10 +26,9 @@ export async function create(config) {
|
|
|
27
26
|
|
|
28
27
|
const output = path.join(config.kit.outDir, 'generated');
|
|
29
28
|
|
|
30
|
-
write_client_manifest(config, manifest_data, output);
|
|
29
|
+
write_client_manifest(config.kit, manifest_data, `${output}/client`);
|
|
31
30
|
write_server(config, output);
|
|
32
31
|
write_root(manifest_data, output);
|
|
33
|
-
write_matchers(manifest_data, output);
|
|
34
32
|
await write_all_types(config, manifest_data);
|
|
35
33
|
|
|
36
34
|
return { manifest_data };
|
|
@@ -72,7 +70,7 @@ export async function all_types(config, mode) {
|
|
|
72
70
|
}
|
|
73
71
|
|
|
74
72
|
/**
|
|
75
|
-
* Regenerate
|
|
73
|
+
* Regenerate __SERVER__/internal.js in response to src/{app.html,error.html,service-worker.js} changing
|
|
76
74
|
* @param {import('types').ValidatedConfig} config
|
|
77
75
|
*/
|
|
78
76
|
export function server(config) {
|
|
@@ -5,11 +5,12 @@ import { trim, write_if_changed } from './utils.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* Writes the client manifest to disk. The manifest is used to power the router. It contains the
|
|
7
7
|
* list of routes and corresponding Svelte components (i.e. pages and layouts).
|
|
8
|
-
* @param {import('types').
|
|
8
|
+
* @param {import('types').ValidatedKitConfig} kit
|
|
9
9
|
* @param {import('types').ManifestData} manifest_data
|
|
10
10
|
* @param {string} output
|
|
11
|
+
* @param {Array<{ has_server_load: boolean }>} [metadata]
|
|
11
12
|
*/
|
|
12
|
-
export function write_client_manifest(
|
|
13
|
+
export function write_client_manifest(kit, manifest_data, output, metadata) {
|
|
13
14
|
/**
|
|
14
15
|
* Creates a module that exports a `CSRPageNode`
|
|
15
16
|
* @param {import('types').PageNode} node
|
|
@@ -32,15 +33,16 @@ export function write_client_manifest(config, manifest_data, output) {
|
|
|
32
33
|
);
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
if (node.server) {
|
|
36
|
-
declarations.push(`export const has_server_load = true;`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
36
|
return declarations.join('\n');
|
|
40
37
|
}
|
|
41
38
|
|
|
39
|
+
/** @type {Map<import('types').PageNode, number>} */
|
|
40
|
+
const indices = new Map();
|
|
41
|
+
|
|
42
42
|
const nodes = manifest_data.nodes
|
|
43
43
|
.map((node, i) => {
|
|
44
|
+
indices.set(node, i);
|
|
45
|
+
|
|
44
46
|
write_if_changed(`${output}/nodes/${i}.js`, generate_node(node));
|
|
45
47
|
return `() => import('./nodes/${i}')`;
|
|
46
48
|
})
|
|
@@ -58,14 +60,35 @@ export function write_client_manifest(config, manifest_data, output) {
|
|
|
58
60
|
while (layouts.at(-1) === '') layouts.pop();
|
|
59
61
|
while (errors.at(-1) === '') errors.pop();
|
|
60
62
|
|
|
63
|
+
let leaf_has_server_load = false;
|
|
64
|
+
if (route.leaf) {
|
|
65
|
+
if (metadata) {
|
|
66
|
+
const i = /** @type {number} */ (indices.get(route.leaf));
|
|
67
|
+
leaf_has_server_load = metadata[i].has_server_load;
|
|
68
|
+
} else if (route.leaf.server) {
|
|
69
|
+
leaf_has_server_load = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
// Encode whether or not the route uses server data
|
|
62
74
|
// using the ones' complement, to save space
|
|
63
|
-
const array = [`${
|
|
75
|
+
const array = [`${leaf_has_server_load ? '~' : ''}${route.page.leaf}`];
|
|
76
|
+
|
|
64
77
|
// Encode whether or not the layout uses server data.
|
|
65
78
|
// It's a different method compared to pages because layouts
|
|
66
|
-
// are reused across pages, so we
|
|
79
|
+
// are reused across pages, so we save space by doing it this way.
|
|
67
80
|
route.page.layouts.forEach((layout) => {
|
|
68
|
-
if (layout
|
|
81
|
+
if (layout == undefined) return;
|
|
82
|
+
|
|
83
|
+
let layout_has_server_load = false;
|
|
84
|
+
|
|
85
|
+
if (metadata) {
|
|
86
|
+
layout_has_server_load = metadata[layout].has_server_load;
|
|
87
|
+
} else if (manifest_data.nodes[layout].server) {
|
|
88
|
+
layout_has_server_load = true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (layout_has_server_load) {
|
|
69
92
|
layouts_with_server_load.add(layout);
|
|
70
93
|
}
|
|
71
94
|
});
|
|
@@ -81,15 +104,15 @@ export function write_client_manifest(config, manifest_data, output) {
|
|
|
81
104
|
.join(',\n\t\t')}
|
|
82
105
|
}`.replace(/^\t/gm, '');
|
|
83
106
|
|
|
84
|
-
const hooks_file = resolve_entry(
|
|
107
|
+
const hooks_file = resolve_entry(kit.files.hooks.client);
|
|
85
108
|
|
|
86
|
-
// String representation of
|
|
109
|
+
// String representation of __CLIENT__/manifest.js
|
|
87
110
|
write_if_changed(
|
|
88
|
-
`${output}/
|
|
111
|
+
`${output}/manifest.js`,
|
|
89
112
|
trim(`
|
|
90
113
|
${hooks_file ? `import * as client_hooks from '${relative_path(output, hooks_file)}';` : ''}
|
|
91
114
|
|
|
92
|
-
export { matchers } from './
|
|
115
|
+
export { matchers } from './matchers.js';
|
|
93
116
|
|
|
94
117
|
export const nodes = [${nodes}];
|
|
95
118
|
|
|
@@ -104,4 +127,22 @@ export function write_client_manifest(config, manifest_data, output) {
|
|
|
104
127
|
};
|
|
105
128
|
`)
|
|
106
129
|
);
|
|
130
|
+
|
|
131
|
+
// write matchers to a separate module so that we don't
|
|
132
|
+
// need to worry about name conflicts
|
|
133
|
+
const imports = [];
|
|
134
|
+
const matchers = [];
|
|
135
|
+
|
|
136
|
+
for (const key in manifest_data.matchers) {
|
|
137
|
+
const src = manifest_data.matchers[key];
|
|
138
|
+
|
|
139
|
+
imports.push(`import { match as ${key} } from ${s(relative_path(output, src))};`);
|
|
140
|
+
matchers.push(key);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const module = imports.length
|
|
144
|
+
? `${imports.join('\n')}\n\nexport const matchers = { ${matchers.join(', ')} };`
|
|
145
|
+
: 'export const matchers = {};';
|
|
146
|
+
|
|
147
|
+
write_if_changed(`${output}/matchers.js`, module);
|
|
107
148
|
}
|
|
@@ -4,6 +4,7 @@ import { posixify, resolve_entry } from '../../utils/filesystem.js';
|
|
|
4
4
|
import { s } from '../../utils/misc.js';
|
|
5
5
|
import { load_error_page, load_template } from '../config/index.js';
|
|
6
6
|
import { runtime_directory } from '../utils.js';
|
|
7
|
+
import { write_if_changed } from './utils.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @param {{
|
|
@@ -23,7 +24,7 @@ const server_template = ({
|
|
|
23
24
|
template,
|
|
24
25
|
error_page
|
|
25
26
|
}) => `
|
|
26
|
-
import root from '
|
|
27
|
+
import root from '../root.svelte';
|
|
27
28
|
import { set_building, set_paths, set_private_env, set_public_env, set_version } from '${runtime_directory}/shared.js';
|
|
28
29
|
|
|
29
30
|
set_paths(${s(config.kit.paths)});
|
|
@@ -75,11 +76,11 @@ export function write_server(config, output) {
|
|
|
75
76
|
|
|
76
77
|
/** @param {string} file */
|
|
77
78
|
function relative(file) {
|
|
78
|
-
return posixify(path.relative(output
|
|
79
|
+
return posixify(path.relative(`${output}/server`, file));
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
`${output}/server
|
|
82
|
+
write_if_changed(
|
|
83
|
+
`${output}/server/internal.js`,
|
|
83
84
|
server_template({
|
|
84
85
|
config,
|
|
85
86
|
hooks: fs.existsSync(hooks_file) ? relative(hooks_file) : null,
|