From fc5f94a3bc8f89f855979bf9ddb15e93ae69d234 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 25 May 2022 08:21:22 -0700 Subject: [PATCH] [chore] provide Vite config via plugin --- .changeset/cyan-files-hammer.md | 5 + packages/kit/src/cli.js | 44 +- packages/kit/src/core/dev/index.js | 104 ----- packages/kit/src/core/dev/plugin.js | 686 +++++++++++++++------------- packages/kit/tsconfig.json | 2 +- 5 files changed, 413 insertions(+), 428 deletions(-) create mode 100644 .changeset/cyan-files-hammer.md delete mode 100644 packages/kit/src/core/dev/index.js diff --git a/.changeset/cyan-files-hammer.md b/.changeset/cyan-files-hammer.md new file mode 100644 index 0000000000000..634729aff7149 --- /dev/null +++ b/.changeset/cyan-files-hammer.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +[chore] provide Vite config via plugin diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 8ed551c492926..3fdeeacdbf1bb 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -1,9 +1,10 @@ -import sade from 'sade'; -import colors from 'kleur'; +import chokidar from 'chokidar'; import fs from 'fs'; +import colors from 'kleur'; import { relative } from 'path'; import * as ports from 'port-authority'; -import chokidar from 'chokidar'; +import sade from 'sade'; +import * as vite from 'vite'; import { load_config } from './core/config/index.js'; import { networkInterfaces, release } from 'os'; import { coalesce_to_error } from './utils/error.js'; @@ -62,28 +63,41 @@ prog let close; async function start() { - const { dev } = await import('./core/dev/index.js'); + const { plugins, svelte_config } = await import('./core/dev/plugin.js'); - const { server, config } = await dev({ - port, - host, - https - }); + /** @type {import('vite').UserConfig} */ + const config = { plugins }; + config.server = config.server || {}; + + // optional config from command-line flags + // these should take precedence, but not print conflict warnings + if (host) { + config.server.host = host; + } + if (https) { + config.server.https = https; + } + if (port) { + config.server.port = port; + } + + const server = await vite.createServer(config); + await server.listen(port); const address_info = /** @type {import('net').AddressInfo} */ ( /** @type {import('http').Server} */ (server.httpServer).address() ); - const vite_config = server.config; + const resolved_config = server.config; welcome({ port: address_info.port, host: address_info.address, - https: !!(https || vite_config.server.https), - open: first && (open || !!vite_config.server.open), - base: config.kit.paths.base, - loose: vite_config.server.fs.strict === false, - allow: vite_config.server.fs.allow + https: !!(https || resolved_config.server.https), + open: first && (open || !!resolved_config.server.open), + base: svelte_config.kit.paths.base, + loose: resolved_config.server.fs.strict === false, + allow: resolved_config.server.fs.allow }); first = false; diff --git a/packages/kit/src/core/dev/index.js b/packages/kit/src/core/dev/index.js deleted file mode 100644 index 734f626f55ee1..0000000000000 --- a/packages/kit/src/core/dev/index.js +++ /dev/null @@ -1,104 +0,0 @@ -import path from 'path'; -import { svelte } from '@sveltejs/vite-plugin-svelte'; -import * as vite from 'vite'; -import { deep_merge } from '../../utils/object.js'; -import { load_config, print_config_conflicts } from '../config/index.js'; -import { get_aliases, get_runtime_path } from '../utils.js'; -import { create_plugin } from './plugin.js'; - -const cwd = process.cwd(); - -/** - * @typedef {{ - * port: number, - * host?: string, - * https: boolean, - * }} Options - * @typedef {import('types').SSRComponent} SSRComponent - */ - -/** @param {Options} opts */ -export async function dev({ port, host, https }) { - /** @type {import('types').ValidatedConfig} */ - const config = await load_config(); - - const [vite_config] = deep_merge( - { - server: { - fs: { - allow: [ - ...new Set([ - config.kit.files.lib, - config.kit.files.routes, - config.kit.outDir, - path.resolve(cwd, 'src'), - path.resolve(cwd, 'node_modules'), - path.resolve(vite.searchForWorkspaceRoot(cwd), 'node_modules') - ]) - ] - }, - port: 3000, - strictPort: true, - watch: { - ignored: [`${config.kit.outDir}/**`, `!${config.kit.outDir}/generated/**`] - } - } - }, - await config.kit.vite() - ); - - /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge(vite_config, { - configFile: false, - root: cwd, - resolve: { - alias: get_aliases(config) - }, - build: { - rollupOptions: { - // Vite dependency crawler needs an explicit JS entry point - // eventhough server otherwise works without it - input: `${get_runtime_path(config)}/client/start.js` - } - }, - plugins: [ - svelte({ - ...config, - emitCss: true, - compilerOptions: { - ...config.compilerOptions, - hydratable: !!config.kit.browser.hydrate - }, - configFile: false - }), - await create_plugin(config) - ], - base: '/' - }); - - print_config_conflicts(conflicts, 'kit.vite.'); - - // optional config from command-line flags - // these should take precedence, but not print conflict warnings - if (host) { - merged_config.server.host = host; - } - - // if https is already enabled then do nothing. it could be an object and we - // don't want to overwrite with a boolean - if (https && !merged_config.server.https) { - merged_config.server.https = https; - } - - if (port) { - merged_config.server.port = port; - } - - const server = await vite.createServer(merged_config); - await server.listen(port); - - return { - server, - config - }; -} diff --git a/packages/kit/src/core/dev/plugin.js b/packages/kit/src/core/dev/plugin.js index 8140511caf67d..22690de63c236 100644 --- a/packages/kit/src/core/dev/plugin.js +++ b/packages/kit/src/core/dev/plugin.js @@ -1,17 +1,20 @@ +import { svelte } from '@sveltejs/vite-plugin-svelte'; import fs from 'fs'; -import path from 'path'; -import { URL } from 'url'; import colors from 'kleur'; +import path from 'path'; import sirv from 'sirv'; +import { URL } from 'url'; +import { searchForWorkspaceRoot } from 'vite'; import { installPolyfills } from '../../node/polyfills.js'; import * as sync from '../sync/sync.js'; import { getRequest, setResponse } from '../../node/index.js'; import { SVELTE_KIT_ASSETS } from '../constants.js'; -import { get_mime_lookup, get_runtime_path, resolve_entry } from '../utils.js'; +import { get_aliases, get_mime_lookup, get_runtime_path, resolve_entry } from '../utils.js'; import { coalesce_to_error } from '../../utils/error.js'; -import { load_template } from '../config/index.js'; +import { load_config, load_template, print_config_conflicts } from '../config/index.js'; import { posixify } from '../../utils/filesystem.js'; import { parse_route_id } from '../../utils/routing.js'; +import { deep_merge } from '../../utils/object.js'; // Vite doesn't expose this so we just copy the list for now // https://github.com/vitejs/vite/blob/3edd1af56e980aef56641a5a51cf2932bb580d41/packages/vite/src/node/plugins/css.ts#L96 @@ -19,355 +22,410 @@ const style_pattern = /\.(css|less|sass|scss|styl|stylus|pcss|postcss)$/; const cwd = process.cwd(); +/** @type {import('types').ValidatedConfig} */ +export const svelte_config = await load_config(); + /** - * @param {import('types').ValidatedConfig} config - * @returns {Promise} + * @type {import('vite').Plugin} */ -export async function create_plugin(config) { - return { - name: 'vite-plugin-svelte-kit', - - async configureServer(vite) { - installPolyfills(); - - sync.init(config); - - const runtime = get_runtime_path(config); - - process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = '0'; - - /** @type {import('types').Respond} */ - const respond = (await import(`${runtime}/server/index.js`)).respond; - - /** @type {import('types').SSRManifest} */ - let manifest; - - function update_manifest() { - const { manifest_data } = sync.update(config); - - manifest = { - appDir: config.kit.appDir, - assets: new Set(manifest_data.assets.map((asset) => asset.file)), - mimeTypes: get_mime_lookup(manifest_data), - _: { - entry: { - file: `/@fs${runtime}/client/start.js`, - css: [], - js: [] - }, - nodes: manifest_data.components.map((id) => { - return async () => { - const url = id.startsWith('..') ? `/@fs${path.posix.resolve(id)}` : `/${id}`; - - const module = /** @type {import('types').SSRComponent} */ ( - await vite.ssrLoadModule(url, { fixStacktrace: false }) - ); - const node = await vite.moduleGraph.getModuleByUrl(url); - - if (!node) throw new Error(`Could not find node for ${url}`); - - const deps = new Set(); - await find_deps(vite, node, deps); - - /** @type {Record} */ - const styles = {}; - - for (const dep of deps) { - const parsed = new URL(dep.url, 'http://localhost/'); - const query = parsed.searchParams; - - if ( - style_pattern.test(dep.file) || - (query.has('svelte') && query.get('type') === 'style') - ) { - try { - const mod = await vite.ssrLoadModule(dep.url, { fixStacktrace: false }); - styles[dep.url] = mod.default; - } catch { - // this can happen with dynamically imported modules, I think - // because the Vite module graph doesn't distinguish between - // static and dynamic imports? TODO investigate, submit fix - } +const sveltekit_plugin = { + name: 'vite-plugin-svelte-kit', + + async config() { + const [vite_config] = deep_merge( + { + server: { + fs: { + allow: [ + ...new Set([ + svelte_config.kit.files.lib, + svelte_config.kit.files.routes, + svelte_config.kit.outDir, + path.resolve(cwd, 'src'), + path.resolve(cwd, 'node_modules'), + path.resolve(searchForWorkspaceRoot(cwd), 'node_modules') + ]) + ] + }, + port: 3000, + strictPort: true, + watch: { + ignored: [`${svelte_config.kit.outDir}/**`, `!${svelte_config.kit.outDir}/generated/**`] + } + } + }, + await svelte_config.kit.vite() + ); + + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge(vite_config, { + configFile: false, + root: cwd, + resolve: { + alias: get_aliases(svelte_config) + }, + build: { + rollupOptions: { + // Vite dependency crawler needs an explicit JS entry point + // eventhough server otherwise works without it + input: `${get_runtime_path(svelte_config)}/client/start.js` + } + }, + base: '/' + }); + + print_config_conflicts(conflicts, 'kit.vite.'); + + return merged_config; + }, + + async configureServer(vite) { + installPolyfills(); + + sync.init(svelte_config); + + const runtime = get_runtime_path(svelte_config); + + process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = '0'; + + /** @type {import('types').Respond} */ + const respond = (await import(`${runtime}/server/index.js`)).respond; + + /** @type {import('types').SSRManifest} */ + let manifest; + + function update_manifest() { + const { manifest_data } = sync.update(svelte_config); + + manifest = { + appDir: svelte_config.kit.appDir, + assets: new Set(manifest_data.assets.map((asset) => asset.file)), + mimeTypes: get_mime_lookup(manifest_data), + _: { + entry: { + file: `/@fs${runtime}/client/start.js`, + css: [], + js: [] + }, + nodes: manifest_data.components.map((id) => { + return async () => { + const url = id.startsWith('..') ? `/@fs${path.posix.resolve(id)}` : `/${id}`; + + const module = /** @type {import('types').SSRComponent} */ ( + await vite.ssrLoadModule(url, { fixStacktrace: false }) + ); + const node = await vite.moduleGraph.getModuleByUrl(url); + + if (!node) throw new Error(`Could not find node for ${url}`); + + const deps = new Set(); + await find_deps(vite, node, deps); + + /** @type {Record} */ + const styles = {}; + + for (const dep of deps) { + const parsed = new URL(dep.url, 'http://localhost/'); + const query = parsed.searchParams; + + if ( + style_pattern.test(dep.file) || + (query.has('svelte') && query.get('type') === 'style') + ) { + try { + const mod = await vite.ssrLoadModule(dep.url, { fixStacktrace: false }); + styles[dep.url] = mod.default; + } catch { + // this can happen with dynamically imported modules, I think + // because the Vite module graph doesn't distinguish between + // static and dynamic imports? TODO investigate, submit fix } } + } - return { - module, - entry: url.endsWith('.svelte') ? url : url + '?import', - css: [], - js: [], - // in dev we inline all styles to avoid FOUC - styles - }; + return { + module, + entry: url.endsWith('.svelte') ? url : url + '?import', + css: [], + js: [], + // in dev we inline all styles to avoid FOUC + styles }; - }), - routes: manifest_data.routes.map((route) => { - const { pattern, names, types } = parse_route_id(route.id); - - if (route.type === 'page') { - return { - type: 'page', - id: route.id, - pattern, - names, - types, - shadow: route.shadow - ? async () => { - const url = path.resolve(cwd, /** @type {string} */ (route.shadow)); - return await vite.ssrLoadModule(url, { fixStacktrace: false }); - } - : null, - a: route.a.map((id) => (id ? manifest_data.components.indexOf(id) : undefined)), - b: route.b.map((id) => (id ? manifest_data.components.indexOf(id) : undefined)) - }; - } + }; + }), + routes: manifest_data.routes.map((route) => { + const { pattern, names, types } = parse_route_id(route.id); + if (route.type === 'page') { return { - type: 'endpoint', + type: 'page', id: route.id, pattern, names, types, - load: async () => { - const url = path.resolve(cwd, route.file); - return await vite.ssrLoadModule(url, { fixStacktrace: false }); - } + shadow: route.shadow + ? async () => { + const url = path.resolve(cwd, /** @type {string} */ (route.shadow)); + return await vite.ssrLoadModule(url, { fixStacktrace: false }); + } + : null, + a: route.a.map((id) => (id ? manifest_data.components.indexOf(id) : undefined)), + b: route.b.map((id) => (id ? manifest_data.components.indexOf(id) : undefined)) }; - }), - matchers: async () => { - /** @type {Record} */ - const matchers = {}; - - for (const key in manifest_data.matchers) { - const file = manifest_data.matchers[key]; - const url = path.resolve(cwd, file); - const module = await vite.ssrLoadModule(url, { fixStacktrace: false }); - - if (module.match) { - matchers[key] = module.match; - } else { - throw new Error(`${file} does not export a \`match\` function`); - } - } + } - return matchers; + return { + type: 'endpoint', + id: route.id, + pattern, + names, + types, + load: async () => { + const url = path.resolve(cwd, route.file); + return await vite.ssrLoadModule(url, { fixStacktrace: false }); + } + }; + }), + matchers: async () => { + /** @type {Record} */ + const matchers = {}; + + for (const key in manifest_data.matchers) { + const file = manifest_data.matchers[key]; + const url = path.resolve(cwd, file); + const module = await vite.ssrLoadModule(url, { fixStacktrace: false }); + + if (module.match) { + matchers[key] = module.match; + } else { + throw new Error(`${file} does not export a \`match\` function`); + } } + + return matchers; } - }; - } + } + }; + } - /** @param {Error} error */ - function fix_stack_trace(error) { - return error.stack ? vite.ssrRewriteStacktrace(error.stack) : error.stack; - } + /** @param {Error} error */ + function fix_stack_trace(error) { + return error.stack ? vite.ssrRewriteStacktrace(error.stack) : error.stack; + } - update_manifest(); + update_manifest(); - vite.watcher.on('add', update_manifest); - vite.watcher.on('unlink', update_manifest); + vite.watcher.on('add', update_manifest); + vite.watcher.on('unlink', update_manifest); - const assets = config.kit.paths.assets ? SVELTE_KIT_ASSETS : config.kit.paths.base; - const asset_server = sirv(config.kit.files.assets, { - dev: true, - etag: true, - maxAge: 0, - extensions: [] - }); + const assets = svelte_config.kit.paths.assets + ? SVELTE_KIT_ASSETS + : svelte_config.kit.paths.base; + const asset_server = sirv(svelte_config.kit.files.assets, { + dev: true, + etag: true, + maxAge: 0, + extensions: [] + }); - return () => { - const serve_static_middleware = vite.middlewares.stack.find( - (middleware) => - /** @type {function} */ (middleware.handle).name === 'viteServeStaticMiddleware' - ); + return () => { + const serve_static_middleware = vite.middlewares.stack.find( + (middleware) => + /** @type {function} */ (middleware.handle).name === 'viteServeStaticMiddleware' + ); - remove_html_middlewares(vite.middlewares); + remove_html_middlewares(vite.middlewares); - vite.middlewares.use(async (req, res) => { - try { - if (!req.url || !req.method) throw new Error('Incomplete request'); + vite.middlewares.use(async (req, res) => { + try { + if (!req.url || !req.method) throw new Error('Incomplete request'); - const base = `${vite.config.server.https ? 'https' : 'http'}://${ - req.headers[':authority'] || req.headers.host - }`; + const base = `${vite.config.server.https ? 'https' : 'http'}://${ + req.headers[':authority'] || req.headers.host + }`; - const decoded = decodeURI(new URL(base + req.url).pathname); + const decoded = decodeURI(new URL(base + req.url).pathname); - if (decoded.startsWith(assets)) { - const pathname = decoded.slice(assets.length); - const file = config.kit.files.assets + pathname; + if (decoded.startsWith(assets)) { + const pathname = decoded.slice(assets.length); + const file = svelte_config.kit.files.assets + pathname; - if (fs.existsSync(file) && !fs.statSync(file).isDirectory()) { - const has_correct_case = fs.realpathSync.native(file) === path.resolve(file); + if (fs.existsSync(file) && !fs.statSync(file).isDirectory()) { + const has_correct_case = fs.realpathSync.native(file) === path.resolve(file); - if (has_correct_case) { - req.url = encodeURI(pathname); // don't need query/hash - asset_server(req, res); - return; - } + if (has_correct_case) { + req.url = encodeURI(pathname); // don't need query/hash + asset_server(req, res); + return; } } + } - if (!decoded.startsWith(config.kit.paths.base)) { - return not_found(res, `Not found (did you mean ${config.kit.paths.base + req.url}?)`); - } - - /** @type {Partial} */ - const user_hooks = resolve_entry(config.kit.files.hooks) - ? await vite.ssrLoadModule(`/${config.kit.files.hooks}`, { fixStacktrace: false }) - : {}; - - const handle = user_hooks.handle || (({ event, resolve }) => resolve(event)); - - /** @type {import('types').Hooks} */ - const hooks = { - getSession: user_hooks.getSession || (() => ({})), - handle, - handleError: - user_hooks.handleError || - (({ /** @type {Error & { frame?: string }} */ error }) => { - console.error(colors.bold().red(error.message)); - if (error.frame) { - console.error(colors.gray(error.frame)); - } - if (error.stack) { - console.error(colors.gray(error.stack)); - } - }), - externalFetch: user_hooks.externalFetch || fetch - }; - - if (/** @type {any} */ (hooks).getContext) { - // TODO remove this for 1.0 - throw new Error( - 'The getContext hook has been removed. See https://kit.svelte.dev/docs/hooks' - ); - } - - if (/** @type {any} */ (hooks).serverFetch) { - // TODO remove this for 1.0 - throw new Error('The serverFetch hook has been renamed to externalFetch.'); - } - - // TODO the / prefix will probably fail if outDir is outside the cwd (which - // could be the case in a monorepo setup), but without it these modules - // can get loaded twice via different URLs, which causes failures. Might - // require changes to Vite to fix - const { default: root } = await vite.ssrLoadModule( - `/${posixify(path.relative(cwd, `${config.kit.outDir}/generated/root.svelte`))}`, - { fixStacktrace: false } + if (!decoded.startsWith(svelte_config.kit.paths.base)) { + return not_found( + res, + `Not found (did you mean ${svelte_config.kit.paths.base + req.url}?)` ); + } - const paths = await vite.ssrLoadModule( - process.env.BUNDLED - ? `/${posixify(path.relative(cwd, `${config.kit.outDir}/runtime/paths.js`))}` - : `/@fs${runtime}/paths.js`, - { fixStacktrace: false } + /** @type {Partial} */ + const user_hooks = resolve_entry(svelte_config.kit.files.hooks) + ? await vite.ssrLoadModule(`/${svelte_config.kit.files.hooks}`, { + fixStacktrace: false + }) + : {}; + + const handle = user_hooks.handle || (({ event, resolve }) => resolve(event)); + + /** @type {import('types').Hooks} */ + const hooks = { + getSession: user_hooks.getSession || (() => ({})), + handle, + handleError: + user_hooks.handleError || + (({ /** @type {Error & { frame?: string }} */ error }) => { + console.error(colors.bold().red(error.message)); + if (error.frame) { + console.error(colors.gray(error.frame)); + } + if (error.stack) { + console.error(colors.gray(error.stack)); + } + }), + externalFetch: user_hooks.externalFetch || fetch + }; + + if (/** @type {any} */ (hooks).getContext) { + // TODO remove this for 1.0 + throw new Error( + 'The getContext hook has been removed. See https://kit.svelte.dev/docs/hooks' ); + } - paths.set_paths({ - base: config.kit.paths.base, - assets - }); + if (/** @type {any} */ (hooks).serverFetch) { + // TODO remove this for 1.0 + throw new Error('The serverFetch hook has been renamed to externalFetch.'); + } - let request; + // TODO the / prefix will probably fail if outDir is outside the cwd (which + // could be the case in a monorepo setup), but without it these modules + // can get loaded twice via different URLs, which causes failures. Might + // require changes to Vite to fix + const { default: root } = await vite.ssrLoadModule( + `/${posixify(path.relative(cwd, `${svelte_config.kit.outDir}/generated/root.svelte`))}`, + { fixStacktrace: false } + ); + + const paths = await vite.ssrLoadModule( + process.env.BUNDLED + ? `/${posixify(path.relative(cwd, `${svelte_config.kit.outDir}/runtime/paths.js`))}` + : `/@fs${runtime}/paths.js`, + { fixStacktrace: false } + ); + + paths.set_paths({ + base: svelte_config.kit.paths.base, + assets + }); + + let request; - try { - request = await getRequest(base, req); - } catch (/** @type {any} */ err) { - res.statusCode = err.status || 400; - return res.end(err.reason || 'Invalid request body'); - } + try { + request = await getRequest(base, req); + } catch (/** @type {any} */ err) { + res.statusCode = err.status || 400; + return res.end(err.reason || 'Invalid request body'); + } + + const template = load_template(cwd, svelte_config); - const template = load_template(cwd, config); - - const rendered = await respond( - request, - { - csp: config.kit.csp, - dev: true, - floc: config.kit.floc, - get_stack: (error) => { - return fix_stack_trace(error); - }, - handle_error: (error, event) => { - hooks.handleError({ - error: new Proxy(error, { - get: (target, property) => { - if (property === 'stack') { - return fix_stack_trace(error); - } - - return Reflect.get(target, property, target); + const rendered = await respond( + request, + { + csp: svelte_config.kit.csp, + dev: true, + floc: svelte_config.kit.floc, + get_stack: (error) => { + return fix_stack_trace(error); + }, + handle_error: (error, event) => { + hooks.handleError({ + error: new Proxy(error, { + get: (target, property) => { + if (property === 'stack') { + return fix_stack_trace(error); } - }), - event, - - // TODO remove for 1.0 - // @ts-expect-error - get request() { - throw new Error( - 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details' - ); + + return Reflect.get(target, property, target); } - }); - }, - hooks, - hydrate: config.kit.browser.hydrate, - manifest, - method_override: config.kit.methodOverride, - paths: { - base: config.kit.paths.base, - assets - }, - prefix: '', - prerender: { - default: config.kit.prerender.default, - enabled: config.kit.prerender.enabled - }, - read: (file) => fs.readFileSync(path.join(config.kit.files.assets, file)), - root, - router: config.kit.browser.router, - template: ({ head, body, assets, nonce }) => { - return ( - template - .replace(/%sveltekit\.assets%/g, assets) - .replace(/%sveltekit\.nonce%/g, nonce) - // head and body must be replaced last, in case someone tries to sneak in %sveltekit.assets% etc - .replace('%sveltekit.head%', () => head) - .replace('%sveltekit.body%', () => body) - ); - }, - template_contains_nonce: template.includes('%sveltekit.nonce%'), - trailing_slash: config.kit.trailingSlash + }), + event, + + // TODO remove for 1.0 + // @ts-expect-error + get request() { + throw new Error( + 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details' + ); + } + }); }, - { - getClientAddress: () => { - const { remoteAddress } = req.socket; - if (remoteAddress) return remoteAddress; - throw new Error('Could not determine clientAddress'); - } + hooks, + hydrate: svelte_config.kit.browser.hydrate, + manifest, + method_override: svelte_config.kit.methodOverride, + paths: { + base: svelte_config.kit.paths.base, + assets + }, + prefix: '', + prerender: { + default: svelte_config.kit.prerender.default, + enabled: svelte_config.kit.prerender.enabled + }, + read: (file) => fs.readFileSync(path.join(svelte_config.kit.files.assets, file)), + root, + router: svelte_config.kit.browser.router, + template: ({ head, body, assets, nonce }) => { + return ( + template + .replace(/%sveltekit\.assets%/g, assets) + .replace(/%sveltekit\.nonce%/g, nonce) + // head and body must be replaced last, in case someone tries to sneak in %sveltekit.assets% etc + .replace('%sveltekit.head%', () => head) + .replace('%sveltekit.body%', () => body) + ); + }, + template_contains_nonce: template.includes('%sveltekit.nonce%'), + trailing_slash: svelte_config.kit.trailingSlash + }, + { + getClientAddress: () => { + const { remoteAddress } = req.socket; + if (remoteAddress) return remoteAddress; + throw new Error('Could not determine clientAddress'); } - ); + } + ); - if (rendered.status === 404) { - // @ts-expect-error - serve_static_middleware.handle(req, res, () => { - setResponse(res, rendered); - }); - } else { + if (rendered.status === 404) { + // @ts-expect-error + serve_static_middleware.handle(req, res, () => { setResponse(res, rendered); - } - } catch (e) { - const error = coalesce_to_error(e); - vite.ssrFixStacktrace(error); - res.statusCode = 500; - res.end(error.stack); + }); + } else { + setResponse(res, rendered); } - }); - }; - } - }; -} + } catch (e) { + const error = coalesce_to_error(e); + vite.ssrFixStacktrace(error); + res.statusCode = 500; + res.end(error.stack); + } + }); + }; + } +}; /** @param {import('http').ServerResponse} res */ function not_found(res, message = 'Not found') { @@ -431,3 +489,15 @@ async function find_deps(vite, node, deps) { await Promise.all(branches); } + +export const plugins = [ + svelte({ + ...svelte_config, + compilerOptions: { + ...svelte_config.compilerOptions, + hydratable: !!svelte_config.kit.browser.hydrate + }, + configFile: false + }), + sveltekit_plugin +]; diff --git a/packages/kit/tsconfig.json b/packages/kit/tsconfig.json index 0e095db709ce5..d00de5e9c2457 100644 --- a/packages/kit/tsconfig.json +++ b/packages/kit/tsconfig.json @@ -5,7 +5,7 @@ "noEmit": true, "strict": true, "target": "es2020", - "module": "es2020", + "module": "es2022", "moduleResolution": "node", "allowSyntheticDefaultImports": true, "paths": {