From 43a745ad5f516c48f08718ae256e73d9e47ef0eb Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:01:51 -0800 Subject: [PATCH] fix: make preview work with Vite 5 --- packages/kit/src/exports/vite/index.js | 47 ++++++++++++++- .../kit/src/exports/vite/preview/index.js | 59 ++----------------- 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index a7a886d6d745..f698bb64ad19 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -1,5 +1,5 @@ import fs from 'node:fs'; -import path from 'node:path'; +import path, { join } from 'node:path'; import { svelte } from '@sveltejs/vite-plugin-svelte'; import colors from 'kleur'; @@ -19,15 +19,21 @@ import { dev } from './dev/index.js'; import { is_illegal, module_guard, normalize_id } from './graph_analysis/index.js'; import { preview } from './preview/index.js'; import { get_config_aliases, get_env, strip_virtual_prefix } from './utils.js'; +import { SVELTE_KIT_ASSETS } from '../../constants.js'; import { write_client_manifest } from '../../core/sync/write_client_manifest.js'; import prerender from '../../core/postbuild/prerender.js'; import analyse from '../../core/postbuild/analyse.js'; import { s } from '../../utils/misc.js'; import { hash } from '../../runtime/hash.js'; import { dedent, isSvelte5Plus } from '../../core/sync/utils.js'; +import sirv from 'sirv'; export { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; +/** @typedef {import('http').IncomingMessage} Req */ +/** @typedef {import('http').ServerResponse} Res */ +/** @typedef {(req: Req, res: Res, next: () => void) => void} Handler */ + const cwd = process.cwd(); /** @type {import('./types.js').EnforcedConfig} */ @@ -617,6 +623,23 @@ function kit({ svelte_config }) { * @see https://vitejs.dev/guide/api-plugin.html#configurepreviewserver */ configurePreviewServer(vite) { + // generated client assets and the contents of `static` + const { paths } = svelte_config.kit; + const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base; + vite.middlewares.use( + scoped( + assets, + sirv(join(svelte_config.kit.outDir, 'output/client'), { + setHeaders: (res, pathname) => { + // only apply to immutable directory, not e.g. version.json + if (pathname.startsWith(`/${svelte_config.kit.appDir}/immutable`)) { + res.setHeader('cache-control', 'public,max-age=31536000,immutable'); + } + } + }) + ) + ); + return preview(vite, vite_config, svelte_config); }, @@ -906,3 +929,25 @@ const create_service_worker_module = (config) => dedent` export const prerendered = []; export const version = ${s(config.kit.version.name)}; `; + +/** + * @param {string} scope + * @param {Handler} handler + * @returns {Handler} + */ +function scoped(scope, handler) { + if (scope === '') return handler; + + return (req, res, next) => { + if (req.url?.startsWith(scope)) { + const original_url = req.url; + req.url = req.url.slice(scope.length); + handler(req, res, () => { + req.url = original_url; + next(); + }); + } else { + next(); + } + }; +} diff --git a/packages/kit/src/exports/vite/preview/index.js b/packages/kit/src/exports/vite/preview/index.js index 77ac50745158..fdea3d1ab607 100644 --- a/packages/kit/src/exports/vite/preview/index.js +++ b/packages/kit/src/exports/vite/preview/index.js @@ -8,7 +8,6 @@ import { getRequest, setResponse } from '../../../exports/node/index.js'; import { installPolyfills } from '../../../exports/node/polyfills.js'; import { SVELTE_KIT_ASSETS } from '../../../constants.js'; import { should_polyfill } from '../../../utils/platform.js'; -import { not_found } from '../utils.js'; /** @typedef {import('http').IncomingMessage} Req */ /** @typedef {import('http').ServerResponse} Res */ @@ -54,42 +53,15 @@ export async function preview(vite, vite_config, svelte_config) { }); return () => { - // generated client assets and the contents of `static` - vite.middlewares.use( - scoped( - assets, - sirv(join(svelte_config.kit.outDir, 'output/client'), { - setHeaders: (res, pathname) => { - // only apply to immutable directory, not e.g. version.json - if (pathname.startsWith(`/${svelte_config.kit.appDir}/immutable`)) { - res.setHeader('cache-control', 'public,max-age=31536000,immutable'); - } - } - }) - ) - ); - - vite.middlewares.use((req, res, next) => { - const original_url = /** @type {string} */ (req.url); - const { pathname } = new URL(original_url, 'http://dummy'); - - if (pathname.startsWith(base)) { - next(); - } else { - res.statusCode = 404; - not_found(req, res, base); - } - }); - // prerendered dependencies vite.middlewares.use( - scoped(base, mutable(join(svelte_config.kit.outDir, 'output/prerendered/dependencies'))) + mutable(join(svelte_config.kit.outDir, 'output/prerendered/dependencies')) ); // prerendered pages (we can't just use sirv because we need to // preserve the correct trailingSlash behaviour) vite.middlewares.use( - scoped(base, (req, res, next) => { + (req, res, next) => { let if_none_match_value = req.headers['if-none-match']; if (if_none_match_value?.startsWith('W/"')) { @@ -149,7 +121,7 @@ export async function preview(vite, vite_config, svelte_config) { } else { next(); } - }) + } ); // SSR @@ -157,10 +129,9 @@ export async function preview(vite, vite_config, svelte_config) { const host = req.headers['host']; let request; - try { request = await getRequest({ - base: `${protocol}://${host}`, + base: new URL(base, `${protocol}://${host}`).href, request: req }); } catch (/** @type {any} */ err) { @@ -195,28 +166,6 @@ const mutable = (dir) => }) : (_req, _res, next) => next(); -/** - * @param {string} scope - * @param {Handler} handler - * @returns {Handler} - */ -function scoped(scope, handler) { - if (scope === '') return handler; - - return (req, res, next) => { - if (req.url?.startsWith(scope)) { - const original_url = req.url; - req.url = req.url.slice(scope.length); - handler(req, res, () => { - req.url = original_url; - next(); - }); - } else { - next(); - } - }; -} - /** @param {string} path */ function is_file(path) { return fs.existsSync(path) && !fs.statSync(path).isDirectory();