@sveltejs/kit 1.0.0-next.452 → 1.0.0-next.455
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 +5 -4
- package/scripts/special-types/$env+dynamic+private.md +8 -0
- package/scripts/special-types/$env+dynamic+public.md +8 -0
- package/scripts/special-types/$env+static+private.md +19 -0
- package/scripts/special-types/$env+static+public.md +7 -0
- package/scripts/special-types/$lib.md +1 -0
- package/src/core/adapt/builder.js +28 -44
- package/src/core/adapt/index.js +14 -2
- package/src/core/config/default-error.html +56 -0
- package/src/core/config/index.js +24 -5
- package/src/core/config/options.js +20 -10
- package/src/core/prerender/prerender.js +65 -20
- package/src/core/sync/write_types/index.js +1 -1
- package/src/exports/hooks/sequence.js +21 -3
- package/src/exports/vite/build/build_server.js +13 -12
- package/src/exports/vite/dev/index.js +9 -9
- package/src/exports/vite/index.js +10 -3
- package/src/runtime/client/client.js +42 -42
- package/src/runtime/client/start.js +15 -16
- package/src/runtime/server/endpoint.js +17 -1
- package/src/runtime/server/index.js +11 -13
- package/src/runtime/server/page/fetch.js +3 -1
- package/src/runtime/server/page/index.js +34 -43
- package/src/runtime/server/page/render.js +13 -16
- package/src/runtime/server/page/respond_with_error.js +7 -9
- package/src/runtime/server/utils.js +40 -0
- package/src/utils/routing.js +0 -9
- package/types/ambient.d.ts +16 -3
- package/types/index.d.ts +4 -6
- package/types/internal.d.ts +24 -16
- package/types/private.d.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.455",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"homepage": "https://kit.svelte.dev",
|
|
11
11
|
"type": "module",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@sveltejs/vite-plugin-svelte": "^1.0.
|
|
13
|
+
"@sveltejs/vite-plugin-svelte": "^1.0.3",
|
|
14
14
|
"cookie": "^0.5.0",
|
|
15
15
|
"devalue": "^3.1.2",
|
|
16
16
|
"kleur": "^4.1.4",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"rollup": "^2.78.1",
|
|
37
37
|
"svelte": "^3.48.0",
|
|
38
38
|
"svelte-preprocess": "^4.10.6",
|
|
39
|
-
"typescript": "^4.
|
|
39
|
+
"typescript": "^4.8.2",
|
|
40
40
|
"uvu": "^0.5.3",
|
|
41
41
|
"vite": "^3.1.0-beta.1"
|
|
42
42
|
},
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
"!src/core/**/fixtures",
|
|
54
54
|
"!src/core/**/test",
|
|
55
55
|
"types",
|
|
56
|
-
"svelte-kit.js"
|
|
56
|
+
"svelte-kit.js",
|
|
57
|
+
"scripts/special-types"
|
|
57
58
|
],
|
|
58
59
|
"exports": {
|
|
59
60
|
"./package.json": "./package.json",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
This module provides access to runtime environment variables, as defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/master/packages/adapter-node) (or running [`vite preview`](https://kit.svelte.dev/docs/cli)), this is equivalent to `process.env`. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#kit-env-publicprefix).
|
|
2
|
+
|
|
3
|
+
This module cannot be imported into client-side code.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { env } from '$env/dynamic/private';
|
|
7
|
+
console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE);
|
|
8
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Similar to [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private), but only includes variables that begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#kit-env-publicprefix) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code.
|
|
2
|
+
|
|
3
|
+
Note that public dynamic environment variables must all be sent from the server to the client, causing larger network requests — when possible, use `$env/static/public` instead.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { env } from '$env/dynamic/public';
|
|
7
|
+
console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE);
|
|
8
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Environment variables [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env`. Like [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private), this module cannot be imported into client-side code. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#kit-env-publicprefix).
|
|
2
|
+
|
|
3
|
+
_Unlike_ [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private), the values exported from this module are statically injected into your bundle at build time, enabling optimisations like dead code elimination.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { API_KEY } from '$env/static/private';
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Note that all environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
MY_FEATURE_FLAG=""
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
You can override `.env` values from the command line like so:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
MY_FEATURE_FLAG="enabled" npm run dev
|
|
19
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Similar to [`$env/static/private`](https://kit.svelte.dev/docs/modules#$env-static-private), except that it only includes environment variables that begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#kit-env-publicprefix) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code.
|
|
2
|
+
|
|
3
|
+
Values are replaced statically at build time.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { PUBLIC_BASE_URL } from '$env/static/public';
|
|
7
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This is a simple alias to `src/lib`, or whatever directory is specified as [`config.kit.files.lib`](https://kit.svelte.dev/docs/configuration#files). It allows you to access common components and utility modules without `../../../../` nonsense.
|
|
@@ -5,57 +5,21 @@ import { pipeline } from 'stream';
|
|
|
5
5
|
import { promisify } from 'util';
|
|
6
6
|
import { copy, rimraf, mkdirp } from '../../utils/filesystem.js';
|
|
7
7
|
import { generate_manifest } from '../generate_manifest/index.js';
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
const pipe = promisify(pipeline);
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Creates the Builder which is passed to adapters for building the application.
|
|
12
13
|
* @param {{
|
|
13
14
|
* config: import('types').ValidatedConfig;
|
|
14
15
|
* build_data: import('types').BuildData;
|
|
16
|
+
* routes: import('types').RouteData[];
|
|
15
17
|
* prerendered: import('types').Prerendered;
|
|
16
18
|
* log: import('types').Logger;
|
|
17
19
|
* }} opts
|
|
18
20
|
* @returns {import('types').Builder}
|
|
19
21
|
*/
|
|
20
|
-
export function create_builder({ config, build_data, prerendered, log }) {
|
|
21
|
-
/** @type {Set<string>} */
|
|
22
|
-
const prerendered_paths = new Set(prerendered.paths);
|
|
23
|
-
|
|
24
|
-
/** @param {import('types').RouteData} route */
|
|
25
|
-
// TODO routes should come pre-filtered
|
|
26
|
-
function not_prerendered(route) {
|
|
27
|
-
const path = route.page && get_path(route.id);
|
|
28
|
-
if (path) {
|
|
29
|
-
return !prerendered_paths.has(path) && !prerendered_paths.has(path + '/');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const pipe = promisify(pipeline);
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @param {string} file
|
|
39
|
-
* @param {'gz' | 'br'} format
|
|
40
|
-
*/
|
|
41
|
-
async function compress_file(file, format = 'gz') {
|
|
42
|
-
const compress =
|
|
43
|
-
format == 'br'
|
|
44
|
-
? zlib.createBrotliCompress({
|
|
45
|
-
params: {
|
|
46
|
-
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
|
|
47
|
-
[zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY,
|
|
48
|
-
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: statSync(file).size
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
: zlib.createGzip({ level: zlib.constants.Z_BEST_COMPRESSION });
|
|
52
|
-
|
|
53
|
-
const source = createReadStream(file);
|
|
54
|
-
const destination = createWriteStream(`${file}.${format}`);
|
|
55
|
-
|
|
56
|
-
await pipe(source, compress, destination);
|
|
57
|
-
}
|
|
58
|
-
|
|
22
|
+
export function create_builder({ config, build_data, routes, prerendered, log }) {
|
|
59
23
|
return {
|
|
60
24
|
log,
|
|
61
25
|
rimraf,
|
|
@@ -66,8 +30,6 @@ export function create_builder({ config, build_data, prerendered, log }) {
|
|
|
66
30
|
prerendered,
|
|
67
31
|
|
|
68
32
|
async createEntries(fn) {
|
|
69
|
-
const { routes } = build_data.manifest_data;
|
|
70
|
-
|
|
71
33
|
/** @type {import('types').RouteDefinition[]} */
|
|
72
34
|
const facades = routes.map((route) => {
|
|
73
35
|
const methods = new Set();
|
|
@@ -113,7 +75,7 @@ export function create_builder({ config, build_data, prerendered, log }) {
|
|
|
113
75
|
}
|
|
114
76
|
}
|
|
115
77
|
|
|
116
|
-
const filtered = new Set(group
|
|
78
|
+
const filtered = new Set(group);
|
|
117
79
|
|
|
118
80
|
// heuristic: if /foo/[bar] is included, /foo/[bar].json should
|
|
119
81
|
// also be included, since the page likely needs the endpoint
|
|
@@ -146,7 +108,7 @@ export function create_builder({ config, build_data, prerendered, log }) {
|
|
|
146
108
|
return generate_manifest({
|
|
147
109
|
build_data,
|
|
148
110
|
relative_path: relativePath,
|
|
149
|
-
routes
|
|
111
|
+
routes,
|
|
150
112
|
format
|
|
151
113
|
});
|
|
152
114
|
},
|
|
@@ -221,3 +183,25 @@ export function create_builder({ config, build_data, prerendered, log }) {
|
|
|
221
183
|
}
|
|
222
184
|
};
|
|
223
185
|
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @param {string} file
|
|
189
|
+
* @param {'gz' | 'br'} format
|
|
190
|
+
*/
|
|
191
|
+
async function compress_file(file, format = 'gz') {
|
|
192
|
+
const compress =
|
|
193
|
+
format == 'br'
|
|
194
|
+
? zlib.createBrotliCompress({
|
|
195
|
+
params: {
|
|
196
|
+
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
|
|
197
|
+
[zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY,
|
|
198
|
+
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: statSync(file).size
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
: zlib.createGzip({ level: zlib.constants.Z_BEST_COMPRESSION });
|
|
202
|
+
|
|
203
|
+
const source = createReadStream(file);
|
|
204
|
+
const destination = createWriteStream(`${file}.${format}`);
|
|
205
|
+
|
|
206
|
+
await pipe(source, compress, destination);
|
|
207
|
+
}
|
package/src/core/adapt/index.js
CHANGED
|
@@ -5,14 +5,26 @@ import { create_builder } from './builder.js';
|
|
|
5
5
|
* @param {import('types').ValidatedConfig} config
|
|
6
6
|
* @param {import('types').BuildData} build_data
|
|
7
7
|
* @param {import('types').Prerendered} prerendered
|
|
8
|
+
* @param {import('types').PrerenderMap} prerender_map
|
|
8
9
|
* @param {{ log: import('types').Logger }} opts
|
|
9
10
|
*/
|
|
10
|
-
export async function adapt(config, build_data, prerendered, { log }) {
|
|
11
|
+
export async function adapt(config, build_data, prerendered, prerender_map, { log }) {
|
|
11
12
|
const { name, adapt } = config.kit.adapter;
|
|
12
13
|
|
|
13
14
|
console.log(colors.bold().cyan(`\n> Using ${name}`));
|
|
14
15
|
|
|
15
|
-
const builder = create_builder({
|
|
16
|
+
const builder = create_builder({
|
|
17
|
+
config,
|
|
18
|
+
build_data,
|
|
19
|
+
routes: build_data.manifest_data.routes.filter((route) => {
|
|
20
|
+
if (!route.page && !route.endpoint) return false;
|
|
21
|
+
|
|
22
|
+
const prerender = prerender_map.get(route.id);
|
|
23
|
+
return prerender === false || prerender === undefined || prerender === 'auto';
|
|
24
|
+
}),
|
|
25
|
+
prerendered,
|
|
26
|
+
log
|
|
27
|
+
});
|
|
16
28
|
await adapt(builder);
|
|
17
29
|
|
|
18
30
|
log.success('done');
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>%sveltekit.message%</title>
|
|
6
|
+
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
|
10
|
+
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: center;
|
|
14
|
+
height: 100vh;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.error {
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
max-width: 32rem;
|
|
21
|
+
margin: 0 1rem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.status {
|
|
25
|
+
font-weight: 200;
|
|
26
|
+
font-size: 3rem;
|
|
27
|
+
line-height: 1;
|
|
28
|
+
position: relative;
|
|
29
|
+
top: -0.05rem;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.message {
|
|
33
|
+
border-left: 1px solid #ccc;
|
|
34
|
+
padding: 0 0 0 1rem;
|
|
35
|
+
margin: 0 0 0 1rem;
|
|
36
|
+
min-height: 2.5rem;
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.message h1 {
|
|
42
|
+
font-weight: 400;
|
|
43
|
+
font-size: 1em;
|
|
44
|
+
margin: 0;
|
|
45
|
+
}
|
|
46
|
+
</style>
|
|
47
|
+
</head>
|
|
48
|
+
<body>
|
|
49
|
+
<div class="error">
|
|
50
|
+
<span class="status">%sveltekit.status%</span>
|
|
51
|
+
<div class="message">
|
|
52
|
+
<h1>%sveltekit.message%</h1>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</body>
|
|
56
|
+
</html>
|
package/src/core/config/index.js
CHANGED
|
@@ -10,11 +10,11 @@ import options from './options.js';
|
|
|
10
10
|
* @param {import('types').ValidatedConfig} config
|
|
11
11
|
*/
|
|
12
12
|
export function load_template(cwd, config) {
|
|
13
|
-
const {
|
|
14
|
-
const relative = path.relative(cwd,
|
|
13
|
+
const { appTemplate } = config.kit.files;
|
|
14
|
+
const relative = path.relative(cwd, appTemplate);
|
|
15
15
|
|
|
16
|
-
if (fs.existsSync(
|
|
17
|
-
const contents = fs.readFileSync(
|
|
16
|
+
if (fs.existsSync(appTemplate)) {
|
|
17
|
+
const contents = fs.readFileSync(appTemplate, 'utf8');
|
|
18
18
|
|
|
19
19
|
// TODO remove this for 1.0
|
|
20
20
|
const match = /%svelte\.([a-z]+)%/.exec(contents);
|
|
@@ -34,7 +34,17 @@ export function load_template(cwd, config) {
|
|
|
34
34
|
throw new Error(`${relative} does not exist`);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
return fs.readFileSync(
|
|
37
|
+
return fs.readFileSync(appTemplate, 'utf-8');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Loads the error page (src/error.html by default) if it exists.
|
|
42
|
+
* Falls back to a generic error page content.
|
|
43
|
+
* @param {import('types').ValidatedConfig} config
|
|
44
|
+
*/
|
|
45
|
+
export function load_error_page(config) {
|
|
46
|
+
const { errorTemplate } = config.kit.files;
|
|
47
|
+
return fs.readFileSync(errorTemplate, 'utf-8');
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
/**
|
|
@@ -64,10 +74,19 @@ function process_config(config, { cwd = process.cwd() } = {}) {
|
|
|
64
74
|
validated.kit.outDir = path.resolve(cwd, validated.kit.outDir);
|
|
65
75
|
|
|
66
76
|
for (const key in validated.kit.files) {
|
|
77
|
+
// TODO remove for 1.0
|
|
78
|
+
if (key === 'template') continue;
|
|
79
|
+
|
|
67
80
|
// @ts-expect-error this is typescript at its stupidest
|
|
68
81
|
validated.kit.files[key] = path.resolve(cwd, validated.kit.files[key]);
|
|
69
82
|
}
|
|
70
83
|
|
|
84
|
+
if (!fs.existsSync(validated.kit.files.errorTemplate)) {
|
|
85
|
+
validated.kit.files.errorTemplate = url.fileURLToPath(
|
|
86
|
+
new URL('./default-error.html', import.meta.url)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
71
90
|
return validated;
|
|
72
91
|
}
|
|
73
92
|
|
|
@@ -107,14 +107,16 @@ const options = object(
|
|
|
107
107
|
return input;
|
|
108
108
|
}),
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
// TODO: remove this for the 1.0 release
|
|
111
|
+
browser: object({
|
|
112
|
+
hydrate: error(
|
|
113
|
+
(keypath) =>
|
|
114
|
+
`${keypath} has been removed. You can set it inside the top level +layout.js instead. See the PR for more information: https://github.com/sveltejs/kit/pull/6197`
|
|
115
|
+
),
|
|
116
|
+
router: error(
|
|
117
|
+
(keypath) =>
|
|
118
|
+
`${keypath} has been removed. You can set it inside the top level +layout.js instead. See the PR for more information: https://github.com/sveltejs/kit/pull/6197`
|
|
119
|
+
)
|
|
118
120
|
}),
|
|
119
121
|
|
|
120
122
|
csp: object({
|
|
@@ -140,7 +142,12 @@ const options = object(
|
|
|
140
142
|
params: string(join('src', 'params')),
|
|
141
143
|
routes: string(join('src', 'routes')),
|
|
142
144
|
serviceWorker: string(join('src', 'service-worker')),
|
|
143
|
-
|
|
145
|
+
appTemplate: string(join('src', 'app.html')),
|
|
146
|
+
errorTemplate: string(join('src', 'error.html')),
|
|
147
|
+
// TODO: remove this for the 1.0 release
|
|
148
|
+
template: error(
|
|
149
|
+
() => 'config.kit.files.template has been renamed to config.kit.files.appTemplate'
|
|
150
|
+
)
|
|
144
151
|
}),
|
|
145
152
|
|
|
146
153
|
// TODO: remove this for the 1.0 release
|
|
@@ -221,7 +228,10 @@ const options = object(
|
|
|
221
228
|
(keypath) =>
|
|
222
229
|
`${keypath} has been removed — it is now controlled by the trailingSlash option. See https://kit.svelte.dev/docs/configuration#trailingslash`
|
|
223
230
|
),
|
|
224
|
-
default:
|
|
231
|
+
default: error(
|
|
232
|
+
(keypath) =>
|
|
233
|
+
`${keypath} has been removed. You can set it inside the top level +layout.js instead. See the PR for more information: https://github.com/sveltejs/kit/pull/6197`
|
|
234
|
+
),
|
|
225
235
|
enabled: boolean(true),
|
|
226
236
|
entries: validate(['*'], (input, keypath) => {
|
|
227
237
|
if (!Array.isArray(input) || !input.every((page) => typeof page === 'string')) {
|
|
@@ -9,15 +9,15 @@ import { crawl } from './crawl.js';
|
|
|
9
9
|
import { escape_html_attr } from '../../utils/escape.js';
|
|
10
10
|
import { logger } from '../utils.js';
|
|
11
11
|
import { load_config } from '../config/index.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { affects_path } from '../../utils/routing.js';
|
|
13
|
+
import { get_option } from '../../runtime/server/utils.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* @typedef {import('types').PrerenderErrorHandler} PrerenderErrorHandler
|
|
17
17
|
* @typedef {import('types').Logger} Logger
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
const [, , client_out_dir, results_path,
|
|
20
|
+
const [, , client_out_dir, results_path, verbose, env] = process.argv;
|
|
21
21
|
|
|
22
22
|
prerender();
|
|
23
23
|
|
|
@@ -58,12 +58,15 @@ const OK = 2;
|
|
|
58
58
|
const REDIRECT = 3;
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
|
-
* @param {
|
|
61
|
+
* @param {{
|
|
62
|
+
* prerendered: import('types').Prerendered;
|
|
63
|
+
* prerender_map: import('types').PrerenderMap;
|
|
64
|
+
* }} data
|
|
62
65
|
*/
|
|
63
|
-
const output_and_exit = (
|
|
66
|
+
const output_and_exit = (data) => {
|
|
64
67
|
writeFileSync(
|
|
65
68
|
results_path,
|
|
66
|
-
JSON.stringify(
|
|
69
|
+
JSON.stringify(data, (_key, value) =>
|
|
67
70
|
value instanceof Map ? Array.from(value.entries()) : value
|
|
68
71
|
)
|
|
69
72
|
);
|
|
@@ -79,11 +82,14 @@ export async function prerender() {
|
|
|
79
82
|
paths: []
|
|
80
83
|
};
|
|
81
84
|
|
|
85
|
+
/** @type {import('types').PrerenderMap} */
|
|
86
|
+
const prerender_map = new Map();
|
|
87
|
+
|
|
82
88
|
/** @type {import('types').ValidatedKitConfig} */
|
|
83
89
|
const config = (await load_config()).kit;
|
|
84
90
|
|
|
85
91
|
if (!config.prerender.enabled) {
|
|
86
|
-
output_and_exit(prerendered);
|
|
92
|
+
output_and_exit({ prerendered, prerender_map });
|
|
87
93
|
return;
|
|
88
94
|
}
|
|
89
95
|
|
|
@@ -231,6 +237,16 @@ export async function prerender() {
|
|
|
231
237
|
const encoded_dependency_path = new URL(dependency_path, 'http://localhost').pathname;
|
|
232
238
|
const decoded_dependency_path = decodeURI(encoded_dependency_path);
|
|
233
239
|
|
|
240
|
+
const prerender = result.response.headers.get('x-sveltekit-prerender');
|
|
241
|
+
|
|
242
|
+
if (prerender) {
|
|
243
|
+
const route_id = /** @type {string} */ (result.response.headers.get('x-sveltekit-routeid'));
|
|
244
|
+
const existing_value = prerender_map.get(route_id);
|
|
245
|
+
if (existing_value !== 'auto') {
|
|
246
|
+
prerender_map.set(route_id, prerender === 'true' ? true : 'auto');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
234
250
|
const body = result.body ?? new Uint8Array(await result.response.arrayBuffer());
|
|
235
251
|
save(
|
|
236
252
|
'dependencies',
|
|
@@ -340,25 +356,54 @@ export async function prerender() {
|
|
|
340
356
|
}
|
|
341
357
|
}
|
|
342
358
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if (
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
359
|
+
for (const route of manifest._.routes) {
|
|
360
|
+
try {
|
|
361
|
+
if (route.endpoint) {
|
|
362
|
+
const mod = await route.endpoint();
|
|
363
|
+
if (mod.prerender !== undefined) {
|
|
364
|
+
if (mod.prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
`Cannot prerender a +server file with POST, PATCH, PUT, or DELETE (${route.id})`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
350
369
|
|
|
351
|
-
|
|
352
|
-
enqueue(null, config.paths.base + entry); // TODO can we pre-normalize these?
|
|
370
|
+
prerender_map.set(route.id, mod.prerender);
|
|
353
371
|
}
|
|
354
|
-
} else {
|
|
355
|
-
enqueue(null, config.paths.base + entry);
|
|
356
372
|
}
|
|
373
|
+
|
|
374
|
+
if (route.page) {
|
|
375
|
+
const nodes = await Promise.all(
|
|
376
|
+
[...route.page.layouts, route.page.leaf].map((n) => {
|
|
377
|
+
if (n !== undefined) return manifest._.nodes[n]();
|
|
378
|
+
})
|
|
379
|
+
);
|
|
380
|
+
const prerender = get_option(nodes, 'prerender') ?? false;
|
|
381
|
+
|
|
382
|
+
prerender_map.set(route.id, prerender);
|
|
383
|
+
}
|
|
384
|
+
} catch (e) {
|
|
385
|
+
// We failed to import the module, which indicates it can't be prerendered
|
|
386
|
+
// TODO should we catch these? It's almost certainly a bug in the app
|
|
387
|
+
console.error(e);
|
|
357
388
|
}
|
|
389
|
+
}
|
|
358
390
|
|
|
359
|
-
|
|
391
|
+
for (const entry of config.prerender.entries) {
|
|
392
|
+
if (entry === '*') {
|
|
393
|
+
for (const [id, prerender] of prerender_map) {
|
|
394
|
+
if (prerender) {
|
|
395
|
+
if (id.includes('[')) continue;
|
|
396
|
+
const path = `/${id.split('/').filter(affects_path).join('/')}`;
|
|
397
|
+
enqueue(null, config.paths.base + path);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
} else {
|
|
401
|
+
enqueue(null, config.paths.base + entry);
|
|
402
|
+
}
|
|
360
403
|
}
|
|
361
404
|
|
|
405
|
+
await q.done();
|
|
406
|
+
|
|
362
407
|
const rendered = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
|
|
363
408
|
getClientAddress,
|
|
364
409
|
prerendering: {
|
|
@@ -371,7 +416,7 @@ export async function prerender() {
|
|
|
371
416
|
mkdirp(dirname(file));
|
|
372
417
|
writeFileSync(file, await rendered.text());
|
|
373
418
|
|
|
374
|
-
output_and_exit(prerendered);
|
|
419
|
+
output_and_exit({ prerendered, prerender_map });
|
|
375
420
|
}
|
|
376
421
|
|
|
377
422
|
/** @return {string} */
|
|
@@ -181,7 +181,7 @@ function update_types(config, routes, route) {
|
|
|
181
181
|
`type OutputDataShape<T> = MaybeWithVoid<Omit<App.PageData, RequiredKeys<T>> & Partial<Pick<App.PageData, keyof T & keyof App.PageData>> & Record<string, any>>`
|
|
182
182
|
);
|
|
183
183
|
// null & {} == null, we need to prevent that in some situations
|
|
184
|
-
declarations.push(`type EnsureParentData<T> =
|
|
184
|
+
declarations.push(`type EnsureParentData<T> = T extends null | undefined ? {} : T;`);
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
if (route.leaf) {
|
|
@@ -7,19 +7,37 @@ export function sequence(...handlers) {
|
|
|
7
7
|
if (!length) return ({ event, resolve }) => resolve(event);
|
|
8
8
|
|
|
9
9
|
return ({ event, resolve }) => {
|
|
10
|
-
return apply_handle(0, event);
|
|
10
|
+
return apply_handle(0, event, {});
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {number} i
|
|
14
14
|
* @param {import('types').RequestEvent} event
|
|
15
|
+
* @param {import('types').ResolveOptions | undefined} parent_options
|
|
15
16
|
* @returns {import('types').MaybePromise<Response>}
|
|
16
17
|
*/
|
|
17
|
-
function apply_handle(i, event) {
|
|
18
|
+
function apply_handle(i, event, parent_options) {
|
|
18
19
|
const handle = handlers[i];
|
|
19
20
|
|
|
20
21
|
return handle({
|
|
21
22
|
event,
|
|
22
|
-
resolve:
|
|
23
|
+
resolve: (event, options) => {
|
|
24
|
+
/** @param {{ html: string, done: boolean }} opts */
|
|
25
|
+
const transformPageChunk = async ({ html, done }) => {
|
|
26
|
+
if (options?.transformPageChunk) {
|
|
27
|
+
html = (await options.transformPageChunk({ html, done })) ?? '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (parent_options?.transformPageChunk) {
|
|
31
|
+
html = (await parent_options.transformPageChunk({ html, done })) ?? '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return html;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return i < length - 1
|
|
38
|
+
? apply_handle(i + 1, event, { transformPageChunk })
|
|
39
|
+
: resolve(event, { transformPageChunk });
|
|
40
|
+
}
|
|
23
41
|
});
|
|
24
42
|
}
|
|
25
43
|
};
|
|
@@ -2,7 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { mkdirp, posixify } from '../../../utils/filesystem.js';
|
|
4
4
|
import { get_vite_config, merge_vite_configs, resolve_entry } from '../utils.js';
|
|
5
|
-
import { load_template } from '../../../core/config/index.js';
|
|
5
|
+
import { load_error_page, load_template } from '../../../core/config/index.js';
|
|
6
6
|
import { runtime_directory } from '../../../core/utils.js';
|
|
7
7
|
import { create_build, find_deps, get_default_build_config, is_http_method } from './utils.js';
|
|
8
8
|
import { s } from '../../../utils/misc.js';
|
|
@@ -14,9 +14,10 @@ import { s } from '../../../utils/misc.js';
|
|
|
14
14
|
* has_service_worker: boolean;
|
|
15
15
|
* runtime: string;
|
|
16
16
|
* template: string;
|
|
17
|
+
* error_page: string;
|
|
17
18
|
* }} opts
|
|
18
19
|
*/
|
|
19
|
-
const server_template = ({ config, hooks, has_service_worker, runtime, template }) => `
|
|
20
|
+
const server_template = ({ config, hooks, has_service_worker, runtime, template, error_page }) => `
|
|
20
21
|
import root from '__GENERATED__/root.svelte';
|
|
21
22
|
import { respond } from '${runtime}/server/index.js';
|
|
22
23
|
import { set_paths, assets, base } from '${runtime}/paths.js';
|
|
@@ -24,12 +25,16 @@ import { set_prerendering } from '${runtime}/env.js';
|
|
|
24
25
|
import { set_private_env } from '${runtime}/env-private.js';
|
|
25
26
|
import { set_public_env } from '${runtime}/env-public.js';
|
|
26
27
|
|
|
27
|
-
const
|
|
28
|
+
const app_template = ({ head, body, assets, nonce }) => ${s(template)
|
|
28
29
|
.replace('%sveltekit.head%', '" + head + "')
|
|
29
30
|
.replace('%sveltekit.body%', '" + body + "')
|
|
30
31
|
.replace(/%sveltekit\.assets%/g, '" + assets + "')
|
|
31
32
|
.replace(/%sveltekit\.nonce%/g, '" + nonce + "')};
|
|
32
33
|
|
|
34
|
+
const error_template = ({ status, message }) => ${s(error_page)
|
|
35
|
+
.replace(/%sveltekit\.status%/g, '" + status + "')
|
|
36
|
+
.replace(/%sveltekit\.message%/g, '" + message + "')};
|
|
37
|
+
|
|
33
38
|
let read = null;
|
|
34
39
|
|
|
35
40
|
set_paths(${s(config.kit.paths)});
|
|
@@ -65,21 +70,16 @@ export class Server {
|
|
|
65
70
|
error.stack = this.options.get_stack(error);
|
|
66
71
|
},
|
|
67
72
|
hooks: null,
|
|
68
|
-
hydrate: ${s(config.kit.browser.hydrate)},
|
|
69
73
|
manifest,
|
|
70
74
|
method_override: ${s(config.kit.methodOverride)},
|
|
71
75
|
paths: { base, assets },
|
|
72
|
-
prerender: {
|
|
73
|
-
default: ${config.kit.prerender.default},
|
|
74
|
-
enabled: ${config.kit.prerender.enabled}
|
|
75
|
-
},
|
|
76
76
|
public_env: {},
|
|
77
77
|
read,
|
|
78
78
|
root,
|
|
79
79
|
service_worker: ${has_service_worker ? "base + '/service-worker.js'" : 'null'},
|
|
80
|
-
|
|
81
|
-
template,
|
|
82
|
-
|
|
80
|
+
app_template,
|
|
81
|
+
app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
|
|
82
|
+
error_template,
|
|
83
83
|
trailing_slash: ${s(config.kit.trailingSlash)}
|
|
84
84
|
};
|
|
85
85
|
}
|
|
@@ -205,7 +205,8 @@ export async function build_server(options, client) {
|
|
|
205
205
|
hooks: app_relative(hooks_file),
|
|
206
206
|
has_service_worker: config.kit.serviceWorker.register && !!service_worker_entry_file,
|
|
207
207
|
runtime: posixify(path.relative(build_dir, runtime_directory)),
|
|
208
|
-
template: load_template(cwd, config)
|
|
208
|
+
template: load_template(cwd, config),
|
|
209
|
+
error_page: load_error_page(config)
|
|
209
210
|
})
|
|
210
211
|
);
|
|
211
212
|
|