@sveltejs/kit 1.0.0-next.393 → 1.0.0-next.394

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/dist/vite.js CHANGED
@@ -1,16 +1,23 @@
1
- import * as fs from 'fs';
2
- import fs__default, { readFileSync, existsSync, writeFileSync, readdirSync, statSync } from 'fs';
3
- import path__default, { join, dirname, resolve as resolve$1, normalize } from 'path';
4
- import { a as load_template, $, c as coalesce_to_error, l as load_config } from './chunks/error.js';
1
+ import { fork } from 'node:child_process';
2
+ import fs$1 from 'node:fs';
3
+ import path from 'node:path';
4
+ import { a as load_template, $, l as load_config } from './chunks/index.js';
5
5
  import { svelte } from '@sveltejs/vite-plugin-svelte';
6
6
  import * as vite from 'vite';
7
7
  import { loadConfigFromFile } from 'vite';
8
- import { p as posixify, m as mkdirp, w as walk, r as rimraf } from './chunks/write_tsconfig.js';
9
- import { g as get_runtime_directory, s, i as init, a as get_runtime_prefix, u as update, b as get_mime_lookup, p as parse_route_id, c as all, l as logger } from './chunks/sync.js';
10
- import { URL as URL$1, pathToFileURL } from 'url';
11
- import { installPolyfills } from './node/polyfills.js';
8
+ import { p as posixify, m as mkdirp, r as rimraf } from './chunks/filesystem.js';
9
+ import { s, i as init, u as update, p as parse_route_id, a as all } from './chunks/sync.js';
10
+ import * as fs from 'fs';
11
+ import fs__default, { readdirSync, statSync } from 'fs';
12
+ import path__default, { resolve, join, normalize } from 'path';
13
+ import { g as get_runtime_directory, a as get_runtime_prefix, b as get_mime_lookup, l as logger } from './chunks/utils.js';
12
14
  import * as qs from 'querystring';
15
+ import { URL as URL$1, pathToFileURL } from 'url';
13
16
  import { getRequest, setResponse } from './node.js';
17
+ import { installPolyfills } from './node/polyfills.js';
18
+ import { c as coalesce_to_error } from './chunks/error.js';
19
+ import { fileURLToPath } from 'node:url';
20
+ import './chunks/write_tsconfig.js';
14
21
  import 'assert';
15
22
  import 'net';
16
23
  import 'http';
@@ -31,10 +38,7 @@ import 'node:zlib';
31
38
  import 'node:stream';
32
39
  import 'node:buffer';
33
40
  import 'node:util';
34
- import 'node:url';
35
41
  import 'node:net';
36
- import 'node:fs';
37
- import 'node:path';
38
42
  import 'crypto';
39
43
 
40
44
  /**
@@ -291,9 +295,7 @@ const get_default_config = function ({ config, input, ssr, outDir }) {
291
295
  __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: JSON.stringify(config.kit.version.pollInterval),
292
296
  __SVELTEKIT_DEV__: 'false'
293
297
  },
294
- // prevent Vite copying the contents of `config.kit.files.assets`,
295
- // if it happens to be 'public' instead of 'static'
296
- publicDir: false,
298
+ publicDir: ssr ? false : config.kit.files.assets,
297
299
  resolve: {
298
300
  alias: get_aliases(config.kit)
299
301
  },
@@ -708,747 +710,8 @@ async function build_service_worker(
708
710
  await vite.build(merged_config);
709
711
  }
710
712
 
711
- const absolute = /^([a-z]+:)?\/?\//;
712
- const scheme = /^[a-z]+:/;
713
-
714
- /**
715
- * @param {string} base
716
- * @param {string} path
717
- */
718
- function resolve(base, path) {
719
- if (scheme.test(path)) return path;
720
-
721
- const base_match = absolute.exec(base);
722
- const path_match = absolute.exec(path);
723
-
724
- if (!base_match) {
725
- throw new Error(`bad base path: "${base}"`);
726
- }
727
-
728
- const baseparts = path_match ? [] : base.slice(base_match[0].length).split('/');
729
- const pathparts = path_match ? path.slice(path_match[0].length).split('/') : path.split('/');
730
-
731
- baseparts.pop();
732
-
733
- for (let i = 0; i < pathparts.length; i += 1) {
734
- const part = pathparts[i];
735
- if (part === '.') continue;
736
- else if (part === '..') baseparts.pop();
737
- else baseparts.push(part);
738
- }
739
-
740
- const prefix = (path_match && path_match[0]) || (base_match && base_match[0]) || '';
741
-
742
- return `${prefix}${baseparts.join('/')}`;
743
- }
744
-
745
- /** @param {string} path */
746
- function is_root_relative(path) {
747
- return path[0] === '/' && path[1] !== '/';
748
- }
749
-
750
- /**
751
- * @typedef {{
752
- * fn: () => Promise<any>,
753
- * fulfil: (value: any) => void,
754
- * reject: (error: Error) => void
755
- * }} Task
756
- */
757
-
758
- /** @param {number} concurrency */
759
- function queue(concurrency) {
760
- /** @type {Task[]} */
761
- const tasks = [];
762
-
763
- let current = 0;
764
-
765
- /** @type {(value?: any) => void} */
766
- let fulfil;
767
-
768
- /** @type {(error: Error) => void} */
769
- let reject;
770
-
771
- let closed = false;
772
-
773
- const done = new Promise((f, r) => {
774
- fulfil = f;
775
- reject = r;
776
- });
777
-
778
- done.catch(() => {
779
- // this is necessary in case a catch handler is never added
780
- // to the done promise by the user
781
- });
782
-
783
- function dequeue() {
784
- if (current < concurrency) {
785
- const task = tasks.shift();
786
-
787
- if (task) {
788
- current += 1;
789
- const promise = Promise.resolve(task.fn());
790
-
791
- promise
792
- .then(task.fulfil, (err) => {
793
- task.reject(err);
794
- reject(err);
795
- })
796
- .then(() => {
797
- current -= 1;
798
- dequeue();
799
- });
800
- } else if (current === 0) {
801
- closed = true;
802
- fulfil();
803
- }
804
- }
805
- }
806
-
807
- return {
808
- /** @param {() => any} fn */
809
- add: (fn) => {
810
- if (closed) throw new Error('Cannot add tasks to a queue that has ended');
811
-
812
- const promise = new Promise((fulfil, reject) => {
813
- tasks.push({ fn, fulfil, reject });
814
- });
815
-
816
- dequeue();
817
- return promise;
818
- },
819
-
820
- done: () => {
821
- if (current === 0) {
822
- closed = true;
823
- fulfil();
824
- }
825
-
826
- return done;
827
- }
828
- };
829
- }
830
-
831
- const DOCTYPE = 'DOCTYPE';
832
- const CDATA_OPEN = '[CDATA[';
833
- const CDATA_CLOSE = ']]>';
834
- const COMMENT_OPEN = '--';
835
- const COMMENT_CLOSE = '-->';
836
-
837
- const TAG_OPEN = /[a-zA-Z]/;
838
- const TAG_CHAR = /[a-zA-Z0-9]/;
839
- const ATTRIBUTE_NAME = /[^\t\n\f />"'=]/;
840
-
841
- const WHITESPACE = /[\s\n\r]/;
842
-
843
- /** @param {string} html */
844
- function crawl(html) {
845
- /** @type {string[]} */
846
- const hrefs = [];
847
-
848
- let i = 0;
849
- main: while (i < html.length) {
850
- const char = html[i];
851
-
852
- if (char === '<') {
853
- if (html[i + 1] === '!') {
854
- i += 2;
855
-
856
- if (html.slice(i, i + DOCTYPE.length).toUpperCase() === DOCTYPE) {
857
- i += DOCTYPE.length;
858
- while (i < html.length) {
859
- if (html[i++] === '>') {
860
- continue main;
861
- }
862
- }
863
- }
864
-
865
- // skip cdata
866
- if (html.slice(i, i + CDATA_OPEN.length) === CDATA_OPEN) {
867
- i += CDATA_OPEN.length;
868
- while (i < html.length) {
869
- if (html.slice(i, i + CDATA_CLOSE.length) === CDATA_CLOSE) {
870
- i += CDATA_CLOSE.length;
871
- continue main;
872
- }
873
-
874
- i += 1;
875
- }
876
- }
877
-
878
- // skip comments
879
- if (html.slice(i, i + COMMENT_OPEN.length) === COMMENT_OPEN) {
880
- i += COMMENT_OPEN.length;
881
- while (i < html.length) {
882
- if (html.slice(i, i + COMMENT_CLOSE.length) === COMMENT_CLOSE) {
883
- i += COMMENT_CLOSE.length;
884
- continue main;
885
- }
886
-
887
- i += 1;
888
- }
889
- }
890
- }
891
-
892
- // parse opening tags
893
- const start = ++i;
894
- if (TAG_OPEN.test(html[start])) {
895
- while (i < html.length) {
896
- if (!TAG_CHAR.test(html[i])) {
897
- break;
898
- }
899
-
900
- i += 1;
901
- }
902
-
903
- const tag = html.slice(start, i).toUpperCase();
904
-
905
- if (tag === 'SCRIPT' || tag === 'STYLE') {
906
- while (i < html.length) {
907
- if (
908
- html[i] === '<' &&
909
- html[i + 1] === '/' &&
910
- html.slice(i + 2, i + 2 + tag.length).toUpperCase() === tag
911
- ) {
912
- continue main;
913
- }
914
-
915
- i += 1;
916
- }
917
- }
918
-
919
- let href = '';
920
- let rel = '';
921
-
922
- while (i < html.length) {
923
- const start = i;
924
-
925
- const char = html[start];
926
- if (char === '>') break;
927
-
928
- if (ATTRIBUTE_NAME.test(char)) {
929
- i += 1;
930
-
931
- while (i < html.length) {
932
- if (!ATTRIBUTE_NAME.test(html[i])) {
933
- break;
934
- }
935
-
936
- i += 1;
937
- }
938
-
939
- const name = html.slice(start, i).toLowerCase();
940
-
941
- while (WHITESPACE.test(html[i])) i += 1;
942
-
943
- if (html[i] === '=') {
944
- i += 1;
945
- while (WHITESPACE.test(html[i])) i += 1;
946
-
947
- let value;
948
-
949
- if (html[i] === "'" || html[i] === '"') {
950
- const quote = html[i++];
951
-
952
- const start = i;
953
- let escaped = false;
954
-
955
- while (i < html.length) {
956
- if (!escaped) {
957
- const char = html[i];
958
-
959
- if (html[i] === quote) {
960
- break;
961
- }
962
-
963
- if (char === '\\') {
964
- escaped = true;
965
- }
966
- }
967
-
968
- i += 1;
969
- }
970
-
971
- value = html.slice(start, i);
972
- } else {
973
- const start = i;
974
- while (html[i] !== '>' && !WHITESPACE.test(html[i])) i += 1;
975
- value = html.slice(start, i);
976
-
977
- i -= 1;
978
- }
979
-
980
- if (name === 'href') {
981
- href = value;
982
- } else if (name === 'rel') {
983
- rel = value;
984
- } else if (name === 'src') {
985
- hrefs.push(value);
986
- } else if (name === 'srcset') {
987
- const candidates = [];
988
- let insideURL = true;
989
- value = value.trim();
990
- for (let i = 0; i < value.length; i++) {
991
- if (value[i] === ',' && (!insideURL || (insideURL && value[i + 1] === ' '))) {
992
- candidates.push(value.slice(0, i));
993
- value = value.substring(i + 1).trim();
994
- i = 0;
995
- insideURL = true;
996
- } else if (value[i] === ' ') {
997
- insideURL = false;
998
- }
999
- }
1000
- candidates.push(value);
1001
- for (const candidate of candidates) {
1002
- const src = candidate.split(WHITESPACE)[0];
1003
- hrefs.push(src);
1004
- }
1005
- }
1006
- } else {
1007
- i -= 1;
1008
- }
1009
- }
1010
-
1011
- i += 1;
1012
- }
1013
-
1014
- if (href && !/\bexternal\b/i.test(rel)) {
1015
- hrefs.push(href);
1016
- }
1017
- }
1018
- }
1019
-
1020
- i += 1;
1021
- }
1022
-
1023
- return hrefs;
1024
- }
1025
-
1026
- /**
1027
- * Inside a script element, only `</script` and `<!--` hold special meaning to the HTML parser.
1028
- *
1029
- * The first closes the script element, so everything after is treated as raw HTML.
1030
- * The second disables further parsing until `-->`, so the script element might be unexpectedly
1031
- * kept open until until an unrelated HTML comment in the page.
1032
- *
1033
- * U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR are escaped for the sake of pre-2018
1034
- * browsers.
1035
- *
1036
- * @see tests for unsafe parsing examples.
1037
- * @see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
1038
- * @see https://html.spec.whatwg.org/multipage/syntax.html#cdata-rcdata-restrictions
1039
- * @see https://html.spec.whatwg.org/multipage/parsing.html#script-data-state
1040
- * @see https://html.spec.whatwg.org/multipage/parsing.html#script-data-double-escaped-state
1041
- * @see https://github.com/tc39/proposal-json-superset
1042
- * @type {Record<string, string>}
1043
- */
1044
- const render_json_payload_script_dict = {
1045
- '<': '\\u003C',
1046
- '\u2028': '\\u2028',
1047
- '\u2029': '\\u2029'
1048
- };
1049
-
1050
- new RegExp(
1051
- `[${Object.keys(render_json_payload_script_dict).join('')}]`,
1052
- 'g'
1053
- );
1054
-
1055
- /**
1056
- * When inside a double-quoted attribute value, only `&` and `"` hold special meaning.
1057
- * @see https://html.spec.whatwg.org/multipage/parsing.html#attribute-value-(double-quoted)-state
1058
- * @type {Record<string, string>}
1059
- */
1060
- const escape_html_attr_dict = {
1061
- '&': '&amp;',
1062
- '"': '&quot;'
1063
- };
1064
-
1065
- const escape_html_attr_regex = new RegExp(
1066
- // special characters
1067
- `[${Object.keys(escape_html_attr_dict).join('')}]|` +
1068
- // high surrogate without paired low surrogate
1069
- '[\\ud800-\\udbff](?![\\udc00-\\udfff])|' +
1070
- // a valid surrogate pair, the only match with 2 code units
1071
- // we match it so that we can match unpaired low surrogates in the same pass
1072
- // TODO: use lookbehind assertions once they are widely supported: (?<![\ud800-udbff])[\udc00-\udfff]
1073
- '[\\ud800-\\udbff][\\udc00-\\udfff]|' +
1074
- // unpaired low surrogate (see previous match)
1075
- '[\\udc00-\\udfff]',
1076
- 'g'
1077
- );
1078
-
1079
- /**
1080
- * Formats a string to be used as an attribute's value in raw HTML.
1081
- *
1082
- * It escapes unpaired surrogates (which are allowed in js strings but invalid in HTML), escapes
1083
- * characters that are special in attributes, and surrounds the whole string in double-quotes.
1084
- *
1085
- * @param {string} str
1086
- * @returns {string} Escaped string surrounded by double-quotes.
1087
- * @example const html = `<tag data-value=${escape_html_attr('value')}>...</tag>`;
1088
- */
1089
- function escape_html_attr(str) {
1090
- const escaped_str = str.replace(escape_html_attr_regex, (match) => {
1091
- if (match.length === 2) {
1092
- // valid surrogate pair
1093
- return match;
1094
- }
1095
-
1096
- return escape_html_attr_dict[match] ?? `&#${match.charCodeAt(0)};`;
1097
- });
1098
-
1099
- return `"${escaped_str}"`;
1100
- }
1101
-
1102
- /**
1103
- * @typedef {import('types').PrerenderErrorHandler} PrerenderErrorHandler
1104
- * @typedef {import('types').Logger} Logger
1105
- */
1106
-
1107
- /**
1108
- * @param {Parameters<PrerenderErrorHandler>[0]} details
1109
- * @param {import('types').ValidatedKitConfig} config
1110
- */
1111
- function format_error({ status, path, referrer, referenceType }, config) {
1112
- const message =
1113
- status === 404 && !path.startsWith(config.paths.base)
1114
- ? `${path} does not begin with \`base\`, which is configured in \`paths.base\` and can be imported from \`$app/paths\``
1115
- : path;
1116
-
1117
- return `${status} ${message}${referrer ? ` (${referenceType} from ${referrer})` : ''}`;
1118
- }
1119
-
1120
- /**
1121
- * @param {Logger} log
1122
- * @param {import('types').ValidatedKitConfig} config
1123
- * @returns {PrerenderErrorHandler}
1124
- */
1125
- function normalise_error_handler(log, config) {
1126
- switch (config.prerender.onError) {
1127
- case 'continue':
1128
- return (details) => {
1129
- log.error(format_error(details, config));
1130
- };
1131
- case 'fail':
1132
- return (details) => {
1133
- throw new Error(format_error(details, config));
1134
- };
1135
- default:
1136
- return config.prerender.onError;
1137
- }
1138
- }
1139
-
1140
- const OK = 2;
1141
- const REDIRECT = 3;
1142
-
1143
- /**
1144
- * @param {{
1145
- * config: import('types').ValidatedKitConfig;
1146
- * client_out_dir: string;
1147
- * manifest_path: string;
1148
- * log: Logger;
1149
- * }} opts
1150
- */
1151
- async function prerender({ config, client_out_dir, manifest_path, log }) {
1152
- /** @type {import('types').Prerendered} */
1153
- const prerendered = {
1154
- pages: new Map(),
1155
- assets: new Map(),
1156
- redirects: new Map(),
1157
- paths: []
1158
- };
1159
-
1160
- if (!config.prerender.enabled) {
1161
- return prerendered;
1162
- }
1163
-
1164
- installPolyfills();
1165
- const { fetch } = globalThis;
1166
- globalThis.fetch = async (info, init) => {
1167
- /** @type {string} */
1168
- let url;
1169
-
1170
- /** @type {RequestInit} */
1171
- let opts = {};
1172
-
1173
- if (info instanceof Request) {
1174
- url = info.url;
1175
-
1176
- opts = {
1177
- method: info.method,
1178
- headers: info.headers,
1179
- body: info.body,
1180
- mode: info.mode,
1181
- credentials: info.credentials,
1182
- cache: info.cache,
1183
- redirect: info.redirect,
1184
- referrer: info.referrer,
1185
- integrity: info.integrity
1186
- };
1187
- } else {
1188
- url = info.toString();
1189
- }
1190
-
1191
- if (url.startsWith(config.prerender.origin + '/')) {
1192
- const request = new Request(url, opts);
1193
- const response = await server.respond(request, {
1194
- getClientAddress,
1195
- prerendering: {
1196
- dependencies: new Map()
1197
- }
1198
- });
1199
-
1200
- const decoded = new URL$1(url).pathname;
1201
-
1202
- save(
1203
- 'dependencies',
1204
- response,
1205
- Buffer.from(await response.clone().arrayBuffer()),
1206
- decoded,
1207
- encodeURI(decoded),
1208
- null,
1209
- 'fetched'
1210
- );
1211
-
1212
- return response;
1213
- }
1214
-
1215
- return fetch(info, init);
1216
- };
1217
-
1218
- const server_root = join(config.outDir, 'output');
1219
-
1220
- /** @type {import('types').ServerModule} */
1221
- const { Server, override } = await import(pathToFileURL(`${server_root}/server/index.js`).href);
1222
-
1223
- /** @type {import('types').SSRManifest} */
1224
- const manifest = (await import(pathToFileURL(`${server_root}/server/manifest.js`).href)).manifest;
1225
-
1226
- override({
1227
- paths: config.paths,
1228
- prerendering: true,
1229
- read: (file) => readFileSync(join(config.files.assets, file))
1230
- });
1231
-
1232
- const server = new Server(manifest);
1233
-
1234
- const error = normalise_error_handler(log, config);
1235
-
1236
- const q = queue(config.prerender.concurrency);
1237
-
1238
- /**
1239
- * @param {string} path
1240
- * @param {boolean} is_html
1241
- */
1242
- function output_filename(path, is_html) {
1243
- const file = path.slice(config.paths.base.length + 1) || 'index.html';
1244
-
1245
- if (is_html && !file.endsWith('.html')) {
1246
- return file + (file.endsWith('/') ? 'index.html' : '.html');
1247
- }
1248
-
1249
- return file;
1250
- }
1251
-
1252
- const files = new Set([
1253
- ...walk(client_out_dir).map(posixify),
1254
- ...(existsSync(config.files.assets) ? walk(config.files.assets).map(posixify) : []) // TODO remove this if we use Vite publicDir option
1255
- ]);
1256
- const seen = new Set();
1257
- const written = new Set();
1258
-
1259
- /**
1260
- * @param {string | null} referrer
1261
- * @param {string} decoded
1262
- * @param {string} [encoded]
1263
- */
1264
- function enqueue(referrer, decoded, encoded) {
1265
- if (seen.has(decoded)) return;
1266
- seen.add(decoded);
1267
-
1268
- const file = decoded.slice(config.paths.base.length + 1);
1269
- if (files.has(file)) return;
1270
-
1271
- return q.add(() => visit(decoded, encoded || encodeURI(decoded), referrer));
1272
- }
1273
-
1274
- /**
1275
- * @param {string} decoded
1276
- * @param {string} encoded
1277
- * @param {string?} referrer
1278
- */
1279
- async function visit(decoded, encoded, referrer) {
1280
- if (!decoded.startsWith(config.paths.base)) {
1281
- error({ status: 404, path: decoded, referrer, referenceType: 'linked' });
1282
- return;
1283
- }
1284
-
1285
- /** @type {Map<string, import('types').PrerenderDependency>} */
1286
- const dependencies = new Map();
1287
-
1288
- const response = await server.respond(new Request(config.prerender.origin + encoded), {
1289
- getClientAddress,
1290
- prerendering: {
1291
- dependencies
1292
- }
1293
- });
1294
-
1295
- const body = Buffer.from(await response.arrayBuffer());
1296
-
1297
- save('pages', response, body, decoded, encoded, referrer, 'linked');
1298
-
1299
- for (const [dependency_path, result] of dependencies) {
1300
- // this seems circuitous, but using new URL allows us to not care
1301
- // whether dependency_path is encoded or not
1302
- const encoded_dependency_path = new URL$1(dependency_path, 'http://localhost').pathname;
1303
- const decoded_dependency_path = decodeURI(encoded_dependency_path);
1304
-
1305
- const body = result.body ?? new Uint8Array(await result.response.arrayBuffer());
1306
- save(
1307
- 'dependencies',
1308
- result.response,
1309
- body,
1310
- decoded_dependency_path,
1311
- encoded_dependency_path,
1312
- decoded,
1313
- 'fetched'
1314
- );
1315
- }
1316
-
1317
- if (config.prerender.crawl && response.headers.get('content-type') === 'text/html') {
1318
- for (const href of crawl(body.toString())) {
1319
- if (href.startsWith('data:') || href.startsWith('#')) continue;
1320
-
1321
- const resolved = resolve(encoded, href);
1322
- if (!is_root_relative(resolved)) continue;
1323
-
1324
- const { pathname, search } = new URL$1(resolved, 'http://localhost');
1325
-
1326
- enqueue(decoded, decodeURI(pathname), pathname);
1327
- }
1328
- }
1329
- }
1330
-
1331
- /**
1332
- * @param {'pages' | 'dependencies'} category
1333
- * @param {Response} response
1334
- * @param {string | Uint8Array} body
1335
- * @param {string} decoded
1336
- * @param {string} encoded
1337
- * @param {string | null} referrer
1338
- * @param {'linked' | 'fetched'} referenceType
1339
- */
1340
- function save(category, response, body, decoded, encoded, referrer, referenceType) {
1341
- const response_type = Math.floor(response.status / 100);
1342
- const type = /** @type {string} */ (response.headers.get('content-type'));
1343
- const is_html = response_type === REDIRECT || type === 'text/html';
1344
-
1345
- const file = output_filename(decoded, is_html);
1346
- const dest = `${config.outDir}/output/prerendered/${category}/${file}`;
1347
-
1348
- if (written.has(file)) return;
1349
-
1350
- if (response_type === REDIRECT) {
1351
- const location = response.headers.get('location');
1352
-
1353
- if (location) {
1354
- const resolved = resolve(encoded, location);
1355
- if (is_root_relative(resolved)) {
1356
- enqueue(decoded, decodeURI(resolved), resolved);
1357
- }
1358
-
1359
- if (!response.headers.get('x-sveltekit-normalize')) {
1360
- mkdirp(dirname(dest));
1361
-
1362
- log.warn(`${response.status} ${decoded} -> ${location}`);
1363
-
1364
- writeFileSync(
1365
- dest,
1366
- `<meta http-equiv="refresh" content=${escape_html_attr(`0;url=${location}`)}>`
1367
- );
1368
-
1369
- written.add(file);
1370
-
1371
- if (!prerendered.redirects.has(decoded)) {
1372
- prerendered.redirects.set(decoded, {
1373
- status: response.status,
1374
- location: resolved
1375
- });
1376
-
1377
- prerendered.paths.push(decoded);
1378
- }
1379
- }
1380
- } else {
1381
- log.warn(`location header missing on redirect received from ${decoded}`);
1382
- }
1383
-
1384
- return;
1385
- }
1386
-
1387
- if (response.status === 200) {
1388
- mkdirp(dirname(dest));
1389
-
1390
- log.info(`${response.status} ${decoded}`);
1391
- writeFileSync(dest, body);
1392
- written.add(file);
1393
-
1394
- if (is_html) {
1395
- prerendered.pages.set(decoded, {
1396
- file
1397
- });
1398
- } else {
1399
- prerendered.assets.set(decoded, {
1400
- type
1401
- });
1402
- }
1403
-
1404
- prerendered.paths.push(decoded);
1405
- } else if (response_type !== OK) {
1406
- error({ status: response.status, path: decoded, referrer, referenceType });
1407
- }
1408
- }
1409
-
1410
- if (config.prerender.enabled) {
1411
- for (const entry of config.prerender.entries) {
1412
- if (entry === '*') {
1413
- /** @type {import('types').ManifestData} */
1414
- const { routes } = (await import(pathToFileURL(manifest_path).href)).manifest._;
1415
- const entries = routes
1416
- .map((route) => (route.type === 'page' ? route.path : ''))
1417
- .filter(Boolean);
1418
-
1419
- for (const entry of entries) {
1420
- enqueue(null, config.paths.base + entry); // TODO can we pre-normalize these?
1421
- }
1422
- } else {
1423
- enqueue(null, config.paths.base + entry);
1424
- }
1425
- }
1426
-
1427
- await q.done();
1428
- }
1429
-
1430
- const rendered = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
1431
- getClientAddress,
1432
- prerendering: {
1433
- fallback: true,
1434
- dependencies: new Map()
1435
- }
1436
- });
1437
-
1438
- const file = `${config.outDir}/output/prerendered/fallback.html`;
1439
- mkdirp(dirname(file));
1440
- writeFileSync(file, await rendered.text());
1441
-
1442
- return prerendered;
1443
- }
1444
-
1445
- /** @return {string} */
1446
- function getClientAddress() {
1447
- throw new Error('Cannot read clientAddress during prerendering');
1448
- }
1449
-
1450
713
  function totalist(dir, callback, pre='') {
1451
- dir = resolve$1('.', dir);
714
+ dir = resolve('.', dir);
1452
715
  let arr = readdirSync(dir);
1453
716
  let i=0, abs, stats;
1454
717
  for (; i < arr.length; i++) {
@@ -2022,7 +1285,7 @@ function toHeaders(name, stats, isEtag) {
2022
1285
  }
2023
1286
 
2024
1287
  function sirv (dir, opts={}) {
2025
- dir = resolve$1(dir || '.');
1288
+ dir = resolve(dir || '.');
2026
1289
 
2027
1290
  let isNotFound = opts.onNoMatch || is404;
2028
1291
  let setHeaders = opts.setHeaders || noop;
@@ -2269,37 +1532,50 @@ async function dev(vite, vite_config, svelte_config) {
2269
1532
  extensions: []
2270
1533
  });
2271
1534
 
1535
+ vite.middlewares.use(async (req, res, next) => {
1536
+ try {
1537
+ const base = `${vite.config.server.https ? 'https' : 'http'}://${
1538
+ req.headers[':authority'] || req.headers.host
1539
+ }`;
1540
+
1541
+ const decoded = decodeURI(new URL$1(base + req.url).pathname);
1542
+
1543
+ if (decoded.startsWith(assets)) {
1544
+ const pathname = decoded.slice(assets.length);
1545
+ const file = svelte_config.kit.files.assets + pathname;
1546
+
1547
+ if (fs__default.existsSync(file) && !fs__default.statSync(file).isDirectory()) {
1548
+ if (has_correct_case(file, svelte_config.kit.files.assets)) {
1549
+ req.url = encodeURI(pathname); // don't need query/hash
1550
+ asset_server(req, res);
1551
+ return;
1552
+ }
1553
+ }
1554
+ }
1555
+
1556
+ next();
1557
+ } catch (e) {
1558
+ const error = coalesce_to_error(e);
1559
+ res.statusCode = 500;
1560
+ res.end(fix_stack_trace(error));
1561
+ }
1562
+ });
1563
+
2272
1564
  return () => {
2273
1565
  const serve_static_middleware = vite.middlewares.stack.find(
2274
1566
  (middleware) =>
2275
1567
  /** @type {function} */ (middleware.handle).name === 'viteServeStaticMiddleware'
2276
1568
  );
2277
1569
 
2278
- remove_html_middlewares(vite.middlewares);
1570
+ remove_static_middlewares(vite.middlewares);
2279
1571
 
2280
1572
  vite.middlewares.use(async (req, res) => {
2281
1573
  try {
2282
- if (!req.url || !req.method) throw new Error('Incomplete request');
2283
-
2284
1574
  const base = `${vite.config.server.https ? 'https' : 'http'}://${
2285
1575
  req.headers[':authority'] || req.headers.host
2286
1576
  }`;
2287
1577
 
2288
1578
  const decoded = decodeURI(new URL$1(base + req.url).pathname);
2289
-
2290
- if (decoded.startsWith(assets)) {
2291
- const pathname = decoded.slice(assets.length);
2292
- const file = svelte_config.kit.files.assets + pathname;
2293
-
2294
- if (fs__default.existsSync(file) && !fs__default.statSync(file).isDirectory()) {
2295
- if (has_correct_case(file, svelte_config.kit.files.assets)) {
2296
- req.url = encodeURI(pathname); // don't need query/hash
2297
- asset_server(req, res);
2298
- return;
2299
- }
2300
- }
2301
- }
2302
-
2303
1579
  const file = posixify(path__default.resolve(decoded.slice(1)));
2304
1580
  const is_file = fs__default.existsSync(file) && !fs__default.statSync(file).isDirectory();
2305
1581
  const allowed =
@@ -2478,11 +1754,15 @@ function not_found(res, message = 'Not found') {
2478
1754
  /**
2479
1755
  * @param {import('connect').Server} server
2480
1756
  */
2481
- function remove_html_middlewares(server) {
2482
- const html_middlewares = ['viteServeStaticMiddleware'];
1757
+ function remove_static_middlewares(server) {
1758
+ // We don't use viteServePublicMiddleware because of the following issues:
1759
+ // https://github.com/vitejs/vite/issues/9260
1760
+ // https://github.com/vitejs/vite/issues/9236
1761
+ // https://github.com/vitejs/vite/issues/9234
1762
+ const static_middlewares = ['viteServePublicMiddleware', 'viteServeStaticMiddleware'];
2483
1763
  for (let i = server.stack.length - 1; i > 0; i--) {
2484
- // @ts-expect-error using internals until https://github.com/vitejs/vite/pull/4640 is merged
2485
- if (html_middlewares.includes(server.stack[i].handle.name)) {
1764
+ // @ts-expect-error using internals
1765
+ if (static_middlewares.includes(server.stack[i].handle.name)) {
2486
1766
  server.stack.splice(i, 1);
2487
1767
  }
2488
1768
  }
@@ -2706,16 +1986,13 @@ async function preview(vite, config, protocol) {
2706
1986
  const server = new Server(manifest);
2707
1987
 
2708
1988
  return () => {
2709
- // files in `static`
2710
- vite.middlewares.use(scoped(assets, mutable(config.kit.files.assets)));
2711
-
2712
- // immutable generated client assets
1989
+ // generated client assets and the contents of `static`
2713
1990
  vite.middlewares.use(
2714
1991
  scoped(
2715
1992
  assets,
2716
1993
  sirv(join(config.kit.outDir, 'output/client'), {
2717
1994
  setHeaders: (res, pathname) => {
2718
- // only apply to build directory, not e.g. version.json
1995
+ // only apply to immutable directory, not e.g. version.json
2719
1996
  if (pathname.startsWith(`/${config.kit.appDir}/immutable`)) {
2720
1997
  res.setHeader('cache-control', 'public,max-age=31536000,immutable');
2721
1998
  }
@@ -2954,12 +2231,12 @@ function kit() {
2954
2231
  // for everything regardless — but it means that entry chunks reflect
2955
2232
  // their location in the source code, which is helpful for debugging
2956
2233
  manifest_data.components.forEach((file) => {
2957
- const resolved = path__default.resolve(cwd, file);
2958
- const relative = decodeURIComponent(path__default.relative(svelte_config.kit.files.routes, resolved));
2234
+ const resolved = path.resolve(cwd, file);
2235
+ const relative = decodeURIComponent(path.relative(svelte_config.kit.files.routes, resolved));
2959
2236
 
2960
2237
  const name = relative.startsWith('..')
2961
- ? path__default.basename(file)
2962
- : posixify(path__default.join('pages', relative));
2238
+ ? path.basename(file)
2239
+ : posixify(path.join('pages', relative));
2963
2240
  input[name] = resolved;
2964
2241
  });
2965
2242
 
@@ -2978,11 +2255,11 @@ function kit() {
2978
2255
  function client_build_info(assets, chunks) {
2979
2256
  /** @type {import('vite').Manifest} */
2980
2257
  const vite_manifest = JSON.parse(
2981
- fs__default.readFileSync(`${paths.client_out_dir}/manifest.json`, 'utf-8')
2258
+ fs$1.readFileSync(`${paths.client_out_dir}/manifest.json`, 'utf-8')
2982
2259
  );
2983
2260
 
2984
2261
  const entry_id = posixify(
2985
- path__default.relative(cwd, `${get_runtime_directory(svelte_config.kit)}/client/start.js`)
2262
+ path.relative(cwd, `${get_runtime_directory(svelte_config.kit)}/client/start.js`)
2986
2263
  );
2987
2264
 
2988
2265
  return {
@@ -3041,6 +2318,7 @@ function kit() {
3041
2318
  __SVELTEKIT_DEV__: 'true',
3042
2319
  __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0'
3043
2320
  },
2321
+ publicDir: svelte_config.kit.files.assets,
3044
2322
  resolve: {
3045
2323
  alias: get_aliases(svelte_config.kit)
3046
2324
  },
@@ -3052,9 +2330,9 @@ function kit() {
3052
2330
  svelte_config.kit.files.lib,
3053
2331
  svelte_config.kit.files.routes,
3054
2332
  svelte_config.kit.outDir,
3055
- path__default.resolve(cwd, 'src'),
3056
- path__default.resolve(cwd, 'node_modules'),
3057
- path__default.resolve(vite.searchForWorkspaceRoot(cwd), 'node_modules')
2333
+ path.resolve(cwd, 'src'),
2334
+ path.resolve(cwd, 'node_modules'),
2335
+ path.resolve(vite.searchForWorkspaceRoot(cwd), 'node_modules')
3058
2336
  ])
3059
2337
  ]
3060
2338
  },
@@ -3100,11 +2378,10 @@ function kit() {
3100
2378
  * then use this hook to kick off builds for the server and service worker.
3101
2379
  */
3102
2380
  async writeBundle(_options, bundle) {
3103
- log = logger({
3104
- verbose: vite_config.logLevel === 'info'
3105
- });
2381
+ const verbose = vite_config.logLevel === 'info';
2382
+ log = logger({ verbose });
3106
2383
 
3107
- fs__default.writeFileSync(
2384
+ fs$1.writeFileSync(
3108
2385
  `${paths.client_out_dir}/${svelte_config.kit.appDir}/version.json`,
3109
2386
  JSON.stringify({ version: svelte_config.kit.version.name })
3110
2387
  );
@@ -3136,7 +2413,7 @@ function kit() {
3136
2413
  };
3137
2414
 
3138
2415
  const manifest_path = `${paths.output_dir}/server/manifest.js`;
3139
- fs__default.writeFileSync(
2416
+ fs$1.writeFileSync(
3140
2417
  manifest_path,
3141
2418
  `export const manifest = ${generate_manifest({
3142
2419
  build_data,
@@ -3145,14 +2422,39 @@ function kit() {
3145
2422
  })};\n`
3146
2423
  );
3147
2424
 
3148
- process.env.SVELTEKIT_SERVER_BUILD_COMPLETED = 'true';
3149
2425
  log.info('Prerendering');
2426
+ await new Promise((fulfil, reject) => {
2427
+ const results_path = `${svelte_config.kit.outDir}/generated/prerendered.json`;
2428
+
2429
+ // do prerendering in a subprocess so any dangling stuff gets killed upon completion
2430
+ const script = fileURLToPath(
2431
+ new URL(
2432
+ './prerender.js' ,
2433
+ import.meta.url
2434
+ )
2435
+ );
3150
2436
 
3151
- prerendered = await prerender({
3152
- config: svelte_config.kit,
3153
- client_out_dir: vite_config.build.outDir,
3154
- manifest_path,
3155
- log
2437
+ const child = fork(
2438
+ script,
2439
+ [vite_config.build.outDir, results_path, manifest_path, '' + verbose],
2440
+ {
2441
+ stdio: 'inherit'
2442
+ }
2443
+ );
2444
+
2445
+ child.on('exit', (code) => {
2446
+ if (code) {
2447
+ reject(new Error(`Prerendering failed with code ${code}`));
2448
+ } else {
2449
+ prerendered = JSON.parse(fs$1.readFileSync(results_path, 'utf8'), (key, value) => {
2450
+ if (key === 'pages' || key === 'assets' || key === 'redirects') {
2451
+ return new Map(value);
2452
+ }
2453
+ return value;
2454
+ });
2455
+ fulfil(undefined);
2456
+ }
2457
+ });
3156
2458
  });
3157
2459
 
3158
2460
  if (options.service_worker_entry_file) {
@@ -3183,7 +2485,7 @@ function kit() {
3183
2485
  }
3184
2486
 
3185
2487
  if (svelte_config.kit.adapter) {
3186
- const { adapt } = await import('./chunks/index2.js');
2488
+ const { adapt } = await import('./chunks/index3.js');
3187
2489
  await adapt(svelte_config, build_data, prerendered, { log });
3188
2490
  } else {
3189
2491
  console.log($.bold().yellow('\nNo adapter specified'));
@@ -3192,13 +2494,6 @@ function kit() {
3192
2494
  `See ${$.bold().cyan('https://kit.svelte.dev/docs/adapters')} to learn how to configure your app to run on the platform of your choosing`
3193
2495
  );
3194
2496
  }
3195
-
3196
- if (svelte_config.kit.prerender.enabled) {
3197
- // this is necessary to close any open db connections, etc.
3198
- // TODO: prerender in a subprocess so we can exit in isolation and then remove this
3199
- // https://github.com/sveltejs/kit/issues/5306
3200
- process.exit(0);
3201
- }
3202
2497
  },
3203
2498
 
3204
2499
  /**