@sveltejs/kit 1.0.0-next.403 → 1.0.0-next.405

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.
@@ -1360,6 +1360,9 @@ async function render_response({
1360
1360
  const stylesheets = new Set(entry.stylesheets);
1361
1361
  const modulepreloads = new Set(entry.imports);
1362
1362
 
1363
+ /** @type {Set<string>} */
1364
+ const link_header_preloads = new Set();
1365
+
1363
1366
  /** @type {Map<string, string>} */
1364
1367
  // TODO if we add a client entry point one day, we will need to include inline_styles with the entry, otherwise stylesheets will be linked even if they are below inlineStyleThreshold
1365
1368
  const inline_styles = new Map();
@@ -1519,32 +1522,35 @@ async function render_response({
1519
1522
  head += `\n\t<style${attributes.join('')}>${content}</style>`;
1520
1523
  }
1521
1524
 
1522
- // prettier-ignore
1523
- head += Array.from(stylesheets)
1524
- .map((dep) => {
1525
- const attributes = [
1526
- 'rel="stylesheet"',
1527
- `href="${options.prefix + dep}"`
1528
- ];
1525
+ for (const dep of stylesheets) {
1526
+ const path = options.prefix + dep;
1527
+ const attributes = [];
1529
1528
 
1530
- if (csp.style_needs_nonce) {
1531
- attributes.push(`nonce="${csp.nonce}"`);
1532
- }
1529
+ if (csp.style_needs_nonce) {
1530
+ attributes.push(`nonce="${csp.nonce}"`);
1531
+ }
1533
1532
 
1534
- if (inline_styles.has(dep)) {
1535
- // don't load stylesheets that are already inlined
1536
- // include them in disabled state so that Vite can detect them and doesn't try to add them
1537
- attributes.push('disabled', 'media="(max-width: 0)"');
1538
- }
1533
+ if (inline_styles.has(dep)) {
1534
+ // don't load stylesheets that are already inlined
1535
+ // include them in disabled state so that Vite can detect them and doesn't try to add them
1536
+ attributes.push('disabled', 'media="(max-width: 0)"');
1537
+ } else {
1538
+ const preload_atts = ['rel="preload"', 'as="style"'].concat(attributes);
1539
+ link_header_preloads.add(`<${encodeURI(path)}>; ${preload_atts.join(';')}; nopush`);
1540
+ }
1539
1541
 
1540
- return `\n\t<link ${attributes.join(' ')}>`;
1541
- })
1542
- .join('');
1542
+ attributes.unshift('rel="stylesheet"');
1543
+ head += `\n\t<link href="${path}" ${attributes.join(' ')}>`;
1544
+ }
1543
1545
 
1544
1546
  if (page_config.router || page_config.hydrate) {
1545
- head += Array.from(modulepreloads)
1546
- .map((dep) => `\n\t<link rel="modulepreload" href="${options.prefix + dep}">`)
1547
- .join('');
1547
+ for (const dep of modulepreloads) {
1548
+ const path = options.prefix + dep;
1549
+ link_header_preloads.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
1550
+ if (state.prerendering) {
1551
+ head += `\n\t<link rel="modulepreload" href="${path}">`;
1552
+ }
1553
+ }
1548
1554
 
1549
1555
  const attributes = ['type="module"', `data-sveltekit-hydrate="${target}"`];
1550
1556
 
@@ -1611,6 +1617,10 @@ async function render_response({
1611
1617
  etag: `"${hash(html)}"`
1612
1618
  });
1613
1619
 
1620
+ if (link_header_preloads.size) {
1621
+ headers.set('link', Array.from(link_header_preloads).join(', '));
1622
+ }
1623
+
1614
1624
  if (cache) {
1615
1625
  headers.set('cache-control', `${is_private ? 'private' : 'public'}, max-age=${cache.maxage}`);
1616
1626
  }
@@ -1,7 +1,11 @@
1
1
  import { $ } from './index.js';
2
+ import glob from 'tiny-glob';
3
+ import zlib from 'zlib';
4
+ import { existsSync, statSync, createReadStream, createWriteStream } from 'fs';
5
+ import { pipeline } from 'stream';
6
+ import { promisify } from 'util';
2
7
  import { r as rimraf, m as mkdirp, c as copy } from './filesystem.js';
3
8
  import { g as generate_manifest } from '../vite.js';
4
- import 'fs';
5
9
  import 'path';
6
10
  import 'url';
7
11
  import 'node:child_process';
@@ -18,9 +22,7 @@ import '../node/polyfills.js';
18
22
  import 'assert';
19
23
  import 'net';
20
24
  import 'http';
21
- import 'stream';
22
25
  import 'buffer';
23
- import 'util';
24
26
  import 'stream/web';
25
27
  import 'perf_hooks';
26
28
  import 'util/types';
@@ -28,7 +30,6 @@ import 'events';
28
30
  import 'tls';
29
31
  import 'async_hooks';
30
32
  import 'console';
31
- import 'zlib';
32
33
  import 'node:http';
33
34
  import 'node:https';
34
35
  import 'node:zlib';
@@ -64,6 +65,30 @@ function create_builder({ config, build_data, prerendered, log }) {
64
65
  return true;
65
66
  }
66
67
 
68
+ const pipe = promisify(pipeline);
69
+
70
+ /**
71
+ * @param {string} file
72
+ * @param {'gz' | 'br'} format
73
+ */
74
+ async function compress_file(file, format = 'gz') {
75
+ const compress =
76
+ format == 'br'
77
+ ? zlib.createBrotliCompress({
78
+ params: {
79
+ [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
80
+ [zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY,
81
+ [zlib.constants.BROTLI_PARAM_SIZE_HINT]: statSync(file).size
82
+ }
83
+ })
84
+ : zlib.createGzip({ level: zlib.constants.Z_BEST_COMPRESSION });
85
+
86
+ const source = createReadStream(file);
87
+ const destination = createWriteStream(`${file}.${format}`);
88
+
89
+ await pipe(source, compress, destination);
90
+ }
91
+
67
92
  return {
68
93
  log,
69
94
  rimraf,
@@ -190,6 +215,23 @@ function create_builder({ config, build_data, prerendered, log }) {
190
215
  );
191
216
  },
192
217
 
218
+ async compress(directory) {
219
+ if (!existsSync(directory)) {
220
+ return;
221
+ }
222
+
223
+ const files = await glob('**/*.{html,js,json,css,svg,xml,wasm}', {
224
+ cwd: directory,
225
+ dot: true,
226
+ absolute: true,
227
+ filesOnly: true
228
+ });
229
+
230
+ await Promise.all(
231
+ files.map((file) => Promise.all([compress_file(file, 'gz'), compress_file(file, 'br')]))
232
+ );
233
+ },
234
+
193
235
  async prerender() {
194
236
  throw new Error(
195
237
  'builder.prerender() has been removed. Prerendering now takes place in the build phase — see builder.prerender and builder.writePrerendered'
package/dist/cli.js CHANGED
@@ -19,7 +19,7 @@ function handle_error(e) {
19
19
  process.exit(1);
20
20
  }
21
21
 
22
- const prog = sade('svelte-kit').version('1.0.0-next.403');
22
+ const prog = sade('svelte-kit').version('1.0.0-next.405');
23
23
 
24
24
  prog
25
25
  .command('package')
@@ -11,7 +11,7 @@ import require$$0$3 from 'events';
11
11
  import require$$4$1 from 'tls';
12
12
  import require$$3 from 'async_hooks';
13
13
  import 'console';
14
- import require$$3$1 from 'zlib';
14
+ import zlib from 'zlib';
15
15
  import http from 'node:http';
16
16
  import 'node:https';
17
17
  import 'node:zlib';
@@ -10333,7 +10333,7 @@ function requireFetch () {
10333
10333
  } = requireResponse();
10334
10334
  const { Headers } = requireHeaders();
10335
10335
  const { Request, makeRequest } = requireRequest();
10336
- const zlib = require$$3$1;
10336
+ const zlib$1 = zlib;
10337
10337
  const {
10338
10338
  matchRequestIntegrity,
10339
10339
  makePolicyContainer,
@@ -12215,11 +12215,11 @@ function requireFetch () {
12215
12215
  if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !(request.redirect === 'follow' && location)) {
12216
12216
  for (const coding of codings) {
12217
12217
  if (/(x-)?gzip/.test(coding)) {
12218
- decoders.push(zlib.createGunzip());
12218
+ decoders.push(zlib$1.createGunzip());
12219
12219
  } else if (/(x-)?deflate/.test(coding)) {
12220
- decoders.push(zlib.createInflate());
12220
+ decoders.push(zlib$1.createInflate());
12221
12221
  } else if (coding === 'br') {
12222
- decoders.push(zlib.createBrotliDecompress());
12222
+ decoders.push(zlib$1.createBrotliDecompress());
12223
12223
  } else {
12224
12224
  decoders.length = 0;
12225
12225
  break
package/dist/vite.js CHANGED
@@ -182,20 +182,6 @@ function assets_base(config) {
182
182
  return `${assets || base}/`;
183
183
  }
184
184
 
185
- /**
186
- * vite.config.js will contain vite-plugin-svelte-kit, which kicks off the server and service
187
- * worker builds in a hook. When running the server and service worker builds we must remove
188
- * the SvelteKit plugin so that we do not kick off additional instances of these builds.
189
- * @param {import('vite').UserConfig} config
190
- */
191
- function remove_svelte_kit(config) {
192
- // TODO i feel like there's a more elegant way to do this
193
- // @ts-expect-error - it can't handle infinite type expansion
194
- config.plugins = (config.plugins || [])
195
- .flat(Infinity)
196
- .filter((plugin) => plugin.name !== 'vite-plugin-svelte-kit');
197
- }
198
-
199
185
  const method_names = new Set(['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']);
200
186
 
201
187
  // If we'd written this in TypeScript, it could be easy...
@@ -288,11 +274,11 @@ export class Server {
288
274
  init({ env }) {
289
275
  const entries = Object.entries(env);
290
276
 
291
- const prv = Object.fromEntries(Object.entries(env).filter(([k]) => !k.startsWith('${
277
+ const prv = Object.fromEntries(entries.filter(([k]) => !k.startsWith('${
292
278
  config.kit.env.publicPrefix
293
279
  }')));
294
280
 
295
- const pub = Object.fromEntries(Object.entries(env).filter(([k]) => k.startsWith('${
281
+ const pub = Object.fromEntries(entries.filter(([k]) => k.startsWith('${
296
282
  config.kit.env.publicPrefix
297
283
  }')));
298
284
 
@@ -409,8 +395,6 @@ async function build_server(options, client) {
409
395
  await get_vite_config(vite_config, vite_config_env)
410
396
  );
411
397
 
412
- remove_svelte_kit(merged_config);
413
-
414
398
  const { chunks } = await create_build(merged_config);
415
399
 
416
400
  /** @type {import('vite').Manifest} */
@@ -513,7 +497,7 @@ function get_methods(cwd, output, manifest_data) {
513
497
  * @param {import('vite').Manifest} client_manifest
514
498
  */
515
499
  async function build_service_worker(
516
- { config, vite_config, vite_config_env, manifest_data, output_dir, service_worker_entry_file },
500
+ { config, manifest_data, output_dir, service_worker_entry_file },
517
501
  prerendered,
518
502
  client_manifest
519
503
  ) {
@@ -560,7 +544,7 @@ async function build_service_worker(
560
544
  .trim()
561
545
  );
562
546
 
563
- const merged_config = merge_vite_configs(await get_vite_config(vite_config, vite_config_env), {
547
+ await vite.build({
564
548
  base: assets_base(config.kit),
565
549
  build: {
566
550
  lib: {
@@ -576,7 +560,6 @@ async function build_service_worker(
576
560
  outDir: `${output_dir}/client`,
577
561
  emptyOutDir: false
578
562
  },
579
- // @ts-expect-error
580
563
  configFile: false,
581
564
  resolve: {
582
565
  alias: {
@@ -585,10 +568,6 @@ async function build_service_worker(
585
568
  }
586
569
  }
587
570
  });
588
-
589
- remove_svelte_kit(merged_config);
590
-
591
- await vite.build(merged_config);
592
571
  }
593
572
 
594
573
  function totalist(dir, callback, pre='') {
@@ -2185,6 +2164,11 @@ function kit() {
2185
2164
  * @see https://vitejs.dev/guide/api-plugin.html#config
2186
2165
  */
2187
2166
  async config(config, config_env) {
2167
+ // The config is created in build_server for SSR mode and passed inline
2168
+ if (config.build?.ssr) {
2169
+ return;
2170
+ }
2171
+
2188
2172
  vite_config_env = config_env;
2189
2173
  svelte_config = await load_config();
2190
2174
  is_build = config_env.command === 'build';
@@ -2269,6 +2253,10 @@ function kit() {
2269
2253
  * Clears the output directories.
2270
2254
  */
2271
2255
  buildStart() {
2256
+ if (vite_config.build.ssr) {
2257
+ return;
2258
+ }
2259
+
2272
2260
  // Reset for new build. Goes here because `build --watch` calls buildStart but not config
2273
2261
  completed_build = false;
2274
2262
 
@@ -2287,6 +2275,10 @@ function kit() {
2287
2275
  * then use this hook to kick off builds for the server and service worker.
2288
2276
  */
2289
2277
  async writeBundle(_options, bundle) {
2278
+ if (vite_config.build.ssr) {
2279
+ return;
2280
+ }
2281
+
2290
2282
  for (const file of manifest_data.components) {
2291
2283
  const id = vite.normalizePath(path.resolve(file));
2292
2284
  const node = this.getModuleInfo(id);
@@ -2403,9 +2395,10 @@ function kit() {
2403
2395
  * Runs the adapter.
2404
2396
  */
2405
2397
  async closeBundle() {
2406
- if (!completed_build) {
2407
- // vite calls closeBundle when dev-server restarts, ignore that,
2408
- // and only adapt when build successfully completes.
2398
+ // vite calls closeBundle when dev-server restarts, ignore that,
2399
+ // and only adapt when build successfully completes.
2400
+ const is_restart = !completed_build;
2401
+ if (vite_config.build.ssr || is_restart) {
2409
2402
  return;
2410
2403
  }
2411
2404
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.403",
3
+ "version": "1.0.0-next.405",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -12,7 +12,8 @@
12
12
  "dependencies": {
13
13
  "@sveltejs/vite-plugin-svelte": "^1.0.1",
14
14
  "chokidar": "^3.5.3",
15
- "sade": "^1.8.1"
15
+ "sade": "^1.8.1",
16
+ "tiny-glob": "^0.2.9"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@playwright/test": "^1.23.4",
package/types/index.d.ts CHANGED
@@ -80,6 +80,11 @@ export interface Builder {
80
80
  replace?: Record<string, string>;
81
81
  }
82
82
  ): string[];
83
+
84
+ /**
85
+ * @param {string} directory Path to the directory containing the files to be compressed
86
+ */
87
+ compress(directory: string): void;
83
88
  }
84
89
 
85
90
  export interface Config {