From f177de1b17526985a9caef9eea3ed81098a897ca Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 26 May 2022 21:11:47 -0700 Subject: [PATCH 01/62] Expose Vite plugin as @sveltejs/kit/vite --- .changeset/healthy-carrots-cross.md | 5 + packages/kit/package.json | 3 + packages/kit/rollup.config.js | 3 +- packages/kit/src/cli.js | 2 +- packages/kit/src/vite/dev.js | 461 ++++++++++++++++++++++++++++ packages/kit/src/vite/index.js | 1 + packages/kit/src/vite/plugin.js | 107 +++++++ 7 files changed, 580 insertions(+), 2 deletions(-) create mode 100644 .changeset/healthy-carrots-cross.md create mode 100644 packages/kit/src/vite/dev.js create mode 100644 packages/kit/src/vite/index.js create mode 100644 packages/kit/src/vite/plugin.js diff --git a/.changeset/healthy-carrots-cross.md b/.changeset/healthy-carrots-cross.md new file mode 100644 index 000000000000..bb969d08859c --- /dev/null +++ b/.changeset/healthy-carrots-cross.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +Expose Vite plugin as @sveltejs/kit/vite diff --git a/packages/kit/package.json b/packages/kit/package.json index 4f10e4d9ca98..1d7c510e1b0e 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -88,6 +88,9 @@ }, "./hooks": { "import": "./dist/hooks.js" + }, + "./vite": { + "import": "./dist/vite.js" } }, "types": "types/index.d.ts", diff --git a/packages/kit/rollup.config.js b/packages/kit/rollup.config.js index feee1e87d5ad..7fa7819d249d 100644 --- a/packages/kit/rollup.config.js +++ b/packages/kit/rollup.config.js @@ -63,7 +63,8 @@ export default [ cli: 'src/cli.js', node: 'src/node/index.js', 'node/polyfills': 'src/node/polyfills.js', - hooks: 'src/hooks.js' + hooks: 'src/hooks.js', + vite: 'src/vite/index.js' }, output: { dir: 'dist', diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index e68877c70ef0..6233369c5658 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -64,7 +64,7 @@ prog async function start() { const svelte_config = await load_config(); - const { plugins } = await import('./core/dev/plugin.js'); + const { plugins } = await import('./vite/plugin.js'); const vite_config = await svelte_config.kit.vite(); /** @type {import('vite').UserConfig} */ diff --git a/packages/kit/src/vite/dev.js b/packages/kit/src/vite/dev.js new file mode 100644 index 000000000000..51b3db3b3402 --- /dev/null +++ b/packages/kit/src/vite/dev.js @@ -0,0 +1,461 @@ +import fs from 'fs'; +import colors from 'kleur'; +import path from 'path'; +import sirv from 'sirv'; +import { URL } from 'url'; +import { installPolyfills } from '../node/polyfills.js'; +import * as sync from '../core/sync/sync.js'; +import { getRequest, setResponse } from '../node/index.js'; +import { SVELTE_KIT_ASSETS } from '../core/constants.js'; +import { get_mime_lookup, get_runtime_path, resolve_entry } from '../core/utils.js'; +import { coalesce_to_error } from '../utils/error.js'; +import { load_template } from '../core/config/index.js'; +import { posixify } from '../utils/filesystem.js'; +import { parse_route_id } from '../utils/routing.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 +const style_pattern = /\.(css|less|sass|scss|styl|stylus|pcss|postcss)$/; + +const cwd = process.cwd(); + +/** + * @param {import('types').ValidatedConfig} svelte_config + * @return {import('vite').ServerHook} + */ +export const configure_server = function (svelte_config) { + return async function (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, index) => { + 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, + index, + 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)) + }; + } + + 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; + } + + update_manifest(); + + for (const event of ['add', 'unlink']) { + vite.watcher.on(event, (file) => { + if (file.startsWith(svelte_config.kit.files.routes + path.sep)) { + update_manifest(); + } + }); + } + + 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' + ); + + remove_html_middlewares(vite.middlewares); + + 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 decoded = decodeURI(new URL(base + req.url).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()) { + if (has_correct_case(file, svelte_config.kit.files.assets)) { + req.url = encodeURI(pathname); // don't need query/hash + asset_server(req, res); + return; + } + } + } + + if (!decoded.startsWith(svelte_config.kit.paths.base)) { + return not_found( + res, + `Not found (did you mean ${svelte_config.kit.paths.base + req.url}?)` + ); + } + + /** @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' + ); + } + + 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, `${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'); + } + + const template = load_template(cwd, svelte_config); + + 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); + } + + return Reflect.get(target, property, target); + } + }), + 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' + ); + } + }); + }, + 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 { + 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') { + res.statusCode = 404; + res.end(message); +} + +/** + * @param {import('connect').Server} server + */ +function remove_html_middlewares(server) { + const html_middlewares = [ + 'viteIndexHtmlMiddleware', + 'vite404Middleware', + 'viteSpaFallbackMiddleware', + 'viteServeStaticMiddleware' + ]; + for (let i = server.stack.length - 1; i > 0; i--) { + // @ts-expect-error using internals until https://github.com/vitejs/vite/pull/4640 is merged + if (html_middlewares.includes(server.stack[i].handle.name)) { + server.stack.splice(i, 1); + } + } +} + +/** + * @param {import('vite').ViteDevServer} vite + * @param {import('vite').ModuleNode} node + * @param {Set} deps + */ +async function find_deps(vite, node, deps) { + // since `ssrTransformResult.deps` contains URLs instead of `ModuleNode`s, this process is asynchronous. + // instead of using `await`, we resolve all branches in parallel. + /** @type {Promise[]} */ + const branches = []; + + /** @param {import('vite').ModuleNode} node */ + async function add(node) { + if (!deps.has(node)) { + deps.add(node); + await find_deps(vite, node, deps); + } + } + + /** @param {string} url */ + async function add_by_url(url) { + const node = await vite.moduleGraph.getModuleByUrl(url); + + if (node) { + await add(node); + } + } + + if (node.ssrTransformResult) { + if (node.ssrTransformResult.deps) { + node.ssrTransformResult.deps.forEach((url) => branches.push(add_by_url(url))); + } + } else { + node.importedModules.forEach((node) => branches.push(add(node))); + } + + await Promise.all(branches); +} + +/** + * Determine if a file is being requested with the correct case, + * to ensure consistent behaviour between dev and prod and across + * operating systems. Note that we can't use realpath here, + * because we don't want to follow symlinks + * @param {string} file + * @param {string} assets + * @returns {boolean} + */ + function has_correct_case(file, assets) { + if (file === assets) return true; + + const parent = path.dirname(file); + + if (fs.readdirSync(parent).includes(path.basename(file))) { + return has_correct_case(parent, assets); + } + + return false; +} diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js new file mode 100644 index 000000000000..aca3ef4a576b --- /dev/null +++ b/packages/kit/src/vite/index.js @@ -0,0 +1 @@ +export { plugins as sveltekit } from './plugin.js'; diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js new file mode 100644 index 000000000000..cc5065d6ff77 --- /dev/null +++ b/packages/kit/src/vite/plugin.js @@ -0,0 +1,107 @@ +import { svelte as svelte_plugin } from '@sveltejs/vite-plugin-svelte'; +import path from 'path'; +import { searchForWorkspaceRoot } from 'vite'; +import { print_config_conflicts } from '../core/config/index.js'; +import { get_aliases, get_runtime_path } from '../core/utils.js'; +import { deep_merge } from '../utils/object.js'; +import { configure_server } from './dev.js'; + +const cwd = process.cwd(); + +/** + * @param {import('types').ValidatedConfig} svelte_config + * @return {import('vite').Plugin} + */ +const sveltekit = function (svelte_config) { + return { + name: 'vite-plugin-svelte-kit', + + async config(_config, env) { + if (env.command === 'build') { + throw Error('build not yet supported'); + } + + // dev and preview config can be shared + const [vite_config] = deep_merge( + { + preview: { + port: 3000, + strictPort: true + }, + 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/**` + ] + } + }, + spa: false + }, + 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; + }, + + configureServer: configure_server(svelte_config) + + // TODO: implement configurePreviewServer for Vite 3 + }; +}; + +/** + * @param {import('types').ValidatedConfig} svelte_config + * @return {import('vite').Plugin[]} + */ +const svelte = function (svelte_config) { + return svelte_plugin({ + ...svelte_config, + compilerOptions: { + ...svelte_config.compilerOptions, + hydratable: !!svelte_config.kit.browser.hydrate + }, + configFile: false + }); +}; + +/** + * @param {import('types').ValidatedConfig} svelte_config + * @return {import('vite').Plugin[]} + */ +export const plugins = function (svelte_config) { + return [...svelte(svelte_config), sveltekit(svelte_config)]; +}; From 97350c5eb9c93672a36f90ad2d9b0ee7c729c276 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Fri, 27 May 2022 11:55:34 -0700 Subject: [PATCH 02/62] make svelte config optional --- packages/kit/src/cli.js | 2 +- packages/kit/src/vite/plugin.js | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 6233369c5658..f8226826f326 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -69,7 +69,7 @@ prog /** @type {import('vite').UserConfig} */ const config = { - plugins: [...(vite_config.plugins || []), plugins(svelte_config)] + plugins: [...(vite_config.plugins || []), await plugins(svelte_config)] }; config.server = {}; diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index cc5065d6ff77..7ab431d25acb 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -1,7 +1,7 @@ import { svelte as svelte_plugin } from '@sveltejs/vite-plugin-svelte'; import path from 'path'; import { searchForWorkspaceRoot } from 'vite'; -import { print_config_conflicts } from '../core/config/index.js'; +import { load_config, print_config_conflicts } from '../core/config/index.js'; import { get_aliases, get_runtime_path } from '../core/utils.js'; import { deep_merge } from '../utils/object.js'; import { configure_server } from './dev.js'; @@ -99,9 +99,10 @@ const svelte = function (svelte_config) { }; /** - * @param {import('types').ValidatedConfig} svelte_config - * @return {import('vite').Plugin[]} + * @param {import('types').ValidatedConfig} [svelte_config] + * @return {Promise} */ -export const plugins = function (svelte_config) { +export const plugins = async function (svelte_config) { + svelte_config = svelte_config || (await load_config()); return [...svelte(svelte_config), sveltekit(svelte_config)]; }; From 29e118a9e465c39948f24f628e8654202202234f Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sun, 29 May 2022 21:20:41 -0700 Subject: [PATCH 03/62] Implement build --- packages/kit/src/cli.js | 32 +- packages/kit/src/core/build/build_client.js | 79 --- packages/kit/src/core/build/index.js | 91 ---- packages/kit/src/core/build/utils.js | 13 +- packages/kit/src/core/dev/plugin.js | 544 -------------------- packages/kit/src/vite/dev.js | 2 +- packages/kit/src/vite/plugin.js | 197 ++++++- 7 files changed, 205 insertions(+), 753 deletions(-) delete mode 100644 packages/kit/src/core/build/build_client.js delete mode 100644 packages/kit/src/core/build/index.js delete mode 100644 packages/kit/src/core/dev/plugin.js diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index f8226826f326..5099d01d7b59 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -8,7 +8,6 @@ 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'; -import { logger } from './core/utils.js'; /** @param {unknown} e */ function handle_error(e) { @@ -158,31 +157,18 @@ prog .action(async ({ verbose }) => { try { process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - const config = await load_config(); - - const log = logger({ verbose }); - - const { build } = await import('./core/build/index.js'); - const { build_data, prerendered } = await build(config, { log }); - - console.log( - `\nRun ${colors.bold().cyan('npm run preview')} to preview your production build locally.` - ); - - if (config.kit.adapter) { - const { adapt } = await import('./core/adapt/index.js'); - await adapt(config, build_data, prerendered, { log }); + process.env.VERBOSE = verbose; - // this is necessary to close any open db connections, etc - process.exit(0); - } + const svelte_config = await load_config(); + const { plugins } = await import('./vite/plugin.js'); + const vite_config = await svelte_config.kit.vite(); - console.log(colors.bold().yellow('\nNo adapter specified')); + /** @type {import('vite').UserConfig} */ + const config = { + plugins: [...(vite_config.plugins || []), await plugins(svelte_config)] + }; - // prettier-ignore - console.log( - `See ${colors.bold().cyan('https://kit.svelte.dev/docs/adapters')} to learn how to configure your app to run on the platform of your choosing` - ); + await vite.build(config); } catch (error) { handle_error(error); } diff --git a/packages/kit/src/core/build/build_client.js b/packages/kit/src/core/build/build_client.js deleted file mode 100644 index 9b8a793ec8bc..000000000000 --- a/packages/kit/src/core/build/build_client.js +++ /dev/null @@ -1,79 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { deep_merge } from '../../utils/object.js'; -import { print_config_conflicts } from '../config/index.js'; -import { create_build, find_deps, get_default_config } from './utils.js'; -import { posixify } from '../../utils/filesystem.js'; - -/** - * @param {{ - * cwd: string; - * config: import('types').ValidatedConfig; - * manifest_data: import('types').ManifestData; - * output_dir: string; - * client_entry_file: string; - * }} options - */ -export async function build_client(options) { - const { cwd, config, manifest_data, output_dir, client_entry_file } = options; - - process.env.VITE_SVELTEKIT_APP_VERSION = config.kit.version.name; - process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${config.kit.appDir}/version.json`; - process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${config.kit.version.pollInterval}`; - - const client_out_dir = `${output_dir}/client/${config.kit.appDir}`; - - /** @type {Record} */ - const input = { - start: path.resolve(cwd, client_entry_file) - }; - - // This step is optional — Vite/Rollup will create the necessary chunks - // for everything regardless — but it means that entry chunks reflect - // their location in the source code, which is helpful for debugging - manifest_data.components.forEach((file) => { - const resolved = path.resolve(cwd, file); - const relative = path.relative(config.kit.files.routes, resolved); - - const name = relative.startsWith('..') - ? path.basename(file) - : posixify(path.join('pages', relative)); - input[name] = resolved; - }); - - /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge( - await config.kit.vite(), - get_default_config({ ...options, client_out_dir, input, ssr: false }) - ); - - print_config_conflicts(conflicts, 'kit.vite.', 'build_client'); - - const { chunks, assets } = await create_build(merged_config); - - /** @type {import('vite').Manifest} */ - const vite_manifest = JSON.parse( - fs.readFileSync(`${client_out_dir}/immutable/manifest.json`, 'utf-8') - ); - - const entry = posixify(client_entry_file); - const entry_js = new Set(); - const entry_css = new Set(); - find_deps(entry, vite_manifest, entry_js, entry_css); - - fs.writeFileSync( - `${client_out_dir}/version.json`, - JSON.stringify({ version: process.env.VITE_SVELTEKIT_APP_VERSION }) - ); - - return { - assets, - chunks, - entry: { - file: vite_manifest[entry].file, - js: Array.from(entry_js), - css: Array.from(entry_css) - }, - vite_manifest - }; -} diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js deleted file mode 100644 index ace5c1e4d02e..000000000000 --- a/packages/kit/src/core/build/index.js +++ /dev/null @@ -1,91 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { mkdirp, rimraf, posixify } from '../../utils/filesystem.js'; -import * as sync from '../sync/sync.js'; -import { get_runtime_path, resolve_entry } from '../utils.js'; -import { generate_manifest } from '../generate_manifest/index.js'; -import { build_service_worker } from './build_service_worker.js'; -import { build_client } from './build_client.js'; -import { build_server } from './build_server.js'; -import { prerender } from './prerender/prerender.js'; - -/** - * @param {import('types').ValidatedConfig} config - * @param {{ log: import('types').Logger }} opts - */ -export async function build(config, { log }) { - const cwd = process.cwd(); // TODO is this necessary? - - const build_dir = path.join(config.kit.outDir, 'build'); - rimraf(build_dir); - mkdirp(build_dir); - - const output_dir = path.join(config.kit.outDir, 'output'); - rimraf(output_dir); - mkdirp(output_dir); - - const { manifest_data } = sync.all(config); - - const options = { - cwd, - config, - build_dir, - manifest_data, - output_dir, - client_entry_file: path.relative(cwd, `${get_runtime_path(config)}/client/start.js`), - service_worker_entry_file: resolve_entry(config.kit.files.serviceWorker) - }; - - const client = await build_client(options); - const server = await build_server(options, client); - - /** @type {import('types').BuildData} */ - const build_data = { - app_dir: config.kit.appDir, - manifest_data: options.manifest_data, - service_worker: options.service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable? - client, - server - }; - - const manifest = `export const manifest = ${generate_manifest({ - build_data, - relative_path: '.', - routes: options.manifest_data.routes - })};\n`; - fs.writeFileSync(`${output_dir}/server/manifest.js`, manifest); - - const static_files = options.manifest_data.assets.map((asset) => posixify(asset.file)); - - const files = new Set([ - ...static_files, - ...client.chunks.map((chunk) => `${config.kit.appDir}/immutable/${chunk.fileName}`), - ...client.assets.map((chunk) => `${config.kit.appDir}/immutable/${chunk.fileName}`) - ]); - - // TODO is this right? - static_files.forEach((file) => { - if (file.endsWith('/index.html')) { - files.add(file.slice(0, -11)); - } - }); - - const prerendered = await prerender({ - config, - entries: options.manifest_data.routes - .map((route) => (route.type === 'page' ? route.path : '')) - .filter(Boolean), - files, - log - }); - - if (options.service_worker_entry_file) { - if (config.kit.paths.assets) { - throw new Error('Cannot use service worker alongside config.kit.paths.assets'); - } - - await build_service_worker(options, prerendered, client.vite_manifest); - } - - return { build_data, prerendered }; -} diff --git a/packages/kit/src/core/build/utils.js b/packages/kit/src/core/build/utils.js index 6a0477b9dcc2..84d43e782d5e 100644 --- a/packages/kit/src/core/build/utils.js +++ b/packages/kit/src/core/build/utils.js @@ -1,5 +1,5 @@ -import { svelte } from '@sveltejs/vite-plugin-svelte'; import * as vite from 'vite'; +import { svelte } from '../../vite/plugin.js'; import { get_aliases } from '../utils.js'; /** @@ -74,16 +74,7 @@ export const get_default_config = function ({ client_out_dir, config, input, out }, ssr }, - plugins: [ - svelte({ - ...config, - compilerOptions: { - ...config.compilerOptions, - hydratable: !!config.kit.browser.hydrate - }, - configFile: false - }) - ], + plugins: [svelte(config)], // prevent Vite copying the contents of `config.kit.files.assets`, // if it happens to be 'public' instead of 'static' publicDir: false, diff --git a/packages/kit/src/core/dev/plugin.js b/packages/kit/src/core/dev/plugin.js deleted file mode 100644 index 94bc8bd4f631..000000000000 --- a/packages/kit/src/core/dev/plugin.js +++ /dev/null @@ -1,544 +0,0 @@ -import { svelte as svelte_plugin } from '@sveltejs/vite-plugin-svelte'; -import fs from 'fs'; -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_aliases, get_mime_lookup, get_runtime_path, resolve_entry } from '../utils.js'; -import { coalesce_to_error } from '../../utils/error.js'; -import { 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 -const style_pattern = /\.(css|less|sass|scss|styl|stylus|pcss|postcss)$/; - -const cwd = process.cwd(); - -/** - * @param {import('types').ValidatedConfig} svelte_config - * @return {import('vite').Plugin} - */ -export const sveltekit = function (svelte_config) { - return { - 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, index) => { - 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, - index, - 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)) - }; - } - - 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; - } - - update_manifest(); - - for (const event of ['add', 'unlink']) { - vite.watcher.on(event, (file) => { - if (file.startsWith(svelte_config.kit.files.routes + path.sep)) { - update_manifest(); - } - }); - } - - 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' - ); - - remove_html_middlewares(vite.middlewares); - - 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 decoded = decodeURI(new URL(base + req.url).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()) { - if (has_correct_case(file, svelte_config.kit.files.assets)) { - req.url = encodeURI(pathname); // don't need query/hash - asset_server(req, res); - return; - } - } - } - - if (!decoded.startsWith(svelte_config.kit.paths.base)) { - return not_found( - res, - `Not found (did you mean ${svelte_config.kit.paths.base + req.url}?)` - ); - } - - /** @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' - ); - } - - 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, `${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'); - } - - const template = load_template(cwd, svelte_config); - - 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); - } - - return Reflect.get(target, property, target); - } - }), - 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' - ); - } - }); - }, - 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 { - 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') { - res.statusCode = 404; - res.end(message); -} - -/** - * @param {import('connect').Server} server - */ -function remove_html_middlewares(server) { - const html_middlewares = [ - 'viteIndexHtmlMiddleware', - 'vite404Middleware', - 'viteSpaFallbackMiddleware', - 'viteServeStaticMiddleware' - ]; - for (let i = server.stack.length - 1; i > 0; i--) { - // @ts-expect-error using internals until https://github.com/vitejs/vite/pull/4640 is merged - if (html_middlewares.includes(server.stack[i].handle.name)) { - server.stack.splice(i, 1); - } - } -} - -/** - * @param {import('vite').ViteDevServer} vite - * @param {import('vite').ModuleNode} node - * @param {Set} deps - */ -async function find_deps(vite, node, deps) { - // since `ssrTransformResult.deps` contains URLs instead of `ModuleNode`s, this process is asynchronous. - // instead of using `await`, we resolve all branches in parallel. - /** @type {Promise[]} */ - const branches = []; - - /** @param {import('vite').ModuleNode} node */ - async function add(node) { - if (!deps.has(node)) { - deps.add(node); - await find_deps(vite, node, deps); - } - } - - /** @param {string} url */ - async function add_by_url(url) { - const node = await vite.moduleGraph.getModuleByUrl(url); - - if (node) { - await add(node); - } - } - - if (node.ssrTransformResult) { - if (node.ssrTransformResult.deps) { - node.ssrTransformResult.deps.forEach((url) => branches.push(add_by_url(url))); - } - } else { - node.importedModules.forEach((node) => branches.push(add(node))); - } - - await Promise.all(branches); -} - -/** - * Determine if a file is being requested with the correct case, - * to ensure consistent behaviour between dev and prod and across - * operating systems. Note that we can't use realpath here, - * because we don't want to follow symlinks - * @param {string} file - * @param {string} assets - * @returns {boolean} - */ -function has_correct_case(file, assets) { - if (file === assets) return true; - - const parent = path.dirname(file); - - if (fs.readdirSync(parent).includes(path.basename(file))) { - return has_correct_case(parent, assets); - } - - return false; -} - -/** - * @param {import('types').ValidatedConfig} svelte_config - * @return {import('vite').Plugin[]} - */ -export const svelte = function (svelte_config) { - return svelte_plugin({ - ...svelte_config, - compilerOptions: { - ...svelte_config.compilerOptions, - hydratable: !!svelte_config.kit.browser.hydrate - }, - configFile: false - }); -}; - -/** - * @param {import('types').ValidatedConfig} svelte_config - * @return {import('vite').Plugin[]} - */ -export const plugins = function (svelte_config) { - return [...svelte(svelte_config), sveltekit(svelte_config)]; -}; diff --git a/packages/kit/src/vite/dev.js b/packages/kit/src/vite/dev.js index 51b3db3b3402..fc957174ad0b 100644 --- a/packages/kit/src/vite/dev.js +++ b/packages/kit/src/vite/dev.js @@ -448,7 +448,7 @@ async function find_deps(vite, node, deps) { * @param {string} assets * @returns {boolean} */ - function has_correct_case(file, assets) { +function has_correct_case(file, assets) { if (file === assets) return true; const parent = path.dirname(file); diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 7ab431d25acb..bde44f360b3b 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -1,10 +1,19 @@ import { svelte as svelte_plugin } from '@sveltejs/vite-plugin-svelte'; +import fs from 'fs'; +import colors from 'kleur'; import path from 'path'; import { searchForWorkspaceRoot } from 'vite'; +import { mkdirp, posixify, rimraf } from '../utils/filesystem.js'; +import * as sync from '../core/sync/sync.js'; +import { build_server } from '../core/build/build_server.js'; +import { build_service_worker } from '../core/build/build_service_worker.js'; +import { prerender } from '../core/build/prerender/prerender.js'; import { load_config, print_config_conflicts } from '../core/config/index.js'; -import { get_aliases, get_runtime_path } from '../core/utils.js'; +import { generate_manifest } from '../core/generate_manifest/index.js'; +import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; import { deep_merge } from '../utils/object.js'; import { configure_server } from './dev.js'; +import { find_deps, get_default_config } from '../core/build/utils.js'; const cwd = process.cwd(); @@ -12,13 +21,70 @@ const cwd = process.cwd(); * @param {import('types').ValidatedConfig} svelte_config * @return {import('vite').Plugin} */ -const sveltekit = function (svelte_config) { +export const sveltekit = function (svelte_config) { + const build_dir = path.join(svelte_config.kit.outDir, 'build'); + const output_dir = path.join(svelte_config.kit.outDir, 'output'); + const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; + const client_entry_file = path.relative( + cwd, + `${get_runtime_path(svelte_config)}/client/start.js` + ); + + /** @type {import('types').ManifestData|undefined} */ + let manifest_data = undefined; + return { name: 'vite-plugin-svelte-kit', async config(_config, env) { if (env.command === 'build') { - throw Error('build not yet supported'); + rimraf(build_dir); + mkdirp(build_dir); + + rimraf(output_dir); + mkdirp(output_dir); + + process.env.VITE_SVELTEKIT_APP_VERSION = svelte_config.kit.version.name; + process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${svelte_config.kit.appDir}/version.json`; + process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${svelte_config.kit.version.pollInterval}`; + + manifest_data = sync.all(svelte_config).manifest_data; + + /** @type {Record} */ + const input = { + start: path.resolve(cwd, client_entry_file) + }; + + // This step is optional — Vite/Rollup will create the necessary chunks + // for everything regardless — but it means that entry chunks reflect + // their location in the source code, which is helpful for debugging + manifest_data.components.forEach((file) => { + const resolved = path.resolve(cwd, file); + const relative = path.relative(svelte_config.kit.files.routes, resolved); + + const name = relative.startsWith('..') + ? path.basename(file) + : posixify(path.join('pages', relative)); + input[name] = resolved; + }); + + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge( + await svelte_config.kit.vite(), + get_default_config({ + client_out_dir, + config: svelte_config, + input, + output_dir, + ssr: false + }) + ); + + print_config_conflicts(conflicts, 'kit.vite.', 'build_client'); + + merged_config.plugins.push(svelte_config); + + return merged_config; } // dev and preview config can be shared @@ -77,6 +143,129 @@ const sveltekit = function (svelte_config) { return merged_config; }, + async writeBundle(_options, bundle) { + if (!manifest_data) throw Error('manifest_data not populated'); + + const log = logger({ verbose: !!process.env.VERBOSE }); + + /** @type {import('rollup').OutputChunk[]} */ + const chunks = []; + /** @type {import('rollup').OutputAsset[]} */ + const assets = []; + for (const key of Object.keys(bundle)) { + // collect asset and output chunks + if (bundle[key].type === 'asset') { + assets.push(/** @type {import('rollup').OutputAsset} */ (bundle[key])); + } else { + chunks.push(/** @type {import('rollup').OutputChunk} */ (bundle[key])); + } + } + + /** @type {import('vite').Manifest} */ + const vite_manifest = JSON.parse( + fs.readFileSync(`${client_out_dir}/immutable/manifest.json`, 'utf-8') + ); + + const entry = posixify(client_entry_file); + const entry_js = new Set(); + const entry_css = new Set(); + find_deps(entry, vite_manifest, entry_js, entry_css); + + fs.writeFileSync( + `${client_out_dir}/version.json`, + JSON.stringify({ version: process.env.VITE_SVELTEKIT_APP_VERSION }) + ); + const client = { + assets, + chunks, + entry: { + file: vite_manifest[entry].file, + js: Array.from(entry_js), + css: Array.from(entry_css) + }, + vite_manifest + }; + + const options = { + cwd, + config: svelte_config, + build_dir, + manifest_data, + output_dir, + client_entry_file, + service_worker_entry_file: resolve_entry(svelte_config.kit.files.serviceWorker) + }; + + const server = await build_server(options, client); + + /** @type {import('types').BuildData} */ + const build_data = { + app_dir: svelte_config.kit.appDir, + manifest_data, + service_worker: options.service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable? + client, + server + }; + + const manifest = `export const manifest = ${generate_manifest({ + build_data, + relative_path: '.', + routes: manifest_data.routes + })};\n`; + fs.writeFileSync(`${output_dir}/server/manifest.js`, manifest); + + const static_files = manifest_data.assets.map((asset) => posixify(asset.file)); + + const files = new Set([ + ...static_files, + ...chunks.map((chunk) => `${svelte_config.kit.appDir}/immutable/${chunk.fileName}`), + ...assets.map((chunk) => `${svelte_config.kit.appDir}/immutable/${chunk.fileName}`) + ]); + + // TODO is this right? + static_files.forEach((file) => { + if (file.endsWith('/index.html')) { + files.add(file.slice(0, -11)); + } + }); + + const prerendered = await prerender({ + config: svelte_config, + entries: manifest_data.routes + .map((route) => (route.type === 'page' ? route.path : '')) + .filter(Boolean), + files, + log + }); + + if (options.service_worker_entry_file) { + if (svelte_config.kit.paths.assets) { + throw new Error('Cannot use service worker alongside config.kit.paths.assets'); + } + + await build_service_worker(options, prerendered, client.vite_manifest); + } + + console.log( + `\nRun ${colors.bold().cyan('npm run preview')} to preview your production build locally.` + ); + + if (svelte_config.kit.adapter) { + const { adapt } = await import('../core/adapt/index.js'); + await adapt(svelte_config, build_data, prerendered, { log }); + + // this is necessary to close any open db connections, etc + process.exit(0); + } + + console.log(colors.bold().yellow('\nNo adapter specified')); + + // prettier-ignore + console.log( + `See ${colors.bold().cyan('https://kit.svelte.dev/docs/adapters')} to learn how to configure your app to run on the platform of your choosing` + ); + }, + configureServer: configure_server(svelte_config) // TODO: implement configurePreviewServer for Vite 3 @@ -87,7 +276,7 @@ const sveltekit = function (svelte_config) { * @param {import('types').ValidatedConfig} svelte_config * @return {import('vite').Plugin[]} */ -const svelte = function (svelte_config) { +export const svelte = function (svelte_config) { return svelte_plugin({ ...svelte_config, compilerOptions: { From ea469389b2e696797b946b72becd1e5914c6aa11 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Tue, 31 May 2022 14:50:44 -0700 Subject: [PATCH 04/62] export as experimental/vite for now --- packages/kit/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/package.json b/packages/kit/package.json index 1d7c510e1b0e..2829a566d44f 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -89,7 +89,7 @@ "./hooks": { "import": "./dist/hooks.js" }, - "./vite": { + "./experimental/vite": { "import": "./dist/vite.js" } }, From e3cd4f5dc9356ba4584adab9e0c83ac8755363c6 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Tue, 31 May 2022 16:41:25 -0700 Subject: [PATCH 05/62] add plugin correct number of times with or without vite.config.js --- packages/kit/src/cli.js | 24 +--- packages/kit/src/core/build/build_server.js | 11 +- .../src/core/build/build_service_worker.js | 12 +- packages/kit/src/core/build/utils.js | 2 - packages/kit/src/vite/plugin.js | 128 +++++++++++++----- 5 files changed, 120 insertions(+), 57 deletions(-) diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 5099d01d7b59..0a1036c9bee7 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -8,6 +8,7 @@ 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'; +import { get_vite_config } from './vite/plugin.js'; /** @param {unknown} e */ function handle_error(e) { @@ -63,14 +64,8 @@ prog async function start() { const svelte_config = await load_config(); - const { plugins } = await import('./vite/plugin.js'); - const vite_config = await svelte_config.kit.vite(); - - /** @type {import('vite').UserConfig} */ - const config = { - plugins: [...(vite_config.plugins || []), await plugins(svelte_config)] - }; - config.server = {}; + const config = await get_vite_config(svelte_config); + config.server = config.server || {}; // optional config from command-line flags // these should take precedence, but not print conflict warnings @@ -80,7 +75,7 @@ prog // 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 && !vite_config?.server?.https) { + if (https && !config?.server?.https) { config.server.https = https; } @@ -160,15 +155,8 @@ prog process.env.VERBOSE = verbose; const svelte_config = await load_config(); - const { plugins } = await import('./vite/plugin.js'); - const vite_config = await svelte_config.kit.vite(); - - /** @type {import('vite').UserConfig} */ - const config = { - plugins: [...(vite_config.plugins || []), await plugins(svelte_config)] - }; - - await vite.build(config); + const vite_config = await get_vite_config(svelte_config); + await vite.build(vite_config); } catch (error) { handle_error(error); } diff --git a/packages/kit/src/core/build/build_server.js b/packages/kit/src/core/build/build_server.js index f1b50f5af18c..e1fe7fce92e9 100644 --- a/packages/kit/src/core/build/build_server.js +++ b/packages/kit/src/core/build/build_server.js @@ -6,6 +6,7 @@ import { load_template, print_config_conflicts } from '../config/index.js'; import { get_runtime_path, resolve_entry } from '../utils.js'; import { create_build, find_deps, get_default_config } from './utils.js'; import { s } from '../../utils/misc.js'; +import { get_vite_config } from '../../vite/plugin.js'; /** * @param {{ @@ -174,8 +175,7 @@ export async function build_server(options, client) { }) ); - /** @type {import('vite').UserConfig} */ - const vite_config = await config.kit.vite(); + const vite_config = await get_vite_config(config, false); const default_config = { build: { @@ -205,6 +205,13 @@ export async function build_server(options, client) { print_config_conflicts(conflicts, 'kit.vite.', 'build_server'); + merged_config.plugins = (merged_config.plugins || []).flat(Infinity); + for (let i = merged_config.plugins.length - 1; i > 0; i--) { + if (merged_config.plugins[i]?.name === 'vite-plugin-svelte-kit') { + merged_config.plugins.splice(i, 1); + } + } + process.env.VITE_SVELTEKIT_ADAPTER_NAME = config.kit.adapter?.name; const { chunks } = await create_build(merged_config); diff --git a/packages/kit/src/core/build/build_service_worker.js b/packages/kit/src/core/build/build_service_worker.js index 07a188b6aa55..38898a044b02 100644 --- a/packages/kit/src/core/build/build_service_worker.js +++ b/packages/kit/src/core/build/build_service_worker.js @@ -3,6 +3,7 @@ import * as vite from 'vite'; import { s } from '../../utils/misc.js'; import { deep_merge } from '../../utils/object.js'; import { normalize_path } from '../../utils/url.js'; +import { get_vite_config } from '../../vite/plugin.js'; import { print_config_conflicts } from '../config/index.js'; import { assets_base } from './utils.js'; @@ -66,8 +67,10 @@ export async function build_service_worker( .trim() ); + const vite_config = await get_vite_config(config, false); + /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge(await config.kit.vite(), { + const [merged_config, conflicts] = deep_merge(vite_config, { base: assets_base(config), build: { lib: { @@ -93,5 +96,12 @@ export async function build_service_worker( print_config_conflicts(conflicts, 'kit.vite.', 'build_service_worker'); + merged_config.plugins = (merged_config.plugins || []).flat(Infinity); + for (let i = merged_config.plugins.length - 1; i > 0; i--) { + if (merged_config.plugins[i]?.name === 'vite-plugin-svelte-kit') { + merged_config.plugins.splice(i, 1); + } + } + await vite.build(merged_config); } diff --git a/packages/kit/src/core/build/utils.js b/packages/kit/src/core/build/utils.js index 84d43e782d5e..def188d0de44 100644 --- a/packages/kit/src/core/build/utils.js +++ b/packages/kit/src/core/build/utils.js @@ -1,5 +1,4 @@ import * as vite from 'vite'; -import { svelte } from '../../vite/plugin.js'; import { get_aliases } from '../utils.js'; /** @@ -74,7 +73,6 @@ export const get_default_config = function ({ client_out_dir, config, input, out }, ssr }, - plugins: [svelte(config)], // prevent Vite copying the contents of `config.kit.files.assets`, // if it happens to be 'public' instead of 'static' publicDir: false, diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index bde44f360b3b..39e986991c10 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -70,7 +70,7 @@ export const sveltekit = function (svelte_config) { /** @type {[any, string[]]} */ const [merged_config, conflicts] = deep_merge( - await svelte_config.kit.vite(), + {}, get_default_config({ client_out_dir, config: svelte_config, @@ -82,44 +82,36 @@ export const sveltekit = function (svelte_config) { print_config_conflicts(conflicts, 'kit.vite.', 'build_client'); - merged_config.plugins.push(svelte_config); - return merged_config; } // dev and preview config can be shared - const [vite_config] = deep_merge( - { - preview: { - port: 3000, - strictPort: true - }, - 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/**` - ] - } + const vite_config = { + preview: { + port: 3000, + strictPort: true + }, + 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') + ]) + ] }, - spa: false + port: 3000, + strictPort: true, + watch: { + ignored: [`${svelte_config.kit.outDir}/**`, `!${svelte_config.kit.outDir}/generated/**`] + } }, - await svelte_config.kit.vite() - ); + spa: false + }; /** @type {[any, string[]]} */ const [merged_config, conflicts] = deep_merge(vite_config, { @@ -138,6 +130,7 @@ export const sveltekit = function (svelte_config) { base: '/' }); + // TODO: compare resolved config to defaults to validate print_config_conflicts(conflicts, 'kit.vite.'); return merged_config; @@ -185,6 +178,8 @@ export const sveltekit = function (svelte_config) { }, vite_manifest }; + log.info(`Client build completed. Wrote ${chunks.length} chunks and ${assets.length} assets`); + process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED = 'true'; const options = { cwd, @@ -196,6 +191,8 @@ export const sveltekit = function (svelte_config) { service_worker_entry_file: resolve_entry(svelte_config.kit.files.serviceWorker) }; + log.info('Building server'); + const server = await build_server(options, client); /** @type {import('types').BuildData} */ @@ -229,6 +226,8 @@ export const sveltekit = function (svelte_config) { } }); + log.info('Prerendering'); + const prerendered = await prerender({ config: svelte_config, entries: manifest_data.routes @@ -243,6 +242,8 @@ export const sveltekit = function (svelte_config) { throw new Error('Cannot use service worker alongside config.kit.paths.assets'); } + log.info('Building service worker'); + await build_service_worker(options, prerendered, client.vite_manifest); } @@ -272,6 +273,24 @@ export const sveltekit = function (svelte_config) { }; }; +/** + * @param {import('types').ValidatedConfig} svelte_config + * @param {boolean} [config_file] + * @return {Promise} + */ +export async function get_vite_config(svelte_config, config_file) { + for (const file of ['vite.config.js', 'vite.config.mjs', 'vite.config.cjs']) { + if (fs.existsSync(file)) { + return config_file === false ? await import(path.resolve(cwd, file)) : {}; + } + } + const vite_config = await svelte_config.kit.vite(); + if (config_file !== false) { + vite_config.plugins = [...(vite_config.plugins || []), ...(await plugins(svelte_config))]; + } + return vite_config; +} + /** * @param {import('types').ValidatedConfig} svelte_config * @return {import('vite').Plugin[]} @@ -293,5 +312,46 @@ export const svelte = function (svelte_config) { */ export const plugins = async function (svelte_config) { svelte_config = svelte_config || (await load_config()); - return [...svelte(svelte_config), sveltekit(svelte_config)]; + return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED + ? [...svelte(svelte_config)] + : [...svelte(svelte_config), sveltekit(svelte_config)]; +}; + + +/** + * type {import('vite').Plugin} +TODO: delete this debug plugin after switching to vite CLI +const sveltekit_validation = { + name: 'vite-plugin-svelte-kit-validation', + async configResolved(config) { + let svelte_count = 0; + let svelte_kit_count = 0; + for (const plugin of config.plugins.flat(Infinity)) { + if (plugin.name === 'vite-plugin-svelte') { + svelte_count++; + } else if (plugin.name === 'vite-plugin-svelte-kit') { + svelte_kit_count++; + } + } + + if (config.build.ssr) { + assert_plugin_count('vite-plugin-svelte', svelte_count, 1); + assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, 0); + } else { + assert_plugin_count('vite-plugin-svelte', svelte_count, 1); + assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, 1); + } + } }; +*/ + +/** + * param {string} name + * param {number} count + * param {number} expected_count +function assert_plugin_count(name, count, expected_count) { + if (count !== expected_count) { + throw Error(`Expected ${name} to be present ${expected_count} times, but found ${count}`); + } +} +*/ From 225e1c3b68b7a1b46b31a8a588041690dcde75a2 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 1 Jun 2022 00:34:38 -0700 Subject: [PATCH 06/62] add TODO --- packages/kit/src/vite/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 39e986991c10..57f8c9ef23b8 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -284,6 +284,7 @@ export async function get_vite_config(svelte_config, config_file) { return config_file === false ? await import(path.resolve(cwd, file)) : {}; } } + // TODO: stop reading Vite config from SvelteKit config or move to CLI const vite_config = await svelte_config.kit.vite(); if (config_file !== false) { vite_config.plugins = [...(vite_config.plugins || []), ...(await plugins(svelte_config))]; @@ -317,7 +318,6 @@ export const plugins = async function (svelte_config) { : [...svelte(svelte_config), sveltekit(svelte_config)]; }; - /** * type {import('vite').Plugin} TODO: delete this debug plugin after switching to vite CLI From 559a4139af3c3d010408927fd046ea7d4a5ec33d Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 1 Jun 2022 09:45:17 -0700 Subject: [PATCH 07/62] don't rename dev file for now --- .../src/{vite/dev.js => core/dev/plugin.js} | 18 +++++++++--------- packages/kit/src/vite/plugin.js | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) rename packages/kit/src/{vite/dev.js => core/dev/plugin.js} (96%) diff --git a/packages/kit/src/vite/dev.js b/packages/kit/src/core/dev/plugin.js similarity index 96% rename from packages/kit/src/vite/dev.js rename to packages/kit/src/core/dev/plugin.js index fc957174ad0b..341937b457f1 100644 --- a/packages/kit/src/vite/dev.js +++ b/packages/kit/src/core/dev/plugin.js @@ -3,15 +3,15 @@ import colors from 'kleur'; import path from 'path'; import sirv from 'sirv'; import { URL } from 'url'; -import { installPolyfills } from '../node/polyfills.js'; -import * as sync from '../core/sync/sync.js'; -import { getRequest, setResponse } from '../node/index.js'; -import { SVELTE_KIT_ASSETS } from '../core/constants.js'; -import { get_mime_lookup, get_runtime_path, resolve_entry } from '../core/utils.js'; -import { coalesce_to_error } from '../utils/error.js'; -import { load_template } from '../core/config/index.js'; -import { posixify } from '../utils/filesystem.js'; -import { parse_route_id } from '../utils/routing.js'; +import { getRequest, setResponse } from '../../node/index.js'; +import { installPolyfills } from '../../node/polyfills.js'; +import { coalesce_to_error } from '../../utils/error.js'; +import { posixify } from '../../utils/filesystem.js'; +import { parse_route_id } from '../../utils/routing.js'; +import { load_template } from '../config/index.js'; +import { SVELTE_KIT_ASSETS } from '../constants.js'; +import * as sync from '../sync/sync.js'; +import { get_mime_lookup, get_runtime_path, resolve_entry } from '../utils.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 diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 57f8c9ef23b8..875de11d5146 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -9,10 +9,10 @@ import { build_server } from '../core/build/build_server.js'; import { build_service_worker } from '../core/build/build_service_worker.js'; import { prerender } from '../core/build/prerender/prerender.js'; import { load_config, print_config_conflicts } from '../core/config/index.js'; +import { configure_server } from '../core/dev/plugin.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; import { deep_merge } from '../utils/object.js'; -import { configure_server } from './dev.js'; import { find_deps, get_default_config } from '../core/build/utils.js'; const cwd = process.cwd(); From 8fb89d422fc4564f43debeae87dbd1d9ea5c622e Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 1 Jun 2022 10:37:51 -0700 Subject: [PATCH 08/62] update API --- packages/kit/src/core/config/index.js | 17 ++++++++++--- packages/kit/src/vite/plugin.js | 35 ++++++++++++++++++--------- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index f79cffc9fcd5..fb1ad3e31d0f 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -36,18 +36,27 @@ export function load_template(cwd, config) { return fs.readFileSync(template, 'utf-8'); } +/** + * @returns {Promise} + */ export async function load_config({ cwd = process.cwd() } = {}) { const config_file = path.join(cwd, 'svelte.config.js'); if (!fs.existsSync(config_file)) { - throw new Error( - 'You need to create a svelte.config.js file. See https://kit.svelte.dev/docs/configuration' - ); + return process_config({}, { cwd }); } const config = await import(`${url.pathToFileURL(config_file).href}?ts=${Date.now()}`); - const validated = validate_config(config.default); + return process_config(config.default, { cwd }); +} + +/** + * @param {import('types').Config} config + * @returns {import('types').ValidatedConfig} + */ +export function process_config(config, { cwd = process.cwd() } = {}) { + const validated = validate_config(config); validated.kit.outDir = path.resolve(cwd, validated.kit.outDir); diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 875de11d5146..81b134de1e4a 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -8,7 +8,7 @@ import * as sync from '../core/sync/sync.js'; import { build_server } from '../core/build/build_server.js'; import { build_service_worker } from '../core/build/build_service_worker.js'; import { prerender } from '../core/build/prerender/prerender.js'; -import { load_config, print_config_conflicts } from '../core/config/index.js'; +import { print_config_conflicts, process_config } from '../core/config/index.js'; import { configure_server } from '../core/dev/plugin.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; @@ -287,35 +287,46 @@ export async function get_vite_config(svelte_config, config_file) { // TODO: stop reading Vite config from SvelteKit config or move to CLI const vite_config = await svelte_config.kit.vite(); if (config_file !== false) { - vite_config.plugins = [...(vite_config.plugins || []), ...(await plugins(svelte_config))]; + vite_config.plugins = [...(vite_config.plugins || []), ...plugins_internal(svelte_config)]; } return vite_config; } /** - * @param {import('types').ValidatedConfig} svelte_config + * @param {import('types').Config} svelte_config + * @param {boolean} hydratable * @return {import('vite').Plugin[]} */ -export const svelte = function (svelte_config) { +export const svelte = function (svelte_config, hydratable) { return svelte_plugin({ ...svelte_config, compilerOptions: { - ...svelte_config.compilerOptions, - hydratable: !!svelte_config.kit.browser.hydrate + ...(svelte_config?.compilerOptions || {}), + hydratable }, configFile: false }); }; /** - * @param {import('types').ValidatedConfig} [svelte_config] - * @return {Promise} + * @param {import('types').Config} raw_svelte_config + * @return {import('vite').Plugin[]} + */ +export const plugins = function (raw_svelte_config) { + const svelte_config = process_config(raw_svelte_config, { cwd }); + return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED + ? [...svelte({}, !!svelte_config.kit.browser.hydrate)] + : [...svelte({}, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config)]; +}; + +/** + * @param {import('types').ValidatedConfig} svelte_config + * @return {import('vite').Plugin[]} */ -export const plugins = async function (svelte_config) { - svelte_config = svelte_config || (await load_config()); +const plugins_internal = function (svelte_config) { return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED - ? [...svelte(svelte_config)] - : [...svelte(svelte_config), sveltekit(svelte_config)]; + ? [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate)] + : [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config)]; }; /** From d59946b7ef4e11209ebf1d813c4226bb0f5ba59b Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:57:57 -0700 Subject: [PATCH 09/62] cleanup --- packages/kit/src/core/build/build_server.js | 9 ++------- .../kit/src/core/build/build_service_worker.js | 8 ++------ packages/kit/src/core/utils.js | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/kit/src/core/build/build_server.js b/packages/kit/src/core/build/build_server.js index e1fe7fce92e9..28466af3dfd3 100644 --- a/packages/kit/src/core/build/build_server.js +++ b/packages/kit/src/core/build/build_server.js @@ -3,7 +3,7 @@ import path from 'path'; import { mkdirp, posixify } from '../../utils/filesystem.js'; import { deep_merge } from '../../utils/object.js'; import { load_template, print_config_conflicts } from '../config/index.js'; -import { get_runtime_path, resolve_entry } from '../utils.js'; +import { get_runtime_path, remove_plugin, resolve_entry } from '../utils.js'; import { create_build, find_deps, get_default_config } from './utils.js'; import { s } from '../../utils/misc.js'; import { get_vite_config } from '../../vite/plugin.js'; @@ -205,12 +205,7 @@ export async function build_server(options, client) { print_config_conflicts(conflicts, 'kit.vite.', 'build_server'); - merged_config.plugins = (merged_config.plugins || []).flat(Infinity); - for (let i = merged_config.plugins.length - 1; i > 0; i--) { - if (merged_config.plugins[i]?.name === 'vite-plugin-svelte-kit') { - merged_config.plugins.splice(i, 1); - } - } + remove_plugin(merged_config, 'vite-plugin-svelte-kit'); process.env.VITE_SVELTEKIT_ADAPTER_NAME = config.kit.adapter?.name; diff --git a/packages/kit/src/core/build/build_service_worker.js b/packages/kit/src/core/build/build_service_worker.js index 38898a044b02..310fa8bd52a5 100644 --- a/packages/kit/src/core/build/build_service_worker.js +++ b/packages/kit/src/core/build/build_service_worker.js @@ -5,6 +5,7 @@ import { deep_merge } from '../../utils/object.js'; import { normalize_path } from '../../utils/url.js'; import { get_vite_config } from '../../vite/plugin.js'; import { print_config_conflicts } from '../config/index.js'; +import { remove_plugin } from '../utils.js'; import { assets_base } from './utils.js'; /** @@ -96,12 +97,7 @@ export async function build_service_worker( print_config_conflicts(conflicts, 'kit.vite.', 'build_service_worker'); - merged_config.plugins = (merged_config.plugins || []).flat(Infinity); - for (let i = merged_config.plugins.length - 1; i > 0; i--) { - if (merged_config.plugins[i]?.name === 'vite-plugin-svelte-kit') { - merged_config.plugins.splice(i, 1); - } - } + remove_plugin(merged_config, 'vite-plugin-svelte-kit'); await vite.build(merged_config); } diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index 642a7e7b2064..59bfc079e60d 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -96,3 +96,19 @@ export function get_aliases(config) { return alias; } + +/** + * @param {import('vite').UserConfig} config + * @param {string} name + */ +export function remove_plugin(config, name) { + // @ts-expect-error - it can't handle infinite type expansion + config.plugins = (config.plugins || []).flat(Infinity); + for (let i = config.plugins.length - 1; i > 0; i--) { + const plugin = config.plugins[i]; + // @ts-expect-error - it doesn't know about the `flat` call we just made + if (plugin && plugin?.name === name) { + config.plugins.splice(i, 1); + } + } +} From 4d600284cec19e0cb37f6cc256308b6ea875a3a1 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 1 Jun 2022 15:50:00 -0700 Subject: [PATCH 10/62] Update packages/kit/src/vite/plugin.js Co-authored-by: Rich Harris --- packages/kit/src/vite/plugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 81b134de1e4a..569493c9054d 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -18,10 +18,10 @@ import { find_deps, get_default_config } from '../core/build/utils.js'; const cwd = process.cwd(); /** - * @param {import('types').ValidatedConfig} svelte_config + * @param {import('types').Config['kit']} svelte_config * @return {import('vite').Plugin} */ -export const sveltekit = function (svelte_config) { +export const sveltekit = function (svelte_config = {}) { const build_dir = path.join(svelte_config.kit.outDir, 'build'); const output_dir = path.join(svelte_config.kit.outDir, 'output'); const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; From d858c534405d157f29f087b92808f83274ba9826 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:29:38 -0700 Subject: [PATCH 11/62] Revert "Update packages/kit/src/vite/plugin.js" This reverts commit 4d600284cec19e0cb37f6cc256308b6ea875a3a1. --- packages/kit/src/vite/plugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 569493c9054d..81b134de1e4a 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -18,10 +18,10 @@ import { find_deps, get_default_config } from '../core/build/utils.js'; const cwd = process.cwd(); /** - * @param {import('types').Config['kit']} svelte_config + * @param {import('types').ValidatedConfig} svelte_config * @return {import('vite').Plugin} */ -export const sveltekit = function (svelte_config = {}) { +export const sveltekit = function (svelte_config) { const build_dir = path.join(svelte_config.kit.outDir, 'build'); const output_dir = path.join(svelte_config.kit.outDir, 'output'); const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; From ad7e9f4af44aac6f0287cf03f7aa454f9f3cae1f Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 2 Jun 2022 13:17:50 -0700 Subject: [PATCH 12/62] enable validation plugin --- packages/kit/src/vite/plugin.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 81b134de1e4a..58d98862a5b2 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -330,14 +330,17 @@ const plugins_internal = function (svelte_config) { }; /** - * type {import('vite').Plugin} -TODO: delete this debug plugin after switching to vite CLI + * While we're supporting svelte.config.js and vite.config.js it's very easy + * to end up with duplicate plugins, which is hard to debug. Ensure we avoid that. + * @type {import('vite').Plugin} + */ const sveltekit_validation = { name: 'vite-plugin-svelte-kit-validation', async configResolved(config) { let svelte_count = 0; let svelte_kit_count = 0; - for (const plugin of config.plugins.flat(Infinity)) { + const plugins = config.plugins.flat(Infinity); + for (const plugin of plugins) { if (plugin.name === 'vite-plugin-svelte') { svelte_count++; } else if (plugin.name === 'vite-plugin-svelte-kit') { @@ -354,15 +357,14 @@ const sveltekit_validation = { } } }; -*/ /** - * param {string} name - * param {number} count - * param {number} expected_count + * @param {string} name + * @param {number} count + * @param {number} expected_count + */ function assert_plugin_count(name, count, expected_count) { if (count !== expected_count) { throw Error(`Expected ${name} to be present ${expected_count} times, but found ${count}`); } } -*/ From db7cdb436b8da1f67efa0d61a48524c136cabe3d Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 2 Jun 2022 19:26:51 -0700 Subject: [PATCH 13/62] enable validation for real this time --- packages/kit/src/vite/plugin.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 58d98862a5b2..4ba897ac5cf1 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -315,8 +315,8 @@ export const svelte = function (svelte_config, hydratable) { export const plugins = function (raw_svelte_config) { const svelte_config = process_config(raw_svelte_config, { cwd }); return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED - ? [...svelte({}, !!svelte_config.kit.browser.hydrate)] - : [...svelte({}, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config)]; + ? [...svelte({}, !!svelte_config.kit.browser.hydrate), sveltekit_validation] + : [...svelte({}, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config), sveltekit_validation]; }; /** @@ -325,8 +325,8 @@ export const plugins = function (raw_svelte_config) { */ const plugins_internal = function (svelte_config) { return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED - ? [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate)] - : [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config)]; + ? [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate), sveltekit_validation] + : [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config), sveltekit_validation]; }; /** @@ -336,7 +336,7 @@ const plugins_internal = function (svelte_config) { */ const sveltekit_validation = { name: 'vite-plugin-svelte-kit-validation', - async configResolved(config) { + configResolved(config) { let svelte_count = 0; let svelte_kit_count = 0; const plugins = config.plugins.flat(Infinity); @@ -347,13 +347,12 @@ const sveltekit_validation = { svelte_kit_count++; } } - if (config.build.ssr) { assert_plugin_count('vite-plugin-svelte', svelte_count, 1); assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, 0); } else { assert_plugin_count('vite-plugin-svelte', svelte_count, 1); - assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, 1); + assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? 0 : 1); } } }; @@ -365,6 +364,6 @@ const sveltekit_validation = { */ function assert_plugin_count(name, count, expected_count) { if (count !== expected_count) { - throw Error(`Expected ${name} to be present ${expected_count} times, but found ${count}`); + throw new Error(`Expected ${name} to be present ${expected_count} times, but found ${count}`); } } From 9092e9f1273526a3f55aa1597803a94d8659b892 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 2 Jun 2022 20:56:46 -0700 Subject: [PATCH 14/62] add validation plugin to all builds --- packages/kit/src/core/build/build_server.js | 3 ++- packages/kit/src/core/build/build_service_worker.js | 3 ++- packages/kit/src/vite/plugin.js | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/core/build/build_server.js b/packages/kit/src/core/build/build_server.js index 28466af3dfd3..baaccbc488b7 100644 --- a/packages/kit/src/core/build/build_server.js +++ b/packages/kit/src/core/build/build_server.js @@ -6,7 +6,7 @@ import { load_template, print_config_conflicts } from '../config/index.js'; import { get_runtime_path, remove_plugin, resolve_entry } from '../utils.js'; import { create_build, find_deps, get_default_config } from './utils.js'; import { s } from '../../utils/misc.js'; -import { get_vite_config } from '../../vite/plugin.js'; +import { get_vite_config, sveltekit_validation } from '../../vite/plugin.js'; /** * @param {{ @@ -181,6 +181,7 @@ export async function build_server(options, client) { build: { target: 'node14.8' }, + plugins: [sveltekit_validation], ssr: { // when developing against the Kit src code, we want to ensure that // our dependencies are bundled so that apps don't need to install diff --git a/packages/kit/src/core/build/build_service_worker.js b/packages/kit/src/core/build/build_service_worker.js index 310fa8bd52a5..9fda020dc851 100644 --- a/packages/kit/src/core/build/build_service_worker.js +++ b/packages/kit/src/core/build/build_service_worker.js @@ -3,7 +3,7 @@ import * as vite from 'vite'; import { s } from '../../utils/misc.js'; import { deep_merge } from '../../utils/object.js'; import { normalize_path } from '../../utils/url.js'; -import { get_vite_config } from '../../vite/plugin.js'; +import { get_vite_config, sveltekit_validation } from '../../vite/plugin.js'; import { print_config_conflicts } from '../config/index.js'; import { remove_plugin } from '../utils.js'; import { assets_base } from './utils.js'; @@ -87,6 +87,7 @@ export async function build_service_worker( outDir: `${output_dir}/client`, emptyOutDir: false }, + plugins: [sveltekit_validation], resolve: { alias: { '$service-worker': service_worker, diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 4ba897ac5cf1..37f2cdd1874d 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -334,7 +334,7 @@ const plugins_internal = function (svelte_config) { * to end up with duplicate plugins, which is hard to debug. Ensure we avoid that. * @type {import('vite').Plugin} */ -const sveltekit_validation = { +export const sveltekit_validation = { name: 'vite-plugin-svelte-kit-validation', configResolved(config) { let svelte_count = 0; From 168be56ec685c8f8c35dd3177fcf911c449edd74 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 2 Jun 2022 21:04:48 -0700 Subject: [PATCH 15/62] format --- packages/kit/src/vite/plugin.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 37f2cdd1874d..6ea8adb06d41 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -316,7 +316,11 @@ export const plugins = function (raw_svelte_config) { const svelte_config = process_config(raw_svelte_config, { cwd }); return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? [...svelte({}, !!svelte_config.kit.browser.hydrate), sveltekit_validation] - : [...svelte({}, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config), sveltekit_validation]; + : [ + ...svelte({}, !!svelte_config.kit.browser.hydrate), + sveltekit(svelte_config), + sveltekit_validation + ]; }; /** @@ -326,7 +330,11 @@ export const plugins = function (raw_svelte_config) { const plugins_internal = function (svelte_config) { return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate), sveltekit_validation] - : [...svelte(svelte_config, !!svelte_config.kit.browser.hydrate), sveltekit(svelte_config), sveltekit_validation]; + : [ + ...svelte(svelte_config, !!svelte_config.kit.browser.hydrate), + sveltekit(svelte_config), + sveltekit_validation + ]; }; /** @@ -352,7 +360,11 @@ export const sveltekit_validation = { assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, 0); } else { assert_plugin_count('vite-plugin-svelte', svelte_count, 1); - assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? 0 : 1); + assert_plugin_count( + 'vite-plugin-svelte-kit', + svelte_kit_count, + process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? 0 : 1 + ); } } }; From 1ef709d8c9447132af2df39cc36c1097145d0d0f Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 2 Jun 2022 21:36:31 -0700 Subject: [PATCH 16/62] fix plugin handling --- packages/kit/src/core/build/build_server.js | 4 ++-- .../kit/src/core/build/build_service_worker.js | 4 ++-- packages/kit/src/core/utils.js | 14 +++++++++++--- packages/kit/src/vite/index.js | 2 ++ packages/kit/src/vite/plugin.js | 17 ++++++----------- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/kit/src/core/build/build_server.js b/packages/kit/src/core/build/build_server.js index baaccbc488b7..a3dbc134a1a6 100644 --- a/packages/kit/src/core/build/build_server.js +++ b/packages/kit/src/core/build/build_server.js @@ -3,7 +3,7 @@ import path from 'path'; import { mkdirp, posixify } from '../../utils/filesystem.js'; import { deep_merge } from '../../utils/object.js'; import { load_template, print_config_conflicts } from '../config/index.js'; -import { get_runtime_path, remove_plugin, resolve_entry } from '../utils.js'; +import { ensure_plugins, get_runtime_path, resolve_entry } from '../utils.js'; import { create_build, find_deps, get_default_config } from './utils.js'; import { s } from '../../utils/misc.js'; import { get_vite_config, sveltekit_validation } from '../../vite/plugin.js'; @@ -206,7 +206,7 @@ export async function build_server(options, client) { print_config_conflicts(conflicts, 'kit.vite.', 'build_server'); - remove_plugin(merged_config, 'vite-plugin-svelte-kit'); + ensure_plugins(merged_config, true); process.env.VITE_SVELTEKIT_ADAPTER_NAME = config.kit.adapter?.name; diff --git a/packages/kit/src/core/build/build_service_worker.js b/packages/kit/src/core/build/build_service_worker.js index 9fda020dc851..c2d5e98ae9c6 100644 --- a/packages/kit/src/core/build/build_service_worker.js +++ b/packages/kit/src/core/build/build_service_worker.js @@ -5,7 +5,7 @@ import { deep_merge } from '../../utils/object.js'; import { normalize_path } from '../../utils/url.js'; import { get_vite_config, sveltekit_validation } from '../../vite/plugin.js'; import { print_config_conflicts } from '../config/index.js'; -import { remove_plugin } from '../utils.js'; +import { ensure_plugins } from '../utils.js'; import { assets_base } from './utils.js'; /** @@ -98,7 +98,7 @@ export async function build_service_worker( print_config_conflicts(conflicts, 'kit.vite.', 'build_service_worker'); - remove_plugin(merged_config, 'vite-plugin-svelte-kit'); + ensure_plugins(merged_config); await vite.build(merged_config); } diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index 59bfc079e60d..0c2ce728b7b2 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -1,3 +1,4 @@ +import { svelte } from '@sveltejs/vite-plugin-svelte'; import fs from 'fs'; import path from 'path'; import colors from 'kleur'; @@ -99,16 +100,23 @@ export function get_aliases(config) { /** * @param {import('vite').UserConfig} config - * @param {string} name + * @param {boolean} [add_svelte] */ -export function remove_plugin(config, name) { +export function ensure_plugins(config, add_svelte) { // @ts-expect-error - it can't handle infinite type expansion config.plugins = (config.plugins || []).flat(Infinity); + let has_svelte_plugin = false; for (let i = config.plugins.length - 1; i > 0; i--) { const plugin = config.plugins[i]; // @ts-expect-error - it doesn't know about the `flat` call we just made - if (plugin && plugin?.name === name) { + if (plugin?.name === 'vite-plugin-svelte-kit') { config.plugins.splice(i, 1); + // @ts-expect-error - it doesn't know about the `flat` call we just made + } else if (plugin?.name === 'vite-plugin-svelte') { + has_svelte_plugin = true; } } + if (add_svelte && !has_svelte_plugin && !process.env.SVELTE_VITE_CONFIG) { + config.plugins.push(svelte({})); + } } diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index aca3ef4a576b..3a393b14037d 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -1 +1,3 @@ export { plugins as sveltekit } from './plugin.js'; + +process.env.SVELTE_VITE_CONFIG = 'true'; diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 6ea8adb06d41..8c4ff4bc4e37 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -355,17 +355,12 @@ export const sveltekit_validation = { svelte_kit_count++; } } - if (config.build.ssr) { - assert_plugin_count('vite-plugin-svelte', svelte_count, 1); - assert_plugin_count('vite-plugin-svelte-kit', svelte_kit_count, 0); - } else { - assert_plugin_count('vite-plugin-svelte', svelte_count, 1); - assert_plugin_count( - 'vite-plugin-svelte-kit', - svelte_kit_count, - process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? 0 : 1 - ); - } + assert_plugin_count('vite-plugin-svelte', svelte_count, 1); + assert_plugin_count( + 'vite-plugin-svelte-kit', + svelte_kit_count, + process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? 0 : 1 + ); } }; From fbee989c7b22359df0c3756e273b9d08343d6690 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 2 Jun 2022 21:49:45 -0700 Subject: [PATCH 17/62] format --- packages/kit/src/core/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index 0c2ce728b7b2..60c73055df02 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -111,7 +111,7 @@ export function ensure_plugins(config, add_svelte) { // @ts-expect-error - it doesn't know about the `flat` call we just made if (plugin?.name === 'vite-plugin-svelte-kit') { config.plugins.splice(i, 1); - // @ts-expect-error - it doesn't know about the `flat` call we just made + // @ts-expect-error - it doesn't know about the `flat` call we just made } else if (plugin?.name === 'vite-plugin-svelte') { has_svelte_plugin = true; } From d7ab6123b51294f32510e98d918cdf832efaf1a0 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Tue, 7 Jun 2022 11:44:51 -0700 Subject: [PATCH 18/62] cleanup API --- packages/kit/src/cli.js | 4 +- packages/kit/src/core/config/index.js | 2 +- packages/kit/src/core/dev/plugin.js | 611 ++++++++++++------------- packages/kit/src/core/preview/index.js | 257 +++++------ packages/kit/src/vite/plugin.js | 67 ++- 5 files changed, 472 insertions(+), 469 deletions(-) diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 01d6923a7377..369e8225c7c5 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -175,14 +175,14 @@ prog process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - const { sveltekit_plugin } = await import('./core/preview/index.js'); + const { sveltekit } = await import('./vite/plugin.js'); const svelte_config = await load_config(); const vite_config = await svelte_config.kit.vite(); /** @type {import('vite').UserConfig} */ const config = { ...vite_config, - plugins: [...(vite_config.plugins || []), sveltekit_plugin] + plugins: [...(vite_config.plugins || []), sveltekit()] }; config.preview = config.preview || {}; diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 50984b6039bc..7acfae374d0a 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -59,7 +59,7 @@ export async function load_config({ cwd = process.cwd() } = {}) { * @param {import('types').Config} config * @returns {import('types').ValidatedConfig} */ -export function process_config(config, { cwd = process.cwd() } = {}) { +function process_config(config, { cwd = process.cwd() } = {}) { const validated = validate_config(config); validated.kit.outDir = path.resolve(cwd, validated.kit.outDir); diff --git a/packages/kit/src/core/dev/plugin.js b/packages/kit/src/core/dev/plugin.js index 8fe9136d6378..5d7b3e8a7542 100644 --- a/packages/kit/src/core/dev/plugin.js +++ b/packages/kit/src/core/dev/plugin.js @@ -20,359 +20,356 @@ const style_pattern = /\.(css|less|sass|scss|styl|stylus|pcss|postcss)$/; const cwd = process.cwd(); /** + * @param {import('vite').ViteDevServer} vite * @param {import('types').ValidatedConfig} svelte_config - * @return {import('vite').ServerHook} + * @return {Promise void>>} */ -export const configure_server = function (svelte_config) { - return async function (vite) { - installPolyfills(); +export const configure_server = async function (vite, svelte_config) { + installPolyfills(); - sync.init(svelte_config); + sync.init(svelte_config); - const runtime = get_runtime_path(svelte_config.kit); + const runtime = get_runtime_path(svelte_config.kit); - process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = '0'; + 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').Respond} */ + const respond = (await import(`${runtime}/server/index.js`)).respond; - /** @type {import('types').SSRManifest} */ - let manifest; + /** @type {import('types').SSRManifest} */ + let manifest; - function update_manifest() { - const { manifest_data } = sync.update(svelte_config); + 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, index) => { - return async () => { - const url = id.startsWith('..') ? `/@fs${path.posix.resolve(id)}` : `/${id}`; + 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, index) => { + 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 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, - index, - entry: url.endsWith('.svelte') ? url : url + '?import', - css: [], - js: [], - // in dev we inline all styles to avoid FOUC - styles - }; + return { + module, + index, + 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; } - } - }; - } - - /** @param {Error} error */ - function fix_stack_trace(error) { - return error.stack ? vite.ssrRewriteStacktrace(error.stack) : error.stack; - } - update_manifest(); + 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`); + } + } - for (const event of ['add', 'unlink']) { - vite.watcher.on(event, (file) => { - if (file.startsWith(svelte_config.kit.files.routes + path.sep)) { - update_manifest(); + return matchers; } - }); - } - - 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' - ); - - remove_html_middlewares(vite.middlewares); - - 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 - }`; + /** @param {Error} error */ + function fix_stack_trace(error) { + return error.stack ? vite.ssrRewriteStacktrace(error.stack) : error.stack; + } - const decoded = decodeURI(new URL(base + req.url).pathname); + update_manifest(); - if (decoded.startsWith(assets)) { - const pathname = decoded.slice(assets.length); - const file = svelte_config.kit.files.assets + pathname; + for (const event of ['add', 'unlink']) { + vite.watcher.on(event, (file) => { + if (file.startsWith(svelte_config.kit.files.routes + path.sep)) { + update_manifest(); + } + }); + } - if (fs.existsSync(file) && !fs.statSync(file).isDirectory()) { - if (has_correct_case(file, svelte_config.kit.files.assets)) { - req.url = encodeURI(pathname); // don't need query/hash - asset_server(req, res); - return; - } + 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' + ); + + remove_html_middlewares(vite.middlewares); + + 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 decoded = decodeURI(new URL(base + req.url).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()) { + if (has_correct_case(file, svelte_config.kit.files.assets)) { + req.url = encodeURI(pathname); // don't need query/hash + asset_server(req, res); + return; } } + } - if (!decoded.startsWith(svelte_config.kit.paths.base)) { - return not_found( - res, - `Not found (did you mean ${svelte_config.kit.paths.base + req.url}?)` - ); - } - - /** @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' - ); - } - - 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, `${svelte_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, `${svelte_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: svelte_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, svelte_config); - - 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); - } - - 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: svelte_config.compilerOptions.hydratable, - 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 + }), + 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.compilerOptions.hydratable, + 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); + } + }); }; }; diff --git a/packages/kit/src/core/preview/index.js b/packages/kit/src/core/preview/index.js index 4df9d39bbce7..b523e7fc9c21 100644 --- a/packages/kit/src/core/preview/index.js +++ b/packages/kit/src/core/preview/index.js @@ -5,161 +5,148 @@ import { pathToFileURL } from 'url'; import { getRequest, setResponse } from '../../node/index.js'; import { installPolyfills } from '../../node/polyfills.js'; import { SVELTE_KIT_ASSETS } from '../constants.js'; -import { load_config } from '../config/index.js'; /** @typedef {import('http').IncomingMessage} Req */ /** @typedef {import('http').ServerResponse} Res */ /** @typedef {(req: Req, res: Res, next: () => void) => void} Handler */ -/** @type {import('types').ValidatedConfig} */ -let config; - -/** @type {boolean} */ -let https; - -/** @type {import('vite').Plugin} */ -export const sveltekit_plugin = { - name: 'vite-plugin-svelte-kit', - async config(vite_config) { - // defaults - vite_config.preview = vite_config.preview || {}; - vite_config.preview.strictPort = vite_config.preview.strictPort ?? true; - - config = await load_config(); - }, - async configResolved(vite_config) { - https = !!vite_config.preview.https; - }, - async configurePreviewServer(vite) { - installPolyfills(); - - const { paths } = config.kit; - const base = paths.base; - const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base; - - const etag = `"${Date.now()}"`; - - const index_file = join(config.kit.outDir, 'output/server/index.js'); - const manifest_file = join(config.kit.outDir, 'output/server/manifest.js'); - - /** @type {import('types').ServerModule} */ - const { Server, override } = await import(pathToFileURL(index_file).href); - const { manifest } = await import(pathToFileURL(manifest_file).href); - - override({ - paths: { base, assets }, - prerendering: false, - protocol: https ? 'https' : 'http', - read: (file) => fs.readFileSync(join(config.kit.files.assets, file)) +/** + * @param {{ + * middlewares: import('connect').Server; + * httpServer: import('http').Server; + * }} vite + * @param {import('types').ValidatedConfig} config + * @param {import('vite').ResolvedConfig} vite_config + */ +export const configure_preview_server = async function (vite, config, vite_config) { + installPolyfills(); + + const { paths } = config.kit; + const base = paths.base; + const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base; + + const etag = `"${Date.now()}"`; + + const index_file = join(config.kit.outDir, 'output/server/index.js'); + const manifest_file = join(config.kit.outDir, 'output/server/manifest.js'); + + /** @type {import('types').ServerModule} */ + const { Server, override } = await import(pathToFileURL(index_file).href); + const { manifest } = await import(pathToFileURL(manifest_file).href); + + override({ + paths: { base, assets }, + prerendering: false, + protocol: vite_config.preview?.https ? 'https' : 'http', + read: (file) => fs.readFileSync(join(config.kit.files.assets, file)) + }); + + const server = new Server(manifest); + + return () => { + // files in `static` + vite.middlewares.use(scoped(assets, mutable(config.kit.files.assets))); + + // immutable generated client assets + vite.middlewares.use( + scoped( + assets, + sirv(join(config.kit.outDir, 'output/client'), { + setHeaders: (res, pathname) => { + // only apply to build directory, not e.g. version.json + if (pathname.startsWith(`/${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; + res.end(`Not found (did you mean ${base + pathname}?)`); + } }); - const server = new Server(manifest); - - return () => { - // files in `static` - vite.middlewares.use(scoped(assets, mutable(config.kit.files.assets))); - - // immutable generated client assets - vite.middlewares.use( - scoped( - assets, - sirv(join(config.kit.outDir, 'output/client'), { - setHeaders: (res, pathname) => { - // only apply to build directory, not e.g. version.json - if (pathname.startsWith(`/${config.kit.appDir}/immutable`)) { - res.setHeader('cache-control', 'public,max-age=31536000,immutable'); - } - } - }) - ) - ); + // prerendered dependencies + vite.middlewares.use( + scoped(base, mutable(join(config.kit.outDir, 'output/prerendered/dependencies'))) + ); - vite.middlewares.use((req, res, next) => { - const original_url = /** @type {string} */ (req.url); - const { pathname } = new URL(original_url, 'http://dummy'); + // 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) => { + let if_none_match_value = req.headers['if-none-match']; - if (pathname.startsWith(base)) { - next(); - } else { - res.statusCode = 404; - res.end(`Not found (did you mean ${base + pathname}?)`); + if (if_none_match_value?.startsWith('W/"')) { + if_none_match_value = if_none_match_value.substring(2); } - }); - // prerendered dependencies - vite.middlewares.use( - scoped(base, mutable(join(config.kit.outDir, 'output/prerendered/dependencies'))) - ); + if (if_none_match_value === etag) { + res.statusCode = 304; + res.end(); + return; + } - // 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) => { - let if_none_match_value = req.headers['if-none-match']; + const { pathname } = new URL(/** @type {string} */ (req.url), 'http://dummy'); - if (if_none_match_value?.startsWith('W/"')) { - if_none_match_value = if_none_match_value.substring(2); - } + // only treat this as a page if it doesn't include an extension + if (pathname === '/' || /\/[^./]+\/?$/.test(pathname)) { + const file = join( + config.kit.outDir, + 'output/prerendered/pages' + + pathname + + (pathname.endsWith('/') ? 'index.html' : '.html') + ); - if (if_none_match_value === etag) { - res.statusCode = 304; - res.end(); + if (fs.existsSync(file)) { + res.writeHead(200, { + 'content-type': 'text/html', + etag + }); + + fs.createReadStream(file).pipe(res); return; } + } - const { pathname } = new URL(/** @type {string} */ (req.url), 'http://dummy'); - - // only treat this as a page if it doesn't include an extension - if (pathname === '/' || /\/[^./]+\/?$/.test(pathname)) { - const file = join( - config.kit.outDir, - 'output/prerendered/pages' + - pathname + - (pathname.endsWith('/') ? 'index.html' : '.html') - ); - - if (fs.existsSync(file)) { - res.writeHead(200, { - 'content-type': 'text/html', - etag - }); - - fs.createReadStream(file).pipe(res); - return; - } + next(); + }) + ); + + // SSR + vite.middlewares.use(async (req, res) => { + const protocol = vite_config.preview?.https ? 'https' : 'http'; + const host = req.headers['host']; + + let request; + + try { + request = await getRequest(`${protocol}://${host}`, req); + } catch (/** @type {any} */ err) { + res.statusCode = err.status || 400; + return res.end(err.reason || 'Invalid request body'); + } + + setResponse( + res, + await server.respond(request, { + getClientAddress: () => { + const { remoteAddress } = req.socket; + if (remoteAddress) return remoteAddress; + throw new Error('Could not determine clientAddress'); } - - next(); }) ); - - // SSR - vite.middlewares.use(async (req, res) => { - const protocol = https ? 'https' : 'http'; - const host = req.headers['host']; - - let request; - - try { - request = await getRequest(`${protocol}://${host}`, req); - } catch (/** @type {any} */ err) { - res.statusCode = err.status || 400; - return res.end(err.reason || 'Invalid request body'); - } - - setResponse( - res, - await server.respond(request, { - getClientAddress: () => { - const { remoteAddress } = req.socket; - if (remoteAddress) return remoteAddress; - throw new Error('Could not determine clientAddress'); - } - }) - ); - }); - }; - } + }); + }; }; /** diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index bc0bdfb23f56..86498a7cba95 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -8,27 +8,25 @@ import * as sync from '../core/sync/sync.js'; import { build_server } from '../core/build/build_server.js'; import { build_service_worker } from '../core/build/build_service_worker.js'; import { prerender } from '../core/build/prerender/prerender.js'; -import { print_config_conflicts, process_config } from '../core/config/index.js'; +import { load_config, print_config_conflicts } from '../core/config/index.js'; import { configure_server } from '../core/dev/plugin.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; import { deep_merge } from '../utils/object.js'; import { find_deps, get_default_config } from '../core/build/utils.js'; +import { configure_preview_server } from '../core/preview/index.js'; const cwd = process.cwd(); /** - * @param {import('types').ValidatedConfig} svelte_config * @return {import('vite').Plugin} */ -export const sveltekit = function (svelte_config) { - const build_dir = path.join(svelte_config.kit.outDir, 'build'); - const output_dir = path.join(svelte_config.kit.outDir, 'output'); - const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; - const client_entry_file = path.relative( - cwd, - `${get_runtime_path(svelte_config.kit)}/client/start.js` - ); +export const sveltekit = function () { + /** @type {import('types').ValidatedConfig} */ + let svelte_config; + + /** @type {import('vite').ResolvedConfig} */ + let vite_config; /** @type {import('types').ManifestData|undefined} */ let manifest_data = undefined; @@ -37,6 +35,16 @@ export const sveltekit = function (svelte_config) { name: 'vite-plugin-svelte-kit', async config(_config, env) { + svelte_config = await load_config(); + + const build_dir = path.join(svelte_config.kit.outDir, 'build'); + const output_dir = path.join(svelte_config.kit.outDir, 'output'); + const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; + const client_entry_file = path.relative( + cwd, + `${get_runtime_path(svelte_config.kit)}/client/start.js` + ); + if (env.command === 'build') { rimraf(build_dir); mkdirp(build_dir); @@ -136,11 +144,23 @@ export const sveltekit = function (svelte_config) { return merged_config; }, + configResolved(config) { + vite_config = config; + }, + async writeBundle(_options, bundle) { if (!manifest_data) throw Error('manifest_data not populated'); const log = logger({ verbose: !!process.env.VERBOSE }); + const build_dir = path.join(svelte_config.kit.outDir, 'build'); + const output_dir = path.join(svelte_config.kit.outDir, 'output'); + const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; + const client_entry_file = path.relative( + cwd, + `${get_runtime_path(svelte_config.kit)}/client/start.js` + ); + /** @type {import('rollup').OutputChunk[]} */ const chunks = []; /** @type {import('rollup').OutputAsset[]} */ @@ -267,9 +287,13 @@ export const sveltekit = function (svelte_config) { ); }, - configureServer: configure_server(svelte_config) + async configureServer(vite) { + return await configure_server(vite, svelte_config); + }, - // TODO: implement configurePreviewServer for Vite 3 + async configurePreviewServer(vite) { + return await configure_preview_server(vite, svelte_config, vite_config); + } }; }; @@ -287,41 +311,36 @@ export async function get_vite_config(svelte_config, config_file) { // TODO: stop reading Vite config from SvelteKit config or move to CLI const vite_config = await svelte_config.kit.vite(); if (config_file !== false) { - vite_config.plugins = [...(vite_config.plugins || []), ...plugins_internal(svelte_config)]; + vite_config.plugins = [...(vite_config.plugins || []), ...plugins_internal()]; } return vite_config; } /** - * @param {import('types').Config} [svelte_config] * @return {import('vite').Plugin[]} */ -export const svelte = function (svelte_config) { +export const svelte = function () { return svelte_plugin({ - ...(svelte_config || {}), configFile: false }); }; /** - * @param {import('types').Config} raw_svelte_config * @return {import('vite').Plugin[]} */ -export const plugins = function (raw_svelte_config) { - const svelte_config = process_config(raw_svelte_config, { cwd }); +export const plugins = function () { return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? [...svelte(), sveltekit_validation] - : [...svelte(), sveltekit(svelte_config), sveltekit_validation]; + : [...svelte(), sveltekit(), sveltekit_validation]; }; /** - * @param {import('types').ValidatedConfig} svelte_config * @return {import('vite').Plugin[]} */ -const plugins_internal = function (svelte_config) { +const plugins_internal = function () { return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED - ? [...svelte(svelte_config), sveltekit_validation] - : [...svelte(svelte_config), sveltekit(svelte_config), sveltekit_validation]; + ? [...svelte(), sveltekit_validation] + : [...svelte(), sveltekit(), sveltekit_validation]; }; /** From 1e1cf51be666c28a1252a63a6ae74ad3a484bc19 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Tue, 7 Jun 2022 19:32:19 -0700 Subject: [PATCH 19/62] remove configFile: false --- packages/kit/src/vite/plugin.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 86498a7cba95..efaef82442d7 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -320,9 +320,7 @@ export async function get_vite_config(svelte_config, config_file) { * @return {import('vite').Plugin[]} */ export const svelte = function () { - return svelte_plugin({ - configFile: false - }); + return svelte_plugin(); }; /** From 2396a1efe33e217bb809202e985f8fd6a5b6406d Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Tue, 7 Jun 2022 19:43:38 -0700 Subject: [PATCH 20/62] fix validation plugin --- packages/kit/src/vite/plugin.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index efaef82442d7..9e1e2c59dbd6 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -215,6 +215,8 @@ export const sveltekit = function () { const server = await build_server(options, client); + process.env.SVELTEKIT_SERVER_BUILD_COMPLETED = 'true'; + /** @type {import('types').BuildData} */ const build_data = { app_dir: svelte_config.kit.appDir, @@ -359,7 +361,11 @@ export const sveltekit_validation = { svelte_kit_count++; } } - assert_plugin_count('vite-plugin-svelte', svelte_count, 1); + assert_plugin_count( + 'vite-plugin-svelte', + svelte_count, + process.env.SVELTEKIT_SERVER_BUILD_COMPLETED ? 0 : 1 + ); assert_plugin_count( 'vite-plugin-svelte-kit', svelte_kit_count, From 1a5e933eed7d9f766ece416c1d3ceac7f441da55 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Tue, 7 Jun 2022 20:04:57 -0700 Subject: [PATCH 21/62] fix preview --- packages/kit/src/cli.js | 4 +++- packages/kit/src/vite/plugin.js | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 369e8225c7c5..5a06c9c1ecc9 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -179,10 +179,12 @@ prog const svelte_config = await load_config(); const vite_config = await svelte_config.kit.vite(); + const has_vite_config = fs.existsSync('vite.config.js'); + /** @type {import('vite').UserConfig} */ const config = { ...vite_config, - plugins: [...(vite_config.plugins || []), sveltekit()] + plugins: [...(vite_config.plugins || []), has_vite_config ? [] : sveltekit()] }; config.preview = config.preview || {}; diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 9e1e2c59dbd6..c9190cea0283 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -338,6 +338,9 @@ export const plugins = function () { * @return {import('vite').Plugin[]} */ const plugins_internal = function () { + if (process.env.SVELTE_VITE_CONFIG) { + return [sveltekit_validation]; + } return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? [...svelte(), sveltekit_validation] : [...svelte(), sveltekit(), sveltekit_validation]; From 554517f8ee2091d3be1d67808a78afec0f12e811 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 22 Jun 2022 11:53:00 -0400 Subject: [PATCH 22/62] Update healthy-carrots-cross.md --- .changeset/healthy-carrots-cross.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/healthy-carrots-cross.md b/.changeset/healthy-carrots-cross.md index bb969d08859c..2ed5c7d3ac10 100644 --- a/.changeset/healthy-carrots-cross.md +++ b/.changeset/healthy-carrots-cross.md @@ -2,4 +2,4 @@ '@sveltejs/kit': patch --- -Expose Vite plugin as @sveltejs/kit/vite +Expose Vite plugin as @sveltejs/kit/experimental/vite From 5912f299867696a532178918e4e36cc099a6d9fd Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 10:02:41 -0400 Subject: [PATCH 23/62] move dev/build/preview inside vite plugin --- .../kit/src/{core => vite}/build/build_server.js | 6 +++--- .../src/{core => vite}/build/build_service_worker.js | 6 +++--- .../kit/src/{core => vite}/build/prerender/crawl.js | 0 .../src/{core => vite}/build/prerender/crawl.spec.js | 0 .../build/prerender/fixtures/basic-href/input.html | 0 .../build/prerender/fixtures/basic-href/output.json | 0 .../build/prerender/fixtures/basic-src/input.html | 0 .../build/prerender/fixtures/basic-src/output.json | 0 .../build/prerender/fixtures/basic-srcset/input.html | 0 .../prerender/fixtures/basic-srcset/output.json | 0 .../fixtures/include-rel-external/input.html | 0 .../fixtures/include-rel-external/output.json | 0 .../fixtures/unquoted-attributes/input.html | 0 .../fixtures/unquoted-attributes/output.json | 0 .../src/{core => vite}/build/prerender/prerender.js | 0 .../kit/src/{core => vite}/build/prerender/queue.js | 0 .../src/{core => vite}/build/prerender/queue.spec.js | 0 packages/kit/src/{core => vite}/build/utils.js | 2 +- packages/kit/src/{core => vite}/dev/plugin.js | 8 ++++---- packages/kit/src/vite/plugin.js | 12 ++++++------ packages/kit/src/{core => vite}/preview/index.js | 2 +- 21 files changed, 18 insertions(+), 18 deletions(-) rename packages/kit/src/{core => vite}/build/build_server.js (98%) rename packages/kit/src/{core => vite}/build/build_service_worker.js (93%) rename packages/kit/src/{core => vite}/build/prerender/crawl.js (100%) rename packages/kit/src/{core => vite}/build/prerender/crawl.spec.js (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/basic-href/input.html (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/basic-href/output.json (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/basic-src/input.html (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/basic-src/output.json (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/basic-srcset/input.html (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/basic-srcset/output.json (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/include-rel-external/input.html (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/include-rel-external/output.json (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/unquoted-attributes/input.html (100%) rename packages/kit/src/{core => vite}/build/prerender/fixtures/unquoted-attributes/output.json (100%) rename packages/kit/src/{core => vite}/build/prerender/prerender.js (100%) rename packages/kit/src/{core => vite}/build/prerender/queue.js (100%) rename packages/kit/src/{core => vite}/build/prerender/queue.spec.js (100%) rename packages/kit/src/{core => vite}/build/utils.js (98%) rename packages/kit/src/{core => vite}/dev/plugin.js (98%) rename packages/kit/src/{core => vite}/preview/index.js (98%) diff --git a/packages/kit/src/core/build/build_server.js b/packages/kit/src/vite/build/build_server.js similarity index 98% rename from packages/kit/src/core/build/build_server.js rename to packages/kit/src/vite/build/build_server.js index 11f50f32f2bc..6c7f046c5276 100644 --- a/packages/kit/src/core/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -2,11 +2,11 @@ import fs from 'fs'; import path from 'path'; import { mkdirp, posixify } from '../../utils/filesystem.js'; import { deep_merge } from '../../utils/object.js'; -import { load_template, print_config_conflicts } from '../config/index.js'; -import { ensure_plugins, get_runtime_path, resolve_entry } from '../utils.js'; +import { load_template, print_config_conflicts } from '../../core/config/index.js'; +import { ensure_plugins, get_runtime_path, resolve_entry } from '../../core/utils.js'; import { create_build, find_deps, get_default_config } from './utils.js'; import { s } from '../../utils/misc.js'; -import { get_vite_config, sveltekit_validation } from '../../vite/plugin.js'; +import { get_vite_config, sveltekit_validation } from '../plugin.js'; /** * @param {{ diff --git a/packages/kit/src/core/build/build_service_worker.js b/packages/kit/src/vite/build/build_service_worker.js similarity index 93% rename from packages/kit/src/core/build/build_service_worker.js rename to packages/kit/src/vite/build/build_service_worker.js index 76b8cb5eaca1..1c136e702a67 100644 --- a/packages/kit/src/core/build/build_service_worker.js +++ b/packages/kit/src/vite/build/build_service_worker.js @@ -3,9 +3,9 @@ import * as vite from 'vite'; import { s } from '../../utils/misc.js'; import { deep_merge } from '../../utils/object.js'; import { normalize_path } from '../../utils/url.js'; -import { get_vite_config, sveltekit_validation } from '../../vite/plugin.js'; -import { print_config_conflicts } from '../config/index.js'; -import { ensure_plugins } from '../utils.js'; +import { get_vite_config, sveltekit_validation } from '../plugin.js'; +import { print_config_conflicts } from '../../core/config/index.js'; +import { ensure_plugins } from '../../core/utils.js'; import { assets_base } from './utils.js'; /** diff --git a/packages/kit/src/core/build/prerender/crawl.js b/packages/kit/src/vite/build/prerender/crawl.js similarity index 100% rename from packages/kit/src/core/build/prerender/crawl.js rename to packages/kit/src/vite/build/prerender/crawl.js diff --git a/packages/kit/src/core/build/prerender/crawl.spec.js b/packages/kit/src/vite/build/prerender/crawl.spec.js similarity index 100% rename from packages/kit/src/core/build/prerender/crawl.spec.js rename to packages/kit/src/vite/build/prerender/crawl.spec.js diff --git a/packages/kit/src/core/build/prerender/fixtures/basic-href/input.html b/packages/kit/src/vite/build/prerender/fixtures/basic-href/input.html similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/basic-href/input.html rename to packages/kit/src/vite/build/prerender/fixtures/basic-href/input.html diff --git a/packages/kit/src/core/build/prerender/fixtures/basic-href/output.json b/packages/kit/src/vite/build/prerender/fixtures/basic-href/output.json similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/basic-href/output.json rename to packages/kit/src/vite/build/prerender/fixtures/basic-href/output.json diff --git a/packages/kit/src/core/build/prerender/fixtures/basic-src/input.html b/packages/kit/src/vite/build/prerender/fixtures/basic-src/input.html similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/basic-src/input.html rename to packages/kit/src/vite/build/prerender/fixtures/basic-src/input.html diff --git a/packages/kit/src/core/build/prerender/fixtures/basic-src/output.json b/packages/kit/src/vite/build/prerender/fixtures/basic-src/output.json similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/basic-src/output.json rename to packages/kit/src/vite/build/prerender/fixtures/basic-src/output.json diff --git a/packages/kit/src/core/build/prerender/fixtures/basic-srcset/input.html b/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/basic-srcset/input.html rename to packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html diff --git a/packages/kit/src/core/build/prerender/fixtures/basic-srcset/output.json b/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/output.json similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/basic-srcset/output.json rename to packages/kit/src/vite/build/prerender/fixtures/basic-srcset/output.json diff --git a/packages/kit/src/core/build/prerender/fixtures/include-rel-external/input.html b/packages/kit/src/vite/build/prerender/fixtures/include-rel-external/input.html similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/include-rel-external/input.html rename to packages/kit/src/vite/build/prerender/fixtures/include-rel-external/input.html diff --git a/packages/kit/src/core/build/prerender/fixtures/include-rel-external/output.json b/packages/kit/src/vite/build/prerender/fixtures/include-rel-external/output.json similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/include-rel-external/output.json rename to packages/kit/src/vite/build/prerender/fixtures/include-rel-external/output.json diff --git a/packages/kit/src/core/build/prerender/fixtures/unquoted-attributes/input.html b/packages/kit/src/vite/build/prerender/fixtures/unquoted-attributes/input.html similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/unquoted-attributes/input.html rename to packages/kit/src/vite/build/prerender/fixtures/unquoted-attributes/input.html diff --git a/packages/kit/src/core/build/prerender/fixtures/unquoted-attributes/output.json b/packages/kit/src/vite/build/prerender/fixtures/unquoted-attributes/output.json similarity index 100% rename from packages/kit/src/core/build/prerender/fixtures/unquoted-attributes/output.json rename to packages/kit/src/vite/build/prerender/fixtures/unquoted-attributes/output.json diff --git a/packages/kit/src/core/build/prerender/prerender.js b/packages/kit/src/vite/build/prerender/prerender.js similarity index 100% rename from packages/kit/src/core/build/prerender/prerender.js rename to packages/kit/src/vite/build/prerender/prerender.js diff --git a/packages/kit/src/core/build/prerender/queue.js b/packages/kit/src/vite/build/prerender/queue.js similarity index 100% rename from packages/kit/src/core/build/prerender/queue.js rename to packages/kit/src/vite/build/prerender/queue.js diff --git a/packages/kit/src/core/build/prerender/queue.spec.js b/packages/kit/src/vite/build/prerender/queue.spec.js similarity index 100% rename from packages/kit/src/core/build/prerender/queue.spec.js rename to packages/kit/src/vite/build/prerender/queue.spec.js diff --git a/packages/kit/src/core/build/utils.js b/packages/kit/src/vite/build/utils.js similarity index 98% rename from packages/kit/src/core/build/utils.js rename to packages/kit/src/vite/build/utils.js index 8ba4c8642add..46ec53f03e0d 100644 --- a/packages/kit/src/core/build/utils.js +++ b/packages/kit/src/vite/build/utils.js @@ -1,5 +1,5 @@ import * as vite from 'vite'; -import { get_aliases } from '../utils.js'; +import { get_aliases } from '../../core/utils.js'; /** * @typedef {import('rollup').RollupOutput} RollupOutput diff --git a/packages/kit/src/core/dev/plugin.js b/packages/kit/src/vite/dev/plugin.js similarity index 98% rename from packages/kit/src/core/dev/plugin.js rename to packages/kit/src/vite/dev/plugin.js index 5b4b4fead9a6..33e72315315a 100644 --- a/packages/kit/src/core/dev/plugin.js +++ b/packages/kit/src/vite/dev/plugin.js @@ -8,10 +8,10 @@ import { installPolyfills } from '../../node/polyfills.js'; import { coalesce_to_error } from '../../utils/error.js'; import { posixify } from '../../utils/filesystem.js'; import { parse_route_id } from '../../utils/routing.js'; -import { load_template } from '../config/index.js'; -import { SVELTE_KIT_ASSETS } from '../constants.js'; -import * as sync from '../sync/sync.js'; -import { get_mime_lookup, get_runtime_path, resolve_entry } from '../utils.js'; +import { load_template } from '../../core/config/index.js'; +import { SVELTE_KIT_ASSETS } from '../../core/constants.js'; +import * as sync from '../../core/sync/sync.js'; +import { get_mime_lookup, get_runtime_path, resolve_entry } from '../../core/utils.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 diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index c9190cea0283..a0198f7c4967 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -5,16 +5,16 @@ import path from 'path'; import { searchForWorkspaceRoot } from 'vite'; import { mkdirp, posixify, rimraf } from '../utils/filesystem.js'; import * as sync from '../core/sync/sync.js'; -import { build_server } from '../core/build/build_server.js'; -import { build_service_worker } from '../core/build/build_service_worker.js'; -import { prerender } from '../core/build/prerender/prerender.js'; +import { build_server } from './build/build_server.js'; +import { build_service_worker } from './build/build_service_worker.js'; +import { prerender } from './build/prerender/prerender.js'; import { load_config, print_config_conflicts } from '../core/config/index.js'; -import { configure_server } from '../core/dev/plugin.js'; +import { configure_server } from './dev/plugin.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; import { deep_merge } from '../utils/object.js'; -import { find_deps, get_default_config } from '../core/build/utils.js'; -import { configure_preview_server } from '../core/preview/index.js'; +import { find_deps, get_default_config } from './build/utils.js'; +import { configure_preview_server } from './preview/index.js'; const cwd = process.cwd(); diff --git a/packages/kit/src/core/preview/index.js b/packages/kit/src/vite/preview/index.js similarity index 98% rename from packages/kit/src/core/preview/index.js rename to packages/kit/src/vite/preview/index.js index b523e7fc9c21..2a06f7e1513a 100644 --- a/packages/kit/src/core/preview/index.js +++ b/packages/kit/src/vite/preview/index.js @@ -4,7 +4,7 @@ import sirv from 'sirv'; import { pathToFileURL } from 'url'; import { getRequest, setResponse } from '../../node/index.js'; import { installPolyfills } from '../../node/polyfills.js'; -import { SVELTE_KIT_ASSETS } from '../constants.js'; +import { SVELTE_KIT_ASSETS } from '../../core/constants.js'; /** @typedef {import('http').IncomingMessage} Req */ /** @typedef {import('http').ServerResponse} Res */ From 2fbff0f334093b42aca858df8da4bbb39b89fb0c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 10:03:22 -0400 Subject: [PATCH 24/62] move adapt inside build --- .../fixtures/basic/.svelte-kit/output/client/routes/index.js | 0 .../basic/.svelte-kit/output/server/.well-known/test.js | 0 .../adapt/fixtures/basic/.svelte-kit/output/server/index.js | 0 packages/kit/src/{core => vite/build}/adapt/builder.js | 4 ++-- packages/kit/src/{core => vite/build}/adapt/builder.spec.js | 0 .../build}/adapt/fixtures/basic/static/answer.md | 0 packages/kit/src/{core => vite/build}/adapt/index.js | 0 packages/kit/src/vite/plugin.js | 2 +- 8 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/client/routes/index.js delete mode 100644 packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/server/.well-known/test.js delete mode 100644 packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/server/index.js rename packages/kit/src/{core => vite/build}/adapt/builder.js (96%) rename packages/kit/src/{core => vite/build}/adapt/builder.spec.js (100%) rename packages/kit/src/{core => vite/build}/adapt/fixtures/basic/static/answer.md (100%) rename packages/kit/src/{core => vite/build}/adapt/index.js (100%) diff --git a/packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/client/routes/index.js b/packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/client/routes/index.js deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/server/.well-known/test.js b/packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/server/.well-known/test.js deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/server/index.js b/packages/kit/src/core/adapt/fixtures/basic/.svelte-kit/output/server/index.js deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/kit/src/core/adapt/builder.js b/packages/kit/src/vite/build/adapt/builder.js similarity index 96% rename from packages/kit/src/core/adapt/builder.js rename to packages/kit/src/vite/build/adapt/builder.js index 5e828c84aad3..c1f55c344a32 100644 --- a/packages/kit/src/core/adapt/builder.js +++ b/packages/kit/src/vite/build/adapt/builder.js @@ -1,5 +1,5 @@ -import { copy, rimraf, mkdirp } from '../../utils/filesystem.js'; -import { generate_manifest } from '../generate_manifest/index.js'; +import { copy, rimraf, mkdirp } from '../../../utils/filesystem.js'; +import { generate_manifest } from '../../../core/generate_manifest/index.js'; /** * Creates the Builder which is passed to adapters for building the application. diff --git a/packages/kit/src/core/adapt/builder.spec.js b/packages/kit/src/vite/build/adapt/builder.spec.js similarity index 100% rename from packages/kit/src/core/adapt/builder.spec.js rename to packages/kit/src/vite/build/adapt/builder.spec.js diff --git a/packages/kit/src/core/adapt/fixtures/basic/static/answer.md b/packages/kit/src/vite/build/adapt/fixtures/basic/static/answer.md similarity index 100% rename from packages/kit/src/core/adapt/fixtures/basic/static/answer.md rename to packages/kit/src/vite/build/adapt/fixtures/basic/static/answer.md diff --git a/packages/kit/src/core/adapt/index.js b/packages/kit/src/vite/build/adapt/index.js similarity index 100% rename from packages/kit/src/core/adapt/index.js rename to packages/kit/src/vite/build/adapt/index.js diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index a0198f7c4967..04790877c57b 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -274,7 +274,7 @@ export const sveltekit = function () { ); if (svelte_config.kit.adapter) { - const { adapt } = await import('../core/adapt/index.js'); + const { adapt } = await import('./build/adapt/index.js'); await adapt(svelte_config, build_data, prerendered, { log }); // this is necessary to close any open db connections, etc From c7de1cb29dbaf8d6a5c4a2d3fead66147fa84efd Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 10:56:52 -0400 Subject: [PATCH 25/62] move all vite-related code into src/vite --- packages/kit/src/core/config/index.spec.js | 16 ++++++++++++- packages/kit/src/core/utils.js | 23 ------------------- packages/kit/src/vite/build/build_server.js | 6 ++--- .../src/vite/build/build_service_worker.js | 5 ++-- packages/kit/src/vite/build/utils.js | 23 +++++++++++++++++++ packages/kit/src/vite/plugin.js | 2 +- .../src/{utils/object.js => vite/utils.js} | 15 ------------ .../object.spec.js => vite/utils.spec.js} | 2 +- 8 files changed, 45 insertions(+), 47 deletions(-) rename packages/kit/src/{utils/object.js => vite/utils.js} (83%) rename packages/kit/src/{utils/object.spec.js => vite/utils.spec.js} (98%) diff --git a/packages/kit/src/core/config/index.spec.js b/packages/kit/src/core/config/index.spec.js index 597a5ecf911b..6106d4ff3c25 100644 --- a/packages/kit/src/core/config/index.spec.js +++ b/packages/kit/src/core/config/index.spec.js @@ -2,12 +2,26 @@ import { join } from 'path'; import { fileURLToPath } from 'url'; import { test } from 'uvu'; import * as assert from 'uvu/assert'; -import { remove_keys } from '../../utils/object.js'; import { validate_config, load_config } from './index.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = join(__filename, '..'); +/** + * mutates and remove keys from an object when check callback returns true + * @param {Record} o any object + * @param {([key, value]: [string, any]) => boolean} check callback with access + * to the key-value pair and returns a boolean that decides the deletion of key + */ +function remove_keys(o, check) { + for (const key in o) { + if (!Object.hasOwnProperty.call(o, key)) continue; + if (check([key, o[key]])) delete o[key]; + const nested = typeof o[key] === 'object' && !Array.isArray(o[key]); + if (nested) remove_keys(o[key], check); + } +} + const get_defaults = (prefix = '') => ({ extensions: ['.svelte'], kit: { diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index 7a7b5ede628e..5e7d23163180 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -97,26 +97,3 @@ export function get_aliases(config) { return alias; } - -/** - * @param {import('vite').UserConfig} config - * @param {boolean} [add_svelte] - */ -export function ensure_plugins(config, add_svelte) { - // @ts-expect-error - it can't handle infinite type expansion - config.plugins = (config.plugins || []).flat(Infinity); - let has_svelte_plugin = false; - for (let i = config.plugins.length - 1; i > 0; i--) { - const plugin = config.plugins[i]; - // @ts-expect-error - it doesn't know about the `flat` call we just made - if (plugin?.name === 'vite-plugin-svelte-kit') { - config.plugins.splice(i, 1); - // @ts-expect-error - it doesn't know about the `flat` call we just made - } else if (plugin?.name === 'vite-plugin-svelte') { - has_svelte_plugin = true; - } - } - if (add_svelte && !has_svelte_plugin && !process.env.SVELTE_VITE_CONFIG) { - config.plugins.push(svelte({})); - } -} diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index 6c7f046c5276..76e4aeb6cf8c 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -1,10 +1,10 @@ import fs from 'fs'; import path from 'path'; import { mkdirp, posixify } from '../../utils/filesystem.js'; -import { deep_merge } from '../../utils/object.js'; +import { deep_merge } from '../utils.js'; import { load_template, print_config_conflicts } from '../../core/config/index.js'; -import { ensure_plugins, get_runtime_path, resolve_entry } from '../../core/utils.js'; -import { create_build, find_deps, get_default_config } from './utils.js'; +import { get_runtime_path, resolve_entry } from '../../core/utils.js'; +import { create_build, find_deps, get_default_config, ensure_plugins } from './utils.js'; import { s } from '../../utils/misc.js'; import { get_vite_config, sveltekit_validation } from '../plugin.js'; diff --git a/packages/kit/src/vite/build/build_service_worker.js b/packages/kit/src/vite/build/build_service_worker.js index 1c136e702a67..002acef9305b 100644 --- a/packages/kit/src/vite/build/build_service_worker.js +++ b/packages/kit/src/vite/build/build_service_worker.js @@ -1,12 +1,11 @@ import fs from 'fs'; import * as vite from 'vite'; import { s } from '../../utils/misc.js'; -import { deep_merge } from '../../utils/object.js'; +import { deep_merge } from '../utils.js'; import { normalize_path } from '../../utils/url.js'; import { get_vite_config, sveltekit_validation } from '../plugin.js'; import { print_config_conflicts } from '../../core/config/index.js'; -import { ensure_plugins } from '../../core/utils.js'; -import { assets_base } from './utils.js'; +import { assets_base, ensure_plugins } from './utils.js'; /** * @param {{ diff --git a/packages/kit/src/vite/build/utils.js b/packages/kit/src/vite/build/utils.js index 46ec53f03e0d..13821bb6806c 100644 --- a/packages/kit/src/vite/build/utils.js +++ b/packages/kit/src/vite/build/utils.js @@ -98,3 +98,26 @@ export function assets_base(config) { const { base, assets } = config.paths; return `${assets || base}/${config.appDir}/immutable/`; } + +/** + * @param {import('vite').UserConfig} config + * @param {boolean} [add_svelte] + */ +export function ensure_plugins(config, add_svelte) { + // @ts-expect-error - it can't handle infinite type expansion + config.plugins = (config.plugins || []).flat(Infinity); + let has_svelte_plugin = false; + for (let i = config.plugins.length - 1; i > 0; i--) { + const plugin = config.plugins[i]; + // @ts-expect-error - it doesn't know about the `flat` call we just made + if (plugin?.name === 'vite-plugin-svelte-kit') { + config.plugins.splice(i, 1); + // @ts-expect-error - it doesn't know about the `flat` call we just made + } else if (plugin?.name === 'vite-plugin-svelte') { + has_svelte_plugin = true; + } + } + if (add_svelte && !has_svelte_plugin && !process.env.SVELTE_VITE_CONFIG) { + config.plugins.push(svelte({})); + } +} diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 04790877c57b..0d19c7b0579b 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -12,9 +12,9 @@ import { load_config, print_config_conflicts } from '../core/config/index.js'; import { configure_server } from './dev/plugin.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; -import { deep_merge } from '../utils/object.js'; import { find_deps, get_default_config } from './build/utils.js'; import { configure_preview_server } from './preview/index.js'; +import { deep_merge } from './utils.js'; const cwd = process.cwd(); diff --git a/packages/kit/src/utils/object.js b/packages/kit/src/vite/utils.js similarity index 83% rename from packages/kit/src/utils/object.js rename to packages/kit/src/vite/utils.js index ed4d192bbf46..af8a23e87c9d 100644 --- a/packages/kit/src/utils/object.js +++ b/packages/kit/src/vite/utils.js @@ -26,21 +26,6 @@ export function normalize_alias(o) { return Object.entries(o).map(([find, replacement]) => ({ find, replacement })); } -/** - * mutates and remove keys from an object when check callback returns true - * @param {Record} o any object - * @param {([key, value]: [string, any]) => boolean} check callback with access - * to the key-value pair and returns a boolean that decides the deletion of key - */ -export function remove_keys(o, check) { - for (const key in o) { - if (!Object.hasOwnProperty.call(o, key)) continue; - if (check([key, o[key]])) delete o[key]; - const nested = typeof o[key] === 'object' && !Array.isArray(o[key]); - if (nested) remove_keys(o[key], check); - } -} - /** * Merges b into a, recursively, mutating a. * @param {Record} a diff --git a/packages/kit/src/utils/object.spec.js b/packages/kit/src/vite/utils.spec.js similarity index 98% rename from packages/kit/src/utils/object.spec.js rename to packages/kit/src/vite/utils.spec.js index e7e33932db82..78249d43e3ca 100644 --- a/packages/kit/src/utils/object.spec.js +++ b/packages/kit/src/vite/utils.spec.js @@ -1,6 +1,6 @@ import { test } from 'uvu'; import * as assert from 'uvu/assert'; -import { deep_merge } from './object.js'; +import { deep_merge } from './utils.js'; test('basic test no conflicts', async () => { const [merged, conflicts] = deep_merge( From 0b0bfd07f1acc7a2d98358307b5c62257d0a4da0 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 11:14:41 -0400 Subject: [PATCH 26/62] move some more stuff around --- packages/kit/src/vite/dev/{plugin.js => index.js} | 4 ++-- packages/kit/src/vite/plugin.js | 10 +++++----- packages/kit/src/vite/preview/index.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) rename packages/kit/src/vite/dev/{plugin.js => index.js} (99%) diff --git a/packages/kit/src/vite/dev/plugin.js b/packages/kit/src/vite/dev/index.js similarity index 99% rename from packages/kit/src/vite/dev/plugin.js rename to packages/kit/src/vite/dev/index.js index 33e72315315a..98ea61118503 100644 --- a/packages/kit/src/vite/dev/plugin.js +++ b/packages/kit/src/vite/dev/index.js @@ -24,7 +24,7 @@ const cwd = process.cwd(); * @param {import('types').ValidatedConfig} svelte_config * @return {Promise void>>} */ -export const configure_server = async function (vite, svelte_config) { +export async function dev(vite, svelte_config) { installPolyfills(); sync.init(svelte_config); @@ -371,7 +371,7 @@ export const configure_server = async function (vite, svelte_config) { } }); }; -}; +} /** @param {import('http').ServerResponse} res */ function not_found(res, message = 'Not found') { diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 0d19c7b0579b..e25ce0414d6d 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -9,11 +9,11 @@ import { build_server } from './build/build_server.js'; import { build_service_worker } from './build/build_service_worker.js'; import { prerender } from './build/prerender/prerender.js'; import { load_config, print_config_conflicts } from '../core/config/index.js'; -import { configure_server } from './dev/plugin.js'; +import { dev } from './dev/index.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; import { find_deps, get_default_config } from './build/utils.js'; -import { configure_preview_server } from './preview/index.js'; +import { preview } from './preview/index.js'; import { deep_merge } from './utils.js'; const cwd = process.cwd(); @@ -290,11 +290,11 @@ export const sveltekit = function () { }, async configureServer(vite) { - return await configure_server(vite, svelte_config); + return await dev(vite, svelte_config); }, - async configurePreviewServer(vite) { - return await configure_preview_server(vite, svelte_config, vite_config); + configurePreviewServer(vite) { + return preview(vite, svelte_config, vite_config); } }; }; diff --git a/packages/kit/src/vite/preview/index.js b/packages/kit/src/vite/preview/index.js index 2a06f7e1513a..327efa96e37a 100644 --- a/packages/kit/src/vite/preview/index.js +++ b/packages/kit/src/vite/preview/index.js @@ -18,7 +18,7 @@ import { SVELTE_KIT_ASSETS } from '../../core/constants.js'; * @param {import('types').ValidatedConfig} config * @param {import('vite').ResolvedConfig} vite_config */ -export const configure_preview_server = async function (vite, config, vite_config) { +export async function preview(vite, config, vite_config) { installPolyfills(); const { paths } = config.kit; @@ -147,7 +147,7 @@ export const configure_preview_server = async function (vite, config, vite_confi ); }); }; -}; +} /** * @param {string} dir From ab54c888aab016f7bf898f1d89cab58070c7c0aa Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 12:02:26 -0400 Subject: [PATCH 27/62] fix some stuff --- packages/kit/src/core/utils.js | 1 - packages/kit/src/vite/build/build_server.js | 2 +- packages/kit/src/vite/build/utils.js | 5 ++++- packages/kit/src/vite/plugin.js | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index 5e7d23163180..86233a701d4c 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -1,4 +1,3 @@ -import { svelte } from '@sveltejs/vite-plugin-svelte'; import fs from 'fs'; import path from 'path'; import colors from 'kleur'; diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index 76e4aeb6cf8c..2848faeae27e 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -181,7 +181,7 @@ export async function build_server(options, client) { build: { target: 'node14.8' }, - plugins: [sveltekit_validation], + plugins: [], ssr: { // when developing against the Kit src code, we want to ensure that // our dependencies are bundled so that apps don't need to install diff --git a/packages/kit/src/vite/build/utils.js b/packages/kit/src/vite/build/utils.js index 13821bb6806c..0b2b738d219a 100644 --- a/packages/kit/src/vite/build/utils.js +++ b/packages/kit/src/vite/build/utils.js @@ -1,4 +1,5 @@ import * as vite from 'vite'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; import { get_aliases } from '../../core/utils.js'; /** @@ -12,7 +13,9 @@ import { get_aliases } from '../../core/utils.js'; * @param {import('vite').UserConfig} config */ export async function create_build(config) { - const { output } = /** @type {RollupOutput} */ (await vite.build(config)); + const { output } = /** @type {RollupOutput} */ ( + await vite.build({ ...config, configFile: false }) + ); const chunks = output.filter( /** @returns {output is OutputChunk} */ (output) => output.type === 'chunk' diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index e25ce0414d6d..19020c32eccc 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -307,7 +307,7 @@ export const sveltekit = function () { export async function get_vite_config(svelte_config, config_file) { for (const file of ['vite.config.js', 'vite.config.mjs', 'vite.config.cjs']) { if (fs.existsSync(file)) { - return config_file === false ? await import(path.resolve(cwd, file)) : {}; + return config_file === false ? (await import(path.resolve(cwd, file))).default : {}; } } // TODO: stop reading Vite config from SvelteKit config or move to CLI @@ -322,6 +322,7 @@ export async function get_vite_config(svelte_config, config_file) { * @return {import('vite').Plugin[]} */ export const svelte = function () { + // TODO what is the purpose of this function? Why do we not just re-export it? return svelte_plugin(); }; From 9b549f0e78c20304b3ed91cb0f06a4971f7e7fe9 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 12:28:39 -0400 Subject: [PATCH 28/62] simplify stuff --- packages/kit/src/cli.js | 30 +++++++++++++--- packages/kit/src/vite/build/build_server.js | 6 ++-- .../src/vite/build/build_service_worker.js | 6 ++-- packages/kit/src/vite/plugin.js | 34 ++++++------------- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 5a06c9c1ecc9..ed51f20e36c2 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -1,13 +1,13 @@ import chokidar from 'chokidar'; import fs from 'fs'; +import path from 'path'; import colors from 'kleur'; -import { relative } from 'path'; 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'; -import { get_vite_config } from './vite/plugin.js'; +import { sveltekit } from './vite/index.js'; /** @param {unknown} e */ function handle_error(e) { @@ -155,7 +155,7 @@ prog const svelte_config = await load_config(); const vite_config = await get_vite_config(svelte_config); - await vite.build(vite_config); + await vite.build(vite_config); // TODO when we get rid of config.kit.vite, this can just be vite.build() } catch (error) { handle_error(error); } @@ -280,7 +280,7 @@ function welcome({ port, host, https, open, base, loose, allow, cwd }) { if (loose) { console.log(`\n ${colors.yellow('Serving with vite.server.fs.strict: false. Note that all files on your machine will be accessible to anyone on your network.')}`); } else if (allow?.length && cwd) { - console.log(`\n ${colors.yellow('Note that all files in the following directories will be accessible to anyone on your network: ' + allow.map(a => relative(cwd, a)).join(', '))}`); + console.log(`\n ${colors.yellow('Note that all files in the following directories will be accessible to anyone on your network: ' + allow.map(a => path.relative(cwd, a)).join(', '))}`); } } else { console.log(` ${colors.gray('network: not exposed')}`); @@ -295,3 +295,25 @@ function welcome({ port, host, https, open, base, loose, allow, cwd }) { console.log('\n'); } + +/** + * @param {import('types').ValidatedConfig} svelte_config + * @return {Promise} + */ +export async function get_vite_config(svelte_config) { + for (const file of ['vite.config.js', 'vite.config.mjs', 'vite.config.cjs']) { + if (fs.existsSync(file)) { + // TODO warn here if config.kit.vite was specified + const module = await import(path.resolve(file)); + return { + ...module.default, + configFile: false + }; + } + } + + // TODO: stop reading Vite config from SvelteKit config or move to CLI + const vite_config = await svelte_config.kit.vite(); + vite_config.plugins = [...(vite_config.plugins || []), ...sveltekit()]; + return vite_config; +} diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index 2848faeae27e..e24abccc7147 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -6,7 +6,6 @@ import { load_template, print_config_conflicts } from '../../core/config/index.j import { get_runtime_path, resolve_entry } from '../../core/utils.js'; import { create_build, find_deps, get_default_config, ensure_plugins } from './utils.js'; import { s } from '../../utils/misc.js'; -import { get_vite_config, sveltekit_validation } from '../plugin.js'; /** * @param {{ @@ -105,6 +104,7 @@ export class Server { `; /** + * @param {import('vite').UserConfig} vite_config * @param {{ * cwd: string; * config: import('types').ValidatedConfig @@ -115,7 +115,7 @@ export class Server { * }} options * @param {{ vite_manifest: import('vite').Manifest, assets: import('rollup').OutputAsset[] }} client */ -export async function build_server(options, client) { +export async function build_server(vite_config, options, client) { const { cwd, config, manifest_data, build_dir, output_dir, service_worker_entry_file } = options; let hooks_file = resolve_entry(config.kit.files.hooks); @@ -175,8 +175,6 @@ export async function build_server(options, client) { }) ); - const vite_config = await get_vite_config(config, false); - const default_config = { build: { target: 'node14.8' diff --git a/packages/kit/src/vite/build/build_service_worker.js b/packages/kit/src/vite/build/build_service_worker.js index 002acef9305b..260805b43a2b 100644 --- a/packages/kit/src/vite/build/build_service_worker.js +++ b/packages/kit/src/vite/build/build_service_worker.js @@ -3,11 +3,11 @@ import * as vite from 'vite'; import { s } from '../../utils/misc.js'; import { deep_merge } from '../utils.js'; import { normalize_path } from '../../utils/url.js'; -import { get_vite_config, sveltekit_validation } from '../plugin.js'; import { print_config_conflicts } from '../../core/config/index.js'; import { assets_base, ensure_plugins } from './utils.js'; /** + * @param {import('vite').UserConfig} vite_config * @param {{ * config: import('types').ValidatedConfig; * manifest_data: import('types').ManifestData; @@ -18,6 +18,7 @@ import { assets_base, ensure_plugins } from './utils.js'; * @param {import('vite').Manifest} client_manifest */ export async function build_service_worker( + vite_config, { config, manifest_data, output_dir, service_worker_entry_file }, prerendered, client_manifest @@ -67,8 +68,6 @@ export async function build_service_worker( .trim() ); - const vite_config = await get_vite_config(config, false); - /** @type {[any, string[]]} */ const [merged_config, conflicts] = deep_merge(vite_config, { base: assets_base(config.kit), @@ -86,7 +85,6 @@ export async function build_service_worker( outDir: `${output_dir}/client`, emptyOutDir: false }, - plugins: [sveltekit_validation], resolve: { alias: { '$service-worker': service_worker, diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 19020c32eccc..a889e8f58000 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -25,8 +25,11 @@ export const sveltekit = function () { /** @type {import('types').ValidatedConfig} */ let svelte_config; + /** @type {import('vite').UserConfig} */ + let vite_user_config; + /** @type {import('vite').ResolvedConfig} */ - let vite_config; + let vite_resolved_config; /** @type {import('types').ManifestData|undefined} */ let manifest_data = undefined; @@ -35,6 +38,8 @@ export const sveltekit = function () { name: 'vite-plugin-svelte-kit', async config(_config, env) { + vite_user_config = _config; + svelte_config = await load_config(); const build_dir = path.join(svelte_config.kit.outDir, 'build'); @@ -145,7 +150,7 @@ export const sveltekit = function () { }, configResolved(config) { - vite_config = config; + vite_resolved_config = config; }, async writeBundle(_options, bundle) { @@ -213,7 +218,7 @@ export const sveltekit = function () { log.info('Building server'); - const server = await build_server(options, client); + const server = await build_server(vite_user_config, options, client); process.env.SVELTEKIT_SERVER_BUILD_COMPLETED = 'true'; @@ -266,7 +271,7 @@ export const sveltekit = function () { log.info('Building service worker'); - await build_service_worker(options, prerendered, client.vite_manifest); + await build_service_worker(vite_user_config, options, prerendered, client.vite_manifest); } console.log( @@ -294,30 +299,11 @@ export const sveltekit = function () { }, configurePreviewServer(vite) { - return preview(vite, svelte_config, vite_config); + return preview(vite, svelte_config, vite_resolved_config); } }; }; -/** - * @param {import('types').ValidatedConfig} svelte_config - * @param {boolean} [config_file] - * @return {Promise} - */ -export async function get_vite_config(svelte_config, config_file) { - for (const file of ['vite.config.js', 'vite.config.mjs', 'vite.config.cjs']) { - if (fs.existsSync(file)) { - return config_file === false ? (await import(path.resolve(cwd, file))).default : {}; - } - } - // TODO: stop reading Vite config from SvelteKit config or move to CLI - const vite_config = await svelte_config.kit.vite(); - if (config_file !== false) { - vite_config.plugins = [...(vite_config.plugins || []), ...plugins_internal()]; - } - return vite_config; -} - /** * @return {import('vite').Plugin[]} */ From e5432d1de7b27295db22f5190768163d43dc26a9 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 12:29:34 -0400 Subject: [PATCH 29/62] remove unused plugins_internal --- packages/kit/src/vite/plugin.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index a889e8f58000..37214575c1da 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -321,18 +321,6 @@ export const plugins = function () { : [...svelte(), sveltekit(), sveltekit_validation]; }; -/** - * @return {import('vite').Plugin[]} - */ -const plugins_internal = function () { - if (process.env.SVELTE_VITE_CONFIG) { - return [sveltekit_validation]; - } - return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED - ? [...svelte(), sveltekit_validation] - : [...svelte(), sveltekit(), sveltekit_validation]; -}; - /** * While we're supporting svelte.config.js and vite.config.js it's very easy * to end up with duplicate plugins, which is hard to debug. Ensure we avoid that. From db3036e90d6b93e6fded0d2ca7025fed3f8b8b44 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 12:36:18 -0400 Subject: [PATCH 30/62] we can now simplify stuff a bunch --- packages/kit/src/vite/plugin.js | 47 +-------------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index 37214575c1da..4d7d2224cf41 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -204,7 +204,6 @@ export const sveltekit = function () { vite_manifest }; log.info(`Client build completed. Wrote ${chunks.length} chunks and ${assets.length} assets`); - process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED = 'true'; const options = { cwd, @@ -316,49 +315,5 @@ export const svelte = function () { * @return {import('vite').Plugin[]} */ export const plugins = function () { - return process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED - ? [...svelte(), sveltekit_validation] - : [...svelte(), sveltekit(), sveltekit_validation]; + return [...svelte(), sveltekit()]; }; - -/** - * While we're supporting svelte.config.js and vite.config.js it's very easy - * to end up with duplicate plugins, which is hard to debug. Ensure we avoid that. - * @type {import('vite').Plugin} - */ -export const sveltekit_validation = { - name: 'vite-plugin-svelte-kit-validation', - configResolved(config) { - let svelte_count = 0; - let svelte_kit_count = 0; - const plugins = config.plugins.flat(Infinity); - for (const plugin of plugins) { - if (plugin.name === 'vite-plugin-svelte') { - svelte_count++; - } else if (plugin.name === 'vite-plugin-svelte-kit') { - svelte_kit_count++; - } - } - assert_plugin_count( - 'vite-plugin-svelte', - svelte_count, - process.env.SVELTEKIT_SERVER_BUILD_COMPLETED ? 0 : 1 - ); - assert_plugin_count( - 'vite-plugin-svelte-kit', - svelte_kit_count, - process.env.SVELTEKIT_CLIENT_BUILD_COMPLETED ? 0 : 1 - ); - } -}; - -/** - * @param {string} name - * @param {number} count - * @param {number} expected_count - */ -function assert_plugin_count(name, count, expected_count) { - if (count !== expected_count) { - throw new Error(`Expected ${name} to be present ${expected_count} times, but found ${count}`); - } -} From a021fc4c133132f665c2303482fc575bc83d749c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 13:04:09 -0400 Subject: [PATCH 31/62] simplify --- packages/kit/src/vite/build/build_server.js | 4 ++-- .../src/vite/build/build_service_worker.js | 4 ++-- packages/kit/src/vite/build/utils.js | 22 +++++-------------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index e24abccc7147..07b3486842e0 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -4,7 +4,7 @@ import { mkdirp, posixify } from '../../utils/filesystem.js'; import { deep_merge } from '../utils.js'; import { load_template, print_config_conflicts } from '../../core/config/index.js'; import { get_runtime_path, resolve_entry } from '../../core/utils.js'; -import { create_build, find_deps, get_default_config, ensure_plugins } from './utils.js'; +import { create_build, find_deps, get_default_config, remove_svelte_kit } from './utils.js'; import { s } from '../../utils/misc.js'; /** @@ -204,7 +204,7 @@ export async function build_server(vite_config, options, client) { print_config_conflicts(conflicts, 'kit.vite.', 'build_server'); - ensure_plugins(merged_config, true); + remove_svelte_kit(merged_config); process.env.VITE_SVELTEKIT_ADAPTER_NAME = config.kit.adapter?.name; diff --git a/packages/kit/src/vite/build/build_service_worker.js b/packages/kit/src/vite/build/build_service_worker.js index 260805b43a2b..8c912f6f0903 100644 --- a/packages/kit/src/vite/build/build_service_worker.js +++ b/packages/kit/src/vite/build/build_service_worker.js @@ -4,7 +4,7 @@ import { s } from '../../utils/misc.js'; import { deep_merge } from '../utils.js'; import { normalize_path } from '../../utils/url.js'; import { print_config_conflicts } from '../../core/config/index.js'; -import { assets_base, ensure_plugins } from './utils.js'; +import { assets_base, remove_svelte_kit } from './utils.js'; /** * @param {import('vite').UserConfig} vite_config @@ -95,7 +95,7 @@ export async function build_service_worker( print_config_conflicts(conflicts, 'kit.vite.', 'build_service_worker'); - ensure_plugins(merged_config); + remove_svelte_kit(merged_config); await vite.build(merged_config); } diff --git a/packages/kit/src/vite/build/utils.js b/packages/kit/src/vite/build/utils.js index 0b2b738d219a..759fe7ad63f5 100644 --- a/packages/kit/src/vite/build/utils.js +++ b/packages/kit/src/vite/build/utils.js @@ -104,23 +104,11 @@ export function assets_base(config) { /** * @param {import('vite').UserConfig} config - * @param {boolean} [add_svelte] */ -export function ensure_plugins(config, add_svelte) { +export function remove_svelte_kit(config) { + // TODO i feel like there's a more elegant way to do this // @ts-expect-error - it can't handle infinite type expansion - config.plugins = (config.plugins || []).flat(Infinity); - let has_svelte_plugin = false; - for (let i = config.plugins.length - 1; i > 0; i--) { - const plugin = config.plugins[i]; - // @ts-expect-error - it doesn't know about the `flat` call we just made - if (plugin?.name === 'vite-plugin-svelte-kit') { - config.plugins.splice(i, 1); - // @ts-expect-error - it doesn't know about the `flat` call we just made - } else if (plugin?.name === 'vite-plugin-svelte') { - has_svelte_plugin = true; - } - } - if (add_svelte && !has_svelte_plugin && !process.env.SVELTE_VITE_CONFIG) { - config.plugins.push(svelte({})); - } + config.plugins = (config.plugins || []) + .flat(Infinity) + .filter((plugin) => plugin.name !== 'vite-plugin-svelte-kit'); } From e4457d5e94a6cdc57670f01797ac32debc8531dc Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 10:46:43 -0700 Subject: [PATCH 32/62] lint --- packages/kit/src/runtime/server/page/load_node.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/kit/src/runtime/server/page/load_node.js b/packages/kit/src/runtime/server/page/load_node.js index 4b0c54cc7b7c..b925a2776ad0 100644 --- a/packages/kit/src/runtime/server/page/load_node.js +++ b/packages/kit/src/runtime/server/page/load_node.js @@ -2,9 +2,8 @@ import * as cookie from 'cookie'; import * as set_cookie_parser from 'set-cookie-parser'; import { normalize } from '../../load.js'; import { respond } from '../index.js'; -import { is_root_relative, resolve } from '../../../utils/url.js'; +import { LoadURL, is_root_relative, resolve } from '../../../utils/url.js'; import { create_prerendering_url_proxy } from './utils.js'; -import { LoadURL } from '../../../utils/url.js'; import { is_pojo, lowercase_keys, normalize_request_method } from '../utils.js'; import { coalesce_to_error } from '../../../utils/error.js'; import { domain_matches, path_matches } from './cookie.js'; From a8a46933854e04c436a25dd550549656295efcc4 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 11:01:36 -0700 Subject: [PATCH 33/62] update path in .prettierrc --- .prettierrc | 2 +- .../vite/build/prerender/fixtures/basic-srcset/input.html | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.prettierrc b/.prettierrc index a87fcd7acf15..bf43738768cd 100644 --- a/.prettierrc +++ b/.prettierrc @@ -24,7 +24,7 @@ "packages/kit/src/packaging/test/fixtures/**/expected/**/*", "packages/kit/src/packaging/test/watch/expected/**/*", "packages/kit/src/packaging/test/watch/package/**/*", - "packages/kit/src/core/build/prerender/fixtures/**/*" + "packages/kit/src/vite/build/prerender/fixtures/**/*" ], "options": { "requirePragma": true diff --git a/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html b/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html index 2cf4e81e6d6b..c3f04b382715 100644 --- a/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html +++ b/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html @@ -5,7 +5,13 @@ A header From f66dd1c04c9137ab1f6bf7cc598467ff2092f03f Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 11:02:46 -0700 Subject: [PATCH 34/62] revert accidental change --- .../vite/build/prerender/fixtures/basic-srcset/input.html | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html b/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html index c3f04b382715..2cf4e81e6d6b 100644 --- a/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html +++ b/packages/kit/src/vite/build/prerender/fixtures/basic-srcset/input.html @@ -5,13 +5,7 @@ A header From d4e01e6b1f6d6f1dc3108080b9c481bbca6f9d42 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 11:28:50 -0700 Subject: [PATCH 35/62] try fixing CI --- packages/kit/test/prerendering/paths-base/tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/test/prerendering/paths-base/tsconfig.json b/packages/kit/test/prerendering/paths-base/tsconfig.json index e969d35a695f..858415b26691 100644 --- a/packages/kit/test/prerendering/paths-base/tsconfig.json +++ b/packages/kit/test/prerendering/paths-base/tsconfig.json @@ -5,8 +5,8 @@ "noEmit": true, "paths": { "@sveltejs/kit": ["../../../types"], - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"], + "$lib": ["./src/lib"], + "$lib/*": ["./src/lib/*"], "types": ["../../../types/internal"] } }, From 67889275f4bcfd7a68c0db70fa016030316e55ce Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 11:33:12 -0700 Subject: [PATCH 36/62] try fixing CI --- .../src/packaging/test/errors/duplicate-export/jsconfig.json | 2 +- packages/kit/test/apps/amp/tsconfig.json | 4 ++-- packages/kit/test/apps/basics/tsconfig.json | 4 ++-- packages/kit/test/apps/options-2/tsconfig.json | 4 ++-- packages/kit/test/prerendering/basics/tsconfig.json | 4 ++-- packages/kit/test/prerendering/options/tsconfig.json | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/kit/src/packaging/test/errors/duplicate-export/jsconfig.json b/packages/kit/src/packaging/test/errors/duplicate-export/jsconfig.json index 92575debb461..f29fde21bafc 100644 --- a/packages/kit/src/packaging/test/errors/duplicate-export/jsconfig.json +++ b/packages/kit/src/packaging/test/errors/duplicate-export/jsconfig.json @@ -3,7 +3,7 @@ "checkJs": true, "baseUrl": ".", "paths": { - "$lib/*": ["src/lib/*"] + "$lib/*": ["./src/lib/*"] } }, "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] diff --git a/packages/kit/test/apps/amp/tsconfig.json b/packages/kit/test/apps/amp/tsconfig.json index e969d35a695f..858415b26691 100644 --- a/packages/kit/test/apps/amp/tsconfig.json +++ b/packages/kit/test/apps/amp/tsconfig.json @@ -5,8 +5,8 @@ "noEmit": true, "paths": { "@sveltejs/kit": ["../../../types"], - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"], + "$lib": ["./src/lib"], + "$lib/*": ["./src/lib/*"], "types": ["../../../types/internal"] } }, diff --git a/packages/kit/test/apps/basics/tsconfig.json b/packages/kit/test/apps/basics/tsconfig.json index ead111316f65..236014c1f2df 100644 --- a/packages/kit/test/apps/basics/tsconfig.json +++ b/packages/kit/test/apps/basics/tsconfig.json @@ -6,8 +6,8 @@ "noEmit": true, "paths": { "@sveltejs/kit": ["../../../types"], - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"], + "$lib": ["./src/lib"], + "$lib/*": ["./src/lib/*"], "types": ["../../../types/internal"] } }, diff --git a/packages/kit/test/apps/options-2/tsconfig.json b/packages/kit/test/apps/options-2/tsconfig.json index e969d35a695f..858415b26691 100644 --- a/packages/kit/test/apps/options-2/tsconfig.json +++ b/packages/kit/test/apps/options-2/tsconfig.json @@ -5,8 +5,8 @@ "noEmit": true, "paths": { "@sveltejs/kit": ["../../../types"], - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"], + "$lib": ["./src/lib"], + "$lib/*": ["./src/lib/*"], "types": ["../../../types/internal"] } }, diff --git a/packages/kit/test/prerendering/basics/tsconfig.json b/packages/kit/test/prerendering/basics/tsconfig.json index e969d35a695f..858415b26691 100644 --- a/packages/kit/test/prerendering/basics/tsconfig.json +++ b/packages/kit/test/prerendering/basics/tsconfig.json @@ -5,8 +5,8 @@ "noEmit": true, "paths": { "@sveltejs/kit": ["../../../types"], - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"], + "$lib": ["./src/lib"], + "$lib/*": ["./src/lib/*"], "types": ["../../../types/internal"] } }, diff --git a/packages/kit/test/prerendering/options/tsconfig.json b/packages/kit/test/prerendering/options/tsconfig.json index c4c541dfa353..91c5f17c7590 100644 --- a/packages/kit/test/prerendering/options/tsconfig.json +++ b/packages/kit/test/prerendering/options/tsconfig.json @@ -4,8 +4,8 @@ "checkJs": true, "noEmit": true, "paths": { - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"], + "$lib": ["./src/lib"], + "$lib/*": ["./src/lib/*"], "types": ["../../../types/internal"] } }, From f56618af093b58aabfb5984001ed74437c686465 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 14:37:40 -0400 Subject: [PATCH 37/62] lint --- packages/kit/src/vite/build/utils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/src/vite/build/utils.js b/packages/kit/src/vite/build/utils.js index 759fe7ad63f5..381857db0607 100644 --- a/packages/kit/src/vite/build/utils.js +++ b/packages/kit/src/vite/build/utils.js @@ -1,5 +1,4 @@ import * as vite from 'vite'; -import { svelte } from '@sveltejs/vite-plugin-svelte'; import { get_aliases } from '../../core/utils.js'; /** From 6f6e3f39c4db6c7424f8d3a604aca1d285241dca Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 14:43:55 -0400 Subject: [PATCH 38/62] lint --- packages/kit/test/prerendering/basics/svelte.config.js | 4 ++-- packages/kit/test/prerendering/basics/test/test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kit/test/prerendering/basics/svelte.config.js b/packages/kit/test/prerendering/basics/svelte.config.js index bad007a33f62..d1a233f77e2e 100644 --- a/packages/kit/test/prerendering/basics/svelte.config.js +++ b/packages/kit/test/prerendering/basics/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import { resolve } from 'path'; import adapter from '../../../../adapter-static/index.js'; /** @type {import('@sveltejs/kit').Config} */ @@ -18,7 +18,7 @@ const config = { clearScreen: false, server: { fs: { - allow: [path.resolve('../../../src')] + allow: [resolve('../../../src')] } } } diff --git a/packages/kit/test/prerendering/basics/test/test.js b/packages/kit/test/prerendering/basics/test/test.js index 3e60ceff72dd..b7dd394892d2 100644 --- a/packages/kit/test/prerendering/basics/test/test.js +++ b/packages/kit/test/prerendering/basics/test/test.js @@ -1,4 +1,4 @@ -import fs from 'fs'; +import * as fs from 'fs'; import { fileURLToPath } from 'url'; import { test } from 'uvu'; import * as assert from 'uvu/assert'; From 1adcd023fbc7dd531f8343e4419130320b62f27a Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 14:48:48 -0400 Subject: [PATCH 39/62] fix --- packages/kit/.gitignore | 2 +- packages/kit/src/packaging/test/watch/src/lib/Test.svelte | 1 + packages/kit/src/packaging/test/watch/src/lib/a.js | 1 + packages/kit/src/packaging/test/watch/src/lib/b.ts | 1 + .../fixtures/basic/.svelte-kit/output/client/routes/index.js | 0 .../basic/.svelte-kit/output/server/.well-known/test.js | 0 .../adapt/fixtures/basic/.svelte-kit/output/server/index.js | 0 7 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 packages/kit/src/packaging/test/watch/src/lib/Test.svelte create mode 100644 packages/kit/src/packaging/test/watch/src/lib/a.js create mode 100644 packages/kit/src/packaging/test/watch/src/lib/b.ts create mode 100644 packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/client/routes/index.js create mode 100644 packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/server/.well-known/test.js create mode 100644 packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/server/index.js diff --git a/packages/kit/.gitignore b/packages/kit/.gitignore index 82ad03c88b0e..a1519ebbd4e4 100644 --- a/packages/kit/.gitignore +++ b/packages/kit/.gitignore @@ -5,7 +5,7 @@ /docs /test/**/.svelte-kit /test/**/build -!/src/core/adapt/fixtures/*/.svelte-kit +!/src/vite/build/adapt/fixtures/*/.svelte-kit !/test/node_modules /test/apps/basics/test/errors.json .custom-out-dir \ No newline at end of file diff --git a/packages/kit/src/packaging/test/watch/src/lib/Test.svelte b/packages/kit/src/packaging/test/watch/src/lib/Test.svelte new file mode 100644 index 000000000000..8f19b8ec1674 --- /dev/null +++ b/packages/kit/src/packaging/test/watch/src/lib/Test.svelte @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/kit/src/packaging/test/watch/src/lib/a.js b/packages/kit/src/packaging/test/watch/src/lib/a.js new file mode 100644 index 000000000000..961d97e14bdc --- /dev/null +++ b/packages/kit/src/packaging/test/watch/src/lib/a.js @@ -0,0 +1 @@ +export const a = "a"; \ No newline at end of file diff --git a/packages/kit/src/packaging/test/watch/src/lib/b.ts b/packages/kit/src/packaging/test/watch/src/lib/b.ts new file mode 100644 index 000000000000..9d7fe6fefebd --- /dev/null +++ b/packages/kit/src/packaging/test/watch/src/lib/b.ts @@ -0,0 +1 @@ +export const b = "b"; \ No newline at end of file diff --git a/packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/client/routes/index.js b/packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/client/routes/index.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/server/.well-known/test.js b/packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/server/.well-known/test.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/server/index.js b/packages/kit/src/vite/build/adapt/fixtures/basic/.svelte-kit/output/server/index.js new file mode 100644 index 000000000000..e69de29bb2d1 From f6217cd5b409ebe3bfa345d9d186207ae527e468 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 14:53:52 -0400 Subject: [PATCH 40/62] appease typescript. not sure why this started happening --- packages/kit/test/prerendering/basics/svelte.config.js | 4 ++-- packages/kit/test/prerendering/disabled/svelte.config.js | 2 +- packages/kit/test/prerendering/options/svelte.config.js | 2 +- packages/kit/test/prerendering/options/test/test.js | 2 +- packages/kit/test/prerendering/paths-base/svelte.config.js | 2 +- packages/kit/test/prerendering/paths-base/test/test.js | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/kit/test/prerendering/basics/svelte.config.js b/packages/kit/test/prerendering/basics/svelte.config.js index d1a233f77e2e..64275704c962 100644 --- a/packages/kit/test/prerendering/basics/svelte.config.js +++ b/packages/kit/test/prerendering/basics/svelte.config.js @@ -1,4 +1,4 @@ -import { resolve } from 'path'; +import * as path from 'path'; import adapter from '../../../../adapter-static/index.js'; /** @type {import('@sveltejs/kit').Config} */ @@ -18,7 +18,7 @@ const config = { clearScreen: false, server: { fs: { - allow: [resolve('../../../src')] + allow: [path.resolve('../../../src')] } } } diff --git a/packages/kit/test/prerendering/disabled/svelte.config.js b/packages/kit/test/prerendering/disabled/svelte.config.js index fd6c9adbfeda..692691aac8eb 100644 --- a/packages/kit/test/prerendering/disabled/svelte.config.js +++ b/packages/kit/test/prerendering/disabled/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import * as path from 'path'; import adapter from '../../../../adapter-static/index.js'; /** @type {import('@sveltejs/kit').Config} */ diff --git a/packages/kit/test/prerendering/options/svelte.config.js b/packages/kit/test/prerendering/options/svelte.config.js index dcd424c079a7..0e0bf7e3e6a2 100644 --- a/packages/kit/test/prerendering/options/svelte.config.js +++ b/packages/kit/test/prerendering/options/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import * as path from 'path'; import adapter from '../../../../adapter-static/index.js'; /** @type {import('@sveltejs/kit').Config} */ diff --git a/packages/kit/test/prerendering/options/test/test.js b/packages/kit/test/prerendering/options/test/test.js index 7b14ff16c6aa..7f104b4db614 100644 --- a/packages/kit/test/prerendering/options/test/test.js +++ b/packages/kit/test/prerendering/options/test/test.js @@ -1,4 +1,4 @@ -import fs from 'fs'; +import * as fs from 'fs'; import { fileURLToPath } from 'url'; import { test } from 'uvu'; import * as assert from 'uvu/assert'; diff --git a/packages/kit/test/prerendering/paths-base/svelte.config.js b/packages/kit/test/prerendering/paths-base/svelte.config.js index 4e1535a7684e..a489865dc085 100644 --- a/packages/kit/test/prerendering/paths-base/svelte.config.js +++ b/packages/kit/test/prerendering/paths-base/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import * as path from 'path'; import adapter from '../../../../adapter-static/index.js'; /** @type {import('@sveltejs/kit').Config} */ diff --git a/packages/kit/test/prerendering/paths-base/test/test.js b/packages/kit/test/prerendering/paths-base/test/test.js index 19ad704892a9..d2a47907a178 100644 --- a/packages/kit/test/prerendering/paths-base/test/test.js +++ b/packages/kit/test/prerendering/paths-base/test/test.js @@ -1,4 +1,4 @@ -import fs from 'fs'; +import * as fs from 'fs'; import { fileURLToPath } from 'url'; import { test } from 'uvu'; import * as assert from 'uvu/assert'; From cf4c5c9aab5cef8e9dd9a6f5c427c56f23bde7aa Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 14:59:12 -0400 Subject: [PATCH 41/62] whyyy --- packages/kit/test/apps/amp/svelte.config.js | 2 +- packages/kit/test/apps/basics/svelte.config.js | 2 +- packages/kit/test/apps/options-2/svelte.config.js | 2 +- packages/kit/test/apps/options/svelte.config.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/kit/test/apps/amp/svelte.config.js b/packages/kit/test/apps/amp/svelte.config.js index 9c3a2801c70a..9482e8972a83 100644 --- a/packages/kit/test/apps/amp/svelte.config.js +++ b/packages/kit/test/apps/amp/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import * as path from 'path'; /** @type {import('@sveltejs/kit').Config} */ const config = { diff --git a/packages/kit/test/apps/basics/svelte.config.js b/packages/kit/test/apps/basics/svelte.config.js index 68b1411a1fdc..a45140535e6d 100644 --- a/packages/kit/test/apps/basics/svelte.config.js +++ b/packages/kit/test/apps/basics/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import * as path from 'path'; /** @type {import('@sveltejs/kit').Config} */ const config = { diff --git a/packages/kit/test/apps/options-2/svelte.config.js b/packages/kit/test/apps/options-2/svelte.config.js index 8160cdf0cb8f..5d46d5f640fd 100644 --- a/packages/kit/test/apps/options-2/svelte.config.js +++ b/packages/kit/test/apps/options-2/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import * as path from 'path'; /** @type {import('@sveltejs/kit').Config} */ const config = { diff --git a/packages/kit/test/apps/options/svelte.config.js b/packages/kit/test/apps/options/svelte.config.js index 569ef37d3af6..dac417144b74 100644 --- a/packages/kit/test/apps/options/svelte.config.js +++ b/packages/kit/test/apps/options/svelte.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import * as path from 'path'; /** @type {import('@sveltejs/kit').Config} */ const config = { From baf68936ee4775c1c42939fb449f57498652164a Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 15:01:33 -0400 Subject: [PATCH 42/62] simplify --- packages/kit/src/vite/index.js | 4 +--- packages/kit/src/vite/plugin.js | 30 +++++++++++------------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 3a393b14037d..081d6275dbb6 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -1,3 +1 @@ -export { plugins as sveltekit } from './plugin.js'; - -process.env.SVELTE_VITE_CONFIG = 'true'; +export { sveltekit } from './plugin.js'; diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js index ef03ec5fdcb4..016183d804be 100644 --- a/packages/kit/src/vite/plugin.js +++ b/packages/kit/src/vite/plugin.js @@ -1,7 +1,7 @@ -import { svelte as svelte_plugin } from '@sveltejs/vite-plugin-svelte'; import fs from 'fs'; -import colors from 'kleur'; import path from 'path'; +import colors from 'kleur'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; import { searchForWorkspaceRoot } from 'vite'; import { mkdirp, posixify, rimraf } from '../utils/filesystem.js'; import * as sync from '../core/sync/sync.js'; @@ -18,10 +18,17 @@ import { deep_merge } from './utils.js'; const cwd = process.cwd(); +/** + * @return {import('vite').Plugin[]} + */ +export function sveltekit() { + return [...svelte(), kit()]; +} + /** * @return {import('vite').Plugin} */ -export const sveltekit = function () { +function kit() { /** @type {import('types').ValidatedConfig} */ let svelte_config; @@ -304,19 +311,4 @@ export const sveltekit = function () { return preview(vite, svelte_config, vite_resolved_config); } }; -}; - -/** - * @return {import('vite').Plugin[]} - */ -export const svelte = function () { - // TODO what is the purpose of this function? Why do we not just re-export it? - return svelte_plugin(); -}; - -/** - * @return {import('vite').Plugin[]} - */ -export const plugins = function () { - return [...svelte(), sveltekit()]; -}; +} From d85333758b230db58d6be665af5a3ee690a81dba Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 15:04:36 -0400 Subject: [PATCH 43/62] simplify --- packages/kit/src/cli.js | 5 +- packages/kit/src/vite/index.js | 315 +++++++++++++++++++++++++++++++- packages/kit/src/vite/plugin.js | 314 ------------------------------- 3 files changed, 317 insertions(+), 317 deletions(-) delete mode 100644 packages/kit/src/vite/plugin.js diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index ed51f20e36c2..7c1c7966f7b4 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -7,7 +7,6 @@ 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'; -import { sveltekit } from './vite/index.js'; /** @param {unknown} e */ function handle_error(e) { @@ -175,7 +174,7 @@ prog process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - const { sveltekit } = await import('./vite/plugin.js'); + const { sveltekit } = await import('./vite/index.js'); const svelte_config = await load_config(); const vite_config = await svelte_config.kit.vite(); @@ -312,6 +311,8 @@ export async function get_vite_config(svelte_config) { } } + const { sveltekit } = await import('./vite/index.js'); + // TODO: stop reading Vite config from SvelteKit config or move to CLI const vite_config = await svelte_config.kit.vite(); vite_config.plugins = [...(vite_config.plugins || []), ...sveltekit()]; diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 081d6275dbb6..016183d804be 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -1 +1,314 @@ -export { sveltekit } from './plugin.js'; +import fs from 'fs'; +import path from 'path'; +import colors from 'kleur'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; +import { searchForWorkspaceRoot } from 'vite'; +import { mkdirp, posixify, rimraf } from '../utils/filesystem.js'; +import * as sync from '../core/sync/sync.js'; +import { build_server } from './build/build_server.js'; +import { build_service_worker } from './build/build_service_worker.js'; +import { prerender } from './build/prerender/prerender.js'; +import { load_config, print_config_conflicts } from '../core/config/index.js'; +import { dev } from './dev/index.js'; +import { generate_manifest } from '../core/generate_manifest/index.js'; +import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; +import { find_deps, get_default_config } from './build/utils.js'; +import { preview } from './preview/index.js'; +import { deep_merge } from './utils.js'; + +const cwd = process.cwd(); + +/** + * @return {import('vite').Plugin[]} + */ +export function sveltekit() { + return [...svelte(), kit()]; +} + +/** + * @return {import('vite').Plugin} + */ +function kit() { + /** @type {import('types').ValidatedConfig} */ + let svelte_config; + + /** @type {import('vite').UserConfig} */ + let vite_user_config; + + /** @type {import('vite').ResolvedConfig} */ + let vite_resolved_config; + + /** @type {import('types').ManifestData|undefined} */ + let manifest_data = undefined; + + return { + name: 'vite-plugin-svelte-kit', + + async config(_config, env) { + vite_user_config = _config; + + svelte_config = await load_config(); + + const build_dir = path.join(svelte_config.kit.outDir, 'build'); + const output_dir = path.join(svelte_config.kit.outDir, 'output'); + const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; + const client_entry_file = path.relative( + cwd, + `${get_runtime_path(svelte_config.kit)}/client/start.js` + ); + + if (env.command === 'build') { + rimraf(build_dir); + mkdirp(build_dir); + + rimraf(output_dir); + mkdirp(output_dir); + + process.env.VITE_SVELTEKIT_APP_VERSION = svelte_config.kit.version.name; + process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${svelte_config.kit.appDir}/version.json`; + process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${svelte_config.kit.version.pollInterval}`; + + manifest_data = sync.all(svelte_config).manifest_data; + + /** @type {Record} */ + const input = { + start: path.resolve(cwd, client_entry_file) + }; + + // This step is optional — Vite/Rollup will create the necessary chunks + // for everything regardless — but it means that entry chunks reflect + // their location in the source code, which is helpful for debugging + manifest_data.components.forEach((file) => { + const resolved = path.resolve(cwd, file); + const relative = path.relative(svelte_config.kit.files.routes, resolved); + + const name = relative.startsWith('..') + ? path.basename(file) + : posixify(path.join('pages', relative)); + input[name] = resolved; + }); + + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge( + {}, + get_default_config({ + client_out_dir, + config: svelte_config, + input, + output_dir, + ssr: false + }) + ); + + print_config_conflicts(conflicts, 'kit.vite.', 'build_client'); + + return merged_config; + } + + // dev and preview config can be shared + const vite_config = { + preview: { + port: 3000, + strictPort: true + }, + 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: [ + // Ignore all siblings of config.kit.outDir/generated + `${posixify(svelte_config.kit.outDir)}/!(generated)` + ] + } + }, + spa: false + }; + + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge(vite_config, { + configFile: false, + root: cwd, + resolve: { + alias: get_aliases(svelte_config.kit) + }, + build: { + rollupOptions: { + // Vite dependency crawler needs an explicit JS entry point + // eventhough server otherwise works without it + input: `${get_runtime_path(svelte_config.kit)}/client/start.js` + } + }, + base: '/' + }); + + // TODO: compare resolved config to defaults to validate + print_config_conflicts(conflicts, 'kit.vite.'); + + return merged_config; + }, + + configResolved(config) { + vite_resolved_config = config; + }, + + async writeBundle(_options, bundle) { + if (!manifest_data) throw Error('manifest_data not populated'); + + const log = logger({ verbose: !!process.env.VERBOSE }); + + const build_dir = path.join(svelte_config.kit.outDir, 'build'); + const output_dir = path.join(svelte_config.kit.outDir, 'output'); + const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; + const client_entry_file = path.relative( + cwd, + `${get_runtime_path(svelte_config.kit)}/client/start.js` + ); + + /** @type {import('rollup').OutputChunk[]} */ + const chunks = []; + /** @type {import('rollup').OutputAsset[]} */ + const assets = []; + for (const key of Object.keys(bundle)) { + // collect asset and output chunks + if (bundle[key].type === 'asset') { + assets.push(/** @type {import('rollup').OutputAsset} */ (bundle[key])); + } else { + chunks.push(/** @type {import('rollup').OutputChunk} */ (bundle[key])); + } + } + + /** @type {import('vite').Manifest} */ + const vite_manifest = JSON.parse( + fs.readFileSync(`${client_out_dir}/immutable/manifest.json`, 'utf-8') + ); + + const entry = posixify(client_entry_file); + const entry_js = new Set(); + const entry_css = new Set(); + find_deps(entry, vite_manifest, entry_js, entry_css); + + fs.writeFileSync( + `${client_out_dir}/version.json`, + JSON.stringify({ version: process.env.VITE_SVELTEKIT_APP_VERSION }) + ); + const client = { + assets, + chunks, + entry: { + file: vite_manifest[entry].file, + js: Array.from(entry_js), + css: Array.from(entry_css) + }, + vite_manifest + }; + log.info(`Client build completed. Wrote ${chunks.length} chunks and ${assets.length} assets`); + + const options = { + cwd, + config: svelte_config, + build_dir, + manifest_data, + output_dir, + client_entry_file, + service_worker_entry_file: resolve_entry(svelte_config.kit.files.serviceWorker) + }; + + log.info('Building server'); + + const server = await build_server(vite_user_config, options, client); + + process.env.SVELTEKIT_SERVER_BUILD_COMPLETED = 'true'; + + /** @type {import('types').BuildData} */ + const build_data = { + app_dir: svelte_config.kit.appDir, + manifest_data, + service_worker: options.service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable? + client, + server + }; + + const manifest = `export const manifest = ${generate_manifest({ + build_data, + relative_path: '.', + routes: manifest_data.routes + })};\n`; + fs.writeFileSync(`${output_dir}/server/manifest.js`, manifest); + + const static_files = manifest_data.assets.map((asset) => posixify(asset.file)); + + const files = new Set([ + ...static_files, + ...chunks.map((chunk) => `${svelte_config.kit.appDir}/immutable/${chunk.fileName}`), + ...assets.map((chunk) => `${svelte_config.kit.appDir}/immutable/${chunk.fileName}`) + ]); + + // TODO is this right? + static_files.forEach((file) => { + if (file.endsWith('/index.html')) { + files.add(file.slice(0, -11)); + } + }); + + log.info('Prerendering'); + + const prerendered = await prerender({ + config: svelte_config.kit, + entries: manifest_data.routes + .map((route) => (route.type === 'page' ? route.path : '')) + .filter(Boolean), + files, + log + }); + + if (options.service_worker_entry_file) { + if (svelte_config.kit.paths.assets) { + throw new Error('Cannot use service worker alongside config.kit.paths.assets'); + } + + log.info('Building service worker'); + + await build_service_worker(vite_user_config, options, prerendered, client.vite_manifest); + } + + console.log( + `\nRun ${colors.bold().cyan('npm run preview')} to preview your production build locally.` + ); + + if (svelte_config.kit.adapter) { + const { adapt } = await import('./build/adapt/index.js'); + await adapt(svelte_config, build_data, prerendered, { log }); + + // this is necessary to close any open db connections, etc + process.exit(0); + } + + console.log(colors.bold().yellow('\nNo adapter specified')); + + // prettier-ignore + console.log( + `See ${colors.bold().cyan('https://kit.svelte.dev/docs/adapters')} to learn how to configure your app to run on the platform of your choosing` + ); + }, + + async configureServer(vite) { + return await dev(vite, svelte_config); + }, + + configurePreviewServer(vite) { + return preview(vite, svelte_config, vite_resolved_config); + } + }; +} diff --git a/packages/kit/src/vite/plugin.js b/packages/kit/src/vite/plugin.js deleted file mode 100644 index 016183d804be..000000000000 --- a/packages/kit/src/vite/plugin.js +++ /dev/null @@ -1,314 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import colors from 'kleur'; -import { svelte } from '@sveltejs/vite-plugin-svelte'; -import { searchForWorkspaceRoot } from 'vite'; -import { mkdirp, posixify, rimraf } from '../utils/filesystem.js'; -import * as sync from '../core/sync/sync.js'; -import { build_server } from './build/build_server.js'; -import { build_service_worker } from './build/build_service_worker.js'; -import { prerender } from './build/prerender/prerender.js'; -import { load_config, print_config_conflicts } from '../core/config/index.js'; -import { dev } from './dev/index.js'; -import { generate_manifest } from '../core/generate_manifest/index.js'; -import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; -import { find_deps, get_default_config } from './build/utils.js'; -import { preview } from './preview/index.js'; -import { deep_merge } from './utils.js'; - -const cwd = process.cwd(); - -/** - * @return {import('vite').Plugin[]} - */ -export function sveltekit() { - return [...svelte(), kit()]; -} - -/** - * @return {import('vite').Plugin} - */ -function kit() { - /** @type {import('types').ValidatedConfig} */ - let svelte_config; - - /** @type {import('vite').UserConfig} */ - let vite_user_config; - - /** @type {import('vite').ResolvedConfig} */ - let vite_resolved_config; - - /** @type {import('types').ManifestData|undefined} */ - let manifest_data = undefined; - - return { - name: 'vite-plugin-svelte-kit', - - async config(_config, env) { - vite_user_config = _config; - - svelte_config = await load_config(); - - const build_dir = path.join(svelte_config.kit.outDir, 'build'); - const output_dir = path.join(svelte_config.kit.outDir, 'output'); - const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; - const client_entry_file = path.relative( - cwd, - `${get_runtime_path(svelte_config.kit)}/client/start.js` - ); - - if (env.command === 'build') { - rimraf(build_dir); - mkdirp(build_dir); - - rimraf(output_dir); - mkdirp(output_dir); - - process.env.VITE_SVELTEKIT_APP_VERSION = svelte_config.kit.version.name; - process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${svelte_config.kit.appDir}/version.json`; - process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${svelte_config.kit.version.pollInterval}`; - - manifest_data = sync.all(svelte_config).manifest_data; - - /** @type {Record} */ - const input = { - start: path.resolve(cwd, client_entry_file) - }; - - // This step is optional — Vite/Rollup will create the necessary chunks - // for everything regardless — but it means that entry chunks reflect - // their location in the source code, which is helpful for debugging - manifest_data.components.forEach((file) => { - const resolved = path.resolve(cwd, file); - const relative = path.relative(svelte_config.kit.files.routes, resolved); - - const name = relative.startsWith('..') - ? path.basename(file) - : posixify(path.join('pages', relative)); - input[name] = resolved; - }); - - /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge( - {}, - get_default_config({ - client_out_dir, - config: svelte_config, - input, - output_dir, - ssr: false - }) - ); - - print_config_conflicts(conflicts, 'kit.vite.', 'build_client'); - - return merged_config; - } - - // dev and preview config can be shared - const vite_config = { - preview: { - port: 3000, - strictPort: true - }, - 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: [ - // Ignore all siblings of config.kit.outDir/generated - `${posixify(svelte_config.kit.outDir)}/!(generated)` - ] - } - }, - spa: false - }; - - /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge(vite_config, { - configFile: false, - root: cwd, - resolve: { - alias: get_aliases(svelte_config.kit) - }, - build: { - rollupOptions: { - // Vite dependency crawler needs an explicit JS entry point - // eventhough server otherwise works without it - input: `${get_runtime_path(svelte_config.kit)}/client/start.js` - } - }, - base: '/' - }); - - // TODO: compare resolved config to defaults to validate - print_config_conflicts(conflicts, 'kit.vite.'); - - return merged_config; - }, - - configResolved(config) { - vite_resolved_config = config; - }, - - async writeBundle(_options, bundle) { - if (!manifest_data) throw Error('manifest_data not populated'); - - const log = logger({ verbose: !!process.env.VERBOSE }); - - const build_dir = path.join(svelte_config.kit.outDir, 'build'); - const output_dir = path.join(svelte_config.kit.outDir, 'output'); - const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; - const client_entry_file = path.relative( - cwd, - `${get_runtime_path(svelte_config.kit)}/client/start.js` - ); - - /** @type {import('rollup').OutputChunk[]} */ - const chunks = []; - /** @type {import('rollup').OutputAsset[]} */ - const assets = []; - for (const key of Object.keys(bundle)) { - // collect asset and output chunks - if (bundle[key].type === 'asset') { - assets.push(/** @type {import('rollup').OutputAsset} */ (bundle[key])); - } else { - chunks.push(/** @type {import('rollup').OutputChunk} */ (bundle[key])); - } - } - - /** @type {import('vite').Manifest} */ - const vite_manifest = JSON.parse( - fs.readFileSync(`${client_out_dir}/immutable/manifest.json`, 'utf-8') - ); - - const entry = posixify(client_entry_file); - const entry_js = new Set(); - const entry_css = new Set(); - find_deps(entry, vite_manifest, entry_js, entry_css); - - fs.writeFileSync( - `${client_out_dir}/version.json`, - JSON.stringify({ version: process.env.VITE_SVELTEKIT_APP_VERSION }) - ); - const client = { - assets, - chunks, - entry: { - file: vite_manifest[entry].file, - js: Array.from(entry_js), - css: Array.from(entry_css) - }, - vite_manifest - }; - log.info(`Client build completed. Wrote ${chunks.length} chunks and ${assets.length} assets`); - - const options = { - cwd, - config: svelte_config, - build_dir, - manifest_data, - output_dir, - client_entry_file, - service_worker_entry_file: resolve_entry(svelte_config.kit.files.serviceWorker) - }; - - log.info('Building server'); - - const server = await build_server(vite_user_config, options, client); - - process.env.SVELTEKIT_SERVER_BUILD_COMPLETED = 'true'; - - /** @type {import('types').BuildData} */ - const build_data = { - app_dir: svelte_config.kit.appDir, - manifest_data, - service_worker: options.service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable? - client, - server - }; - - const manifest = `export const manifest = ${generate_manifest({ - build_data, - relative_path: '.', - routes: manifest_data.routes - })};\n`; - fs.writeFileSync(`${output_dir}/server/manifest.js`, manifest); - - const static_files = manifest_data.assets.map((asset) => posixify(asset.file)); - - const files = new Set([ - ...static_files, - ...chunks.map((chunk) => `${svelte_config.kit.appDir}/immutable/${chunk.fileName}`), - ...assets.map((chunk) => `${svelte_config.kit.appDir}/immutable/${chunk.fileName}`) - ]); - - // TODO is this right? - static_files.forEach((file) => { - if (file.endsWith('/index.html')) { - files.add(file.slice(0, -11)); - } - }); - - log.info('Prerendering'); - - const prerendered = await prerender({ - config: svelte_config.kit, - entries: manifest_data.routes - .map((route) => (route.type === 'page' ? route.path : '')) - .filter(Boolean), - files, - log - }); - - if (options.service_worker_entry_file) { - if (svelte_config.kit.paths.assets) { - throw new Error('Cannot use service worker alongside config.kit.paths.assets'); - } - - log.info('Building service worker'); - - await build_service_worker(vite_user_config, options, prerendered, client.vite_manifest); - } - - console.log( - `\nRun ${colors.bold().cyan('npm run preview')} to preview your production build locally.` - ); - - if (svelte_config.kit.adapter) { - const { adapt } = await import('./build/adapt/index.js'); - await adapt(svelte_config, build_data, prerendered, { log }); - - // this is necessary to close any open db connections, etc - process.exit(0); - } - - console.log(colors.bold().yellow('\nNo adapter specified')); - - // prettier-ignore - console.log( - `See ${colors.bold().cyan('https://kit.svelte.dev/docs/adapters')} to learn how to configure your app to run on the platform of your choosing` - ); - }, - - async configureServer(vite) { - return await dev(vite, svelte_config); - }, - - configurePreviewServer(vite) { - return preview(vite, svelte_config, vite_resolved_config); - } - }; -} From 901dd781fdf9b18a0de182e654e321c049313e63 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 15:06:27 -0400 Subject: [PATCH 44/62] simplify --- packages/kit/src/cli.js | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 7c1c7966f7b4..1dcff209afd4 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -174,32 +174,18 @@ prog process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - const { sveltekit } = await import('./vite/index.js'); const svelte_config = await load_config(); - const vite_config = await svelte_config.kit.vite(); - - const has_vite_config = fs.existsSync('vite.config.js'); + const vite_config = await get_vite_config(svelte_config); - /** @type {import('vite').UserConfig} */ - const config = { - ...vite_config, - plugins: [...(vite_config.plugins || []), has_vite_config ? [] : sveltekit()] - }; - config.preview = config.preview || {}; + vite_config.preview = vite_config.preview || {}; // optional config from command-line flags // these should take precedence, but not print conflict warnings - if (host) { - config.preview.host = host; - } - if (https) { - config.preview.https = https; - } - if (port) { - config.preview.port = port; - } + if (host) vite_config.preview.host = host; + if (https) vite_config.preview.https = https; + if (port) vite_config.preview.port = port; - const preview_server = await vite.preview(config); + const preview_server = await vite.preview(vite_config); welcome({ port, host, https, open, base: preview_server.config.base }); } catch (error) { From 250e4b99ae92b897152cf10d50e3be2ab1847fff Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 15:35:29 -0400 Subject: [PATCH 45/62] respect user config in build --- packages/kit/src/vite/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 016183d804be..b89c1b1664f4 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -44,8 +44,8 @@ function kit() { return { name: 'vite-plugin-svelte-kit', - async config(_config, env) { - vite_user_config = _config; + async config(config, env) { + vite_user_config = config; svelte_config = await load_config(); @@ -90,7 +90,7 @@ function kit() { /** @type {[any, string[]]} */ const [merged_config, conflicts] = deep_merge( - {}, + vite_user_config, get_default_config({ client_out_dir, config: svelte_config, From 7610ab5e087acec966405a48faf0863a2686dfdd Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 12:38:04 -0700 Subject: [PATCH 46/62] update turbo cache --- turbo.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/turbo.json b/turbo.json index afcb8ae67afd..1316f3c80926 100644 --- a/turbo.json +++ b/turbo.json @@ -24,7 +24,7 @@ }, "check": { "dependsOn": ["sync"], - "inputs": ["src/**", "types/**", ".svelte-kit/types/**", ".custom-out-dir/types/**"], + "inputs": ["src/**", "types/**", ".svelte-kit/types/**", ".custom-out-dir/types/**", ".svelte-kit/tsconfig.json"], "outputs": [] }, "format": {}, From 75b3f5a4a48d8a75fcb3202a45cf1762e8ad3a87 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 12:42:17 -0700 Subject: [PATCH 47/62] format --- packages/kit/src/packaging/test/watch/src/lib/a.js | 2 +- packages/kit/src/packaging/test/watch/src/lib/b.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/packaging/test/watch/src/lib/a.js b/packages/kit/src/packaging/test/watch/src/lib/a.js index 961d97e14bdc..c4a2d30fbc2d 100644 --- a/packages/kit/src/packaging/test/watch/src/lib/a.js +++ b/packages/kit/src/packaging/test/watch/src/lib/a.js @@ -1 +1 @@ -export const a = "a"; \ No newline at end of file +export const a = 'a'; diff --git a/packages/kit/src/packaging/test/watch/src/lib/b.ts b/packages/kit/src/packaging/test/watch/src/lib/b.ts index 9d7fe6fefebd..137b8ce6429a 100644 --- a/packages/kit/src/packaging/test/watch/src/lib/b.ts +++ b/packages/kit/src/packaging/test/watch/src/lib/b.ts @@ -1 +1 @@ -export const b = "b"; \ No newline at end of file +export const b = 'b'; From d6553638858f53365b98e2a6f90c09487fc855b7 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 12:49:13 -0700 Subject: [PATCH 48/62] resolveJsonModule --- packages/kit/test/apps/basics/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/kit/test/apps/basics/tsconfig.json b/packages/kit/test/apps/basics/tsconfig.json index 236014c1f2df..a1e1e2da2142 100644 --- a/packages/kit/test/apps/basics/tsconfig.json +++ b/packages/kit/test/apps/basics/tsconfig.json @@ -9,7 +9,8 @@ "$lib": ["./src/lib"], "$lib/*": ["./src/lib/*"], "types": ["../../../types/internal"] - } + }, + "resolveJsonModule": true }, "extends": "./.svelte-kit/tsconfig.json" } From 61905b4106a0e5f66f956095c7c739506e574aa7 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 16:02:52 -0400 Subject: [PATCH 49/62] remove unnecessary configResolved hook --- packages/kit/src/vite/index.js | 10 ++-------- packages/kit/src/vite/preview/index.js | 7 +++---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index b89c1b1664f4..99a2033e016c 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -35,9 +35,6 @@ function kit() { /** @type {import('vite').UserConfig} */ let vite_user_config; - /** @type {import('vite').ResolvedConfig} */ - let vite_resolved_config; - /** @type {import('types').ManifestData|undefined} */ let manifest_data = undefined; @@ -159,10 +156,6 @@ function kit() { return merged_config; }, - configResolved(config) { - vite_resolved_config = config; - }, - async writeBundle(_options, bundle) { if (!manifest_data) throw Error('manifest_data not populated'); @@ -308,7 +301,8 @@ function kit() { }, configurePreviewServer(vite) { - return preview(vite, svelte_config, vite_resolved_config); + const protocol = vite_user_config.preview?.https ? 'https' : 'http'; + return preview(vite, svelte_config, protocol); } }; } diff --git a/packages/kit/src/vite/preview/index.js b/packages/kit/src/vite/preview/index.js index 327efa96e37a..078e6146ed3a 100644 --- a/packages/kit/src/vite/preview/index.js +++ b/packages/kit/src/vite/preview/index.js @@ -16,9 +16,9 @@ import { SVELTE_KIT_ASSETS } from '../../core/constants.js'; * httpServer: import('http').Server; * }} vite * @param {import('types').ValidatedConfig} config - * @param {import('vite').ResolvedConfig} vite_config + * @param {'http' | 'https'} protocol */ -export async function preview(vite, config, vite_config) { +export async function preview(vite, config, protocol) { installPolyfills(); const { paths } = config.kit; @@ -37,7 +37,7 @@ export async function preview(vite, config, vite_config) { override({ paths: { base, assets }, prerendering: false, - protocol: vite_config.preview?.https ? 'https' : 'http', + protocol, read: (file) => fs.readFileSync(join(config.kit.files.assets, file)) }); @@ -123,7 +123,6 @@ export async function preview(vite, config, vite_config) { // SSR vite.middlewares.use(async (req, res) => { - const protocol = vite_config.preview?.https ? 'https' : 'http'; const host = req.headers['host']; let request; From 2fd09a9676f404de6bde3527d4dd5980a1d09ad4 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 16:16:35 -0400 Subject: [PATCH 50/62] remove unused option --- packages/kit/src/vite/build/build_server.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index 07b3486842e0..ed5ce8ad2e20 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -179,7 +179,6 @@ export async function build_server(vite_config, options, client) { build: { target: 'node14.8' }, - plugins: [], ssr: { // when developing against the Kit src code, we want to ensure that // our dependencies are bundled so that apps don't need to install From 95ddabec718aac7e4343b33b9a331c54c531376f Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 16:30:23 -0400 Subject: [PATCH 51/62] minor simplification --- packages/kit/src/vite/build/build_server.js | 2 +- packages/kit/src/vite/build/utils.js | 7 +++---- packages/kit/src/vite/index.js | 5 ++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index ed5ce8ad2e20..c09716cd2bd3 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -198,7 +198,7 @@ export async function build_server(vite_config, options, client) { /** @type {[any, string[]]} */ const [merged_config, conflicts] = deep_merge( modified_vite_config, - get_default_config({ ...options, input, ssr: true }) + get_default_config({ config, input, ssr: true, outDir: `${output_dir}/server` }) ); print_config_conflicts(conflicts, 'kit.vite.', 'build_server'); diff --git a/packages/kit/src/vite/build/utils.js b/packages/kit/src/vite/build/utils.js index 381857db0607..5ce5e4252530 100644 --- a/packages/kit/src/vite/build/utils.js +++ b/packages/kit/src/vite/build/utils.js @@ -52,21 +52,20 @@ export function find_deps(file, manifest, js, css) { /** * The Vite configuration that we use by default. * @param {{ - * client_out_dir?: string; * config: import('types').ValidatedConfig; * input: Record; - * output_dir: string; * ssr: boolean; + * outDir: string; * }} options * @return {import('vite').UserConfig} */ -export const get_default_config = function ({ client_out_dir, config, input, output_dir, ssr }) { +export const get_default_config = function ({ config, input, ssr, outDir }) { return { base: assets_base(config.kit), build: { cssCodeSplit: true, manifest: true, - outDir: ssr ? `${output_dir}/server` : `${client_out_dir}/immutable`, + outDir, polyfillDynamicImport: false, rollupOptions: { input, diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 99a2033e016c..5bbd2ef66170 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -89,11 +89,10 @@ function kit() { const [merged_config, conflicts] = deep_merge( vite_user_config, get_default_config({ - client_out_dir, config: svelte_config, input, - output_dir, - ssr: false + ssr: false, + outDir: `${client_out_dir}/immutable` }) ); From 8b431a849971a97b77697d42ca97e65f0547ff1e Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 16:33:19 -0400 Subject: [PATCH 52/62] simplify --- packages/kit/src/vite/index.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 5bbd2ef66170..06f3c2c9dcc8 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -35,8 +35,8 @@ function kit() { /** @type {import('vite').UserConfig} */ let vite_user_config; - /** @type {import('types').ManifestData|undefined} */ - let manifest_data = undefined; + /** @type {import('types').ManifestData} */ + let manifest_data; return { name: 'vite-plugin-svelte-kit', @@ -156,8 +156,6 @@ function kit() { }, async writeBundle(_options, bundle) { - if (!manifest_data) throw Error('manifest_data not populated'); - const log = logger({ verbose: !!process.env.VERBOSE }); const build_dir = path.join(svelte_config.kit.outDir, 'build'); From 288a2fe9c301d6b357be06e136ed358e165a50d6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 16:38:20 -0400 Subject: [PATCH 53/62] move some stuff closer to where its used --- packages/kit/src/vite/index.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 06f3c2c9dcc8..bd35fea5c7d7 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -43,18 +43,17 @@ function kit() { async config(config, env) { vite_user_config = config; - svelte_config = await load_config(); - const build_dir = path.join(svelte_config.kit.outDir, 'build'); - const output_dir = path.join(svelte_config.kit.outDir, 'output'); - const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; - const client_entry_file = path.relative( - cwd, - `${get_runtime_path(svelte_config.kit)}/client/start.js` - ); - if (env.command === 'build') { + const build_dir = path.join(svelte_config.kit.outDir, 'build'); + const output_dir = path.join(svelte_config.kit.outDir, 'output'); + const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; + const client_entry_file = path.relative( + cwd, + `${get_runtime_path(svelte_config.kit)}/client/start.js` + ); + rimraf(build_dir); mkdirp(build_dir); From 54f81ee172e21ad51b0fcf9db4e33f7923be934b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 17:01:07 -0400 Subject: [PATCH 54/62] dry some stuff out, move some stuff to buildStart --- packages/kit/src/vite/index.js | 72 +++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index bd35fea5c7d7..95529d6aeec4 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -38,37 +38,32 @@ function kit() { /** @type {import('types').ManifestData} */ let manifest_data; + /** @type {{ + * build_dir: string; + * output_dir: string; + * client_out_dir: string; + * }} */ + let paths; + return { name: 'vite-plugin-svelte-kit', - async config(config, env) { + async config(config, { command }) { vite_user_config = config; svelte_config = await load_config(); - if (env.command === 'build') { - const build_dir = path.join(svelte_config.kit.outDir, 'build'); - const output_dir = path.join(svelte_config.kit.outDir, 'output'); - const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; - const client_entry_file = path.relative( - cwd, - `${get_runtime_path(svelte_config.kit)}/client/start.js` - ); - - rimraf(build_dir); - mkdirp(build_dir); - - rimraf(output_dir); - mkdirp(output_dir); - - process.env.VITE_SVELTEKIT_APP_VERSION = svelte_config.kit.version.name; - process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${svelte_config.kit.appDir}/version.json`; - process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${svelte_config.kit.version.pollInterval}`; + paths = { + build_dir: `${svelte_config.kit.outDir}/build`, + output_dir: `${svelte_config.kit.outDir}/output`, + client_out_dir: `${svelte_config.kit.outDir}/output/client/${svelte_config.kit.appDir}` + }; + if (command === 'build') { manifest_data = sync.all(svelte_config).manifest_data; /** @type {Record} */ const input = { - start: path.resolve(cwd, client_entry_file) + start: `${get_runtime_path(svelte_config.kit)}/client/start.js` }; // This step is optional — Vite/Rollup will create the necessary chunks @@ -91,7 +86,7 @@ function kit() { config: svelte_config, input, ssr: false, - outDir: `${client_out_dir}/immutable` + outDir: `${paths.client_out_dir}/immutable` }) ); @@ -154,17 +149,21 @@ function kit() { return merged_config; }, + buildStart() { + rimraf(paths.build_dir); + mkdirp(paths.build_dir); + + rimraf(paths.output_dir); + mkdirp(paths.output_dir); + + process.env.VITE_SVELTEKIT_APP_VERSION = svelte_config.kit.version.name; + process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${svelte_config.kit.appDir}/version.json`; + process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${svelte_config.kit.version.pollInterval}`; + }, + async writeBundle(_options, bundle) { const log = logger({ verbose: !!process.env.VERBOSE }); - const build_dir = path.join(svelte_config.kit.outDir, 'build'); - const output_dir = path.join(svelte_config.kit.outDir, 'output'); - const client_out_dir = `${output_dir}/client/${svelte_config.kit.appDir}`; - const client_entry_file = path.relative( - cwd, - `${get_runtime_path(svelte_config.kit)}/client/start.js` - ); - /** @type {import('rollup').OutputChunk[]} */ const chunks = []; /** @type {import('rollup').OutputAsset[]} */ @@ -180,16 +179,18 @@ function kit() { /** @type {import('vite').Manifest} */ const vite_manifest = JSON.parse( - fs.readFileSync(`${client_out_dir}/immutable/manifest.json`, 'utf-8') + fs.readFileSync(`${paths.client_out_dir}/immutable/manifest.json`, 'utf-8') ); - const entry = posixify(client_entry_file); + const entry = posixify( + path.relative(cwd, `${get_runtime_path(svelte_config.kit)}/client/start.js`) + ); const entry_js = new Set(); const entry_css = new Set(); find_deps(entry, vite_manifest, entry_js, entry_css); fs.writeFileSync( - `${client_out_dir}/version.json`, + `${paths.client_out_dir}/version.json`, JSON.stringify({ version: process.env.VITE_SVELTEKIT_APP_VERSION }) ); const client = { @@ -207,10 +208,9 @@ function kit() { const options = { cwd, config: svelte_config, - build_dir, + build_dir: paths.build_dir, // TODO just pass `paths` manifest_data, - output_dir, - client_entry_file, + output_dir: paths.output_dir, service_worker_entry_file: resolve_entry(svelte_config.kit.files.serviceWorker) }; @@ -234,7 +234,7 @@ function kit() { relative_path: '.', routes: manifest_data.routes })};\n`; - fs.writeFileSync(`${output_dir}/server/manifest.js`, manifest); + fs.writeFileSync(`${paths.output_dir}/server/manifest.js`, manifest); const static_files = manifest_data.assets.map((asset) => posixify(asset.file)); From c8b1f9a073770882c78fe6a96b7ff76b35c285a1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 18:09:33 -0400 Subject: [PATCH 55/62] do all config checking up-front --- packages/kit/src/vite/build/build_server.js | 4 +- .../src/vite/build/build_service_worker.js | 4 +- packages/kit/src/vite/index.js | 104 +++++++++++++----- 3 files changed, 81 insertions(+), 31 deletions(-) diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index c09716cd2bd3..aa9426815fe3 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -196,13 +196,11 @@ export async function build_server(vite_config, options, client) { const [modified_vite_config] = deep_merge(default_config, vite_config); /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge( + const [merged_config] = deep_merge( modified_vite_config, get_default_config({ config, input, ssr: true, outDir: `${output_dir}/server` }) ); - print_config_conflicts(conflicts, 'kit.vite.', 'build_server'); - remove_svelte_kit(merged_config); process.env.VITE_SVELTEKIT_ADAPTER_NAME = config.kit.adapter?.name; diff --git a/packages/kit/src/vite/build/build_service_worker.js b/packages/kit/src/vite/build/build_service_worker.js index 8c912f6f0903..14899e69384a 100644 --- a/packages/kit/src/vite/build/build_service_worker.js +++ b/packages/kit/src/vite/build/build_service_worker.js @@ -69,7 +69,7 @@ export async function build_service_worker( ); /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge(vite_config, { + const [merged_config] = deep_merge(vite_config, { base: assets_base(config.kit), build: { lib: { @@ -93,8 +93,6 @@ export async function build_service_worker( } }); - print_config_conflicts(conflicts, 'kit.vite.', 'build_service_worker'); - remove_svelte_kit(merged_config); await vite.build(merged_config); diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 95529d6aeec4..da69d636ed52 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -8,7 +8,7 @@ import * as sync from '../core/sync/sync.js'; import { build_server } from './build/build_server.js'; import { build_service_worker } from './build/build_service_worker.js'; import { prerender } from './build/prerender/prerender.js'; -import { load_config, print_config_conflicts } from '../core/config/index.js'; +import { load_config, print_config_conflicts, validate_config } from '../core/config/index.js'; import { dev } from './dev/index.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; @@ -18,6 +18,42 @@ import { deep_merge } from './utils.js'; const cwd = process.cwd(); +const enforced_config = { + base: true, + build: { + cssCodeSplit: true, + emptyOutDir: true, + lib: { + entry: true, + name: true, + formats: true + }, + manifest: true, + outDir: true, + polyfillDynamicImport: true, + rollupOptions: { + input: true, + output: { + format: true, + entryFileNames: true, + chunkFileNames: true, + assetFileNames: true + }, + preserveEntrySignatures: true + }, + ssr: true + }, + publicDir: true, + resolve: { + alias: { + $app: true, + $lib: true, + '$service-worker': true + } + }, + root: true +}; + /** * @return {import('vite').Plugin[]} */ @@ -49,6 +85,15 @@ function kit() { name: 'vite-plugin-svelte-kit', async config(config, { command }) { + const overridden = find_overridden_config(config, enforced_config); + + if (overridden.length > 0) { + console.log( + colors.bold().red('The following Vite config options will be overridden by SvelteKit:') + ); + console.log(overridden.map((key) => ` - ${key}`).join('\n')); + } + vite_user_config = config; svelte_config = await load_config(); @@ -79,20 +124,12 @@ function kit() { input[name] = resolved; }); - /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge( - vite_user_config, - get_default_config({ - config: svelte_config, - input, - ssr: false, - outDir: `${paths.client_out_dir}/immutable` - }) - ); - - print_config_conflicts(conflicts, 'kit.vite.', 'build_client'); - - return merged_config; + return get_default_config({ + config: svelte_config, + input, + ssr: false, + outDir: `${paths.client_out_dir}/immutable` + }); } // dev and preview config can be shared @@ -127,12 +164,8 @@ function kit() { }; /** @type {[any, string[]]} */ - const [merged_config, conflicts] = deep_merge(vite_config, { - configFile: false, - root: cwd, - resolve: { - alias: get_aliases(svelte_config.kit) - }, + const [merged_config] = deep_merge(vite_config, { + base: '/', build: { rollupOptions: { // Vite dependency crawler needs an explicit JS entry point @@ -140,12 +173,12 @@ function kit() { input: `${get_runtime_path(svelte_config.kit)}/client/start.js` } }, - base: '/' + resolve: { + alias: get_aliases(svelte_config.kit) + }, + root: cwd }); - // TODO: compare resolved config to defaults to validate - print_config_conflicts(conflicts, 'kit.vite.'); - return merged_config; }, @@ -302,3 +335,24 @@ function kit() { } }; } + +/** + * + * @param {Record} config + * @param {Record} enforced_config + * @param {string} path + * @param {string[]} out + */ +function find_overridden_config(config, enforced_config, path = '', out = []) { + for (const key in enforced_config) { + if (key in config) { + if (enforced_config[key] === true) { + out.push(path + key); + } else { + find_overridden_config(config[key], enforced_config[key], path + key + '.', out); + } + } + } + + return out; +} From f81a86c45ca03750fa758d89f7c5184d7364f657 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 18:10:15 -0400 Subject: [PATCH 56/62] remove unused print_config_conflicts --- packages/kit/src/core/config/index.js | 16 ---------------- packages/kit/src/vite/build/build_server.js | 2 +- .../kit/src/vite/build/build_service_worker.js | 1 - packages/kit/src/vite/index.js | 2 +- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 7acfae374d0a..004c17a984a1 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -85,19 +85,3 @@ export function validate_config(config) { return options(config, 'config'); } - -/** - * Ensures the user does not override any config values that SvelteKit must control. - * @param {string[]} conflicts - array of conflicts in dotted notation - * @param {string=} pathPrefix - prepended in front of the path - * @param {string=} scope - used to prefix the whole error message - */ -export function print_config_conflicts(conflicts, pathPrefix = '', scope) { - const prefix = scope ? scope + ': ' : ''; - const log = logger({ verbose: false }); - conflicts.forEach((conflict) => { - log.error( - `${prefix}The value for ${pathPrefix}${conflict} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` - ); - }); -} diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index aa9426815fe3..30d23c8433d7 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; import { mkdirp, posixify } from '../../utils/filesystem.js'; import { deep_merge } from '../utils.js'; -import { load_template, print_config_conflicts } from '../../core/config/index.js'; +import { load_template } from '../../core/config/index.js'; import { get_runtime_path, resolve_entry } from '../../core/utils.js'; import { create_build, find_deps, get_default_config, remove_svelte_kit } from './utils.js'; import { s } from '../../utils/misc.js'; diff --git a/packages/kit/src/vite/build/build_service_worker.js b/packages/kit/src/vite/build/build_service_worker.js index 14899e69384a..b6ea9051ac35 100644 --- a/packages/kit/src/vite/build/build_service_worker.js +++ b/packages/kit/src/vite/build/build_service_worker.js @@ -3,7 +3,6 @@ import * as vite from 'vite'; import { s } from '../../utils/misc.js'; import { deep_merge } from '../utils.js'; import { normalize_path } from '../../utils/url.js'; -import { print_config_conflicts } from '../../core/config/index.js'; import { assets_base, remove_svelte_kit } from './utils.js'; /** diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index da69d636ed52..c5f86d72f672 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -8,7 +8,7 @@ import * as sync from '../core/sync/sync.js'; import { build_server } from './build/build_server.js'; import { build_service_worker } from './build/build_service_worker.js'; import { prerender } from './build/prerender/prerender.js'; -import { load_config, print_config_conflicts, validate_config } from '../core/config/index.js'; +import { load_config } from '../core/config/index.js'; import { dev } from './dev/index.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; From 4397c025f586f028daac95371571a8dbdaf293bf Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 18:11:34 -0400 Subject: [PATCH 57/62] remove unused import --- packages/kit/src/core/config/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 004c17a984a1..f903bb086b05 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -1,7 +1,6 @@ import fs from 'fs'; import path from 'path'; import * as url from 'url'; -import { logger } from '../utils.js'; import options from './options.js'; /** From 35be9e49052a0e9aca2188e486133ed6e4a8b4d3 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 18:32:53 -0400 Subject: [PATCH 58/62] simplify merging --- packages/kit/src/vite/build/build_server.js | 11 ++-- .../src/vite/build/build_service_worker.js | 7 ++- packages/kit/src/vite/index.js | 34 +++++------- packages/kit/src/vite/utils.js | 54 ++++++++----------- packages/kit/src/vite/utils.spec.js | 27 ++++------ 5 files changed, 54 insertions(+), 79 deletions(-) diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index 30d23c8433d7..f335631e3674 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import { mkdirp, posixify } from '../../utils/filesystem.js'; -import { deep_merge } from '../utils.js'; +import { merge_vite_configs } from '../utils.js'; import { load_template } from '../../core/config/index.js'; import { get_runtime_path, resolve_entry } from '../../core/utils.js'; import { create_build, find_deps, get_default_config, remove_svelte_kit } from './utils.js'; @@ -192,12 +192,9 @@ export async function build_server(vite_config, options, client) { } }; - // don't warn on overriding defaults - const [modified_vite_config] = deep_merge(default_config, vite_config); - - /** @type {[any, string[]]} */ - const [merged_config] = deep_merge( - modified_vite_config, + const merged_config = merge_vite_configs( + default_config, + vite_config, get_default_config({ config, input, ssr: true, outDir: `${output_dir}/server` }) ); diff --git a/packages/kit/src/vite/build/build_service_worker.js b/packages/kit/src/vite/build/build_service_worker.js index b6ea9051ac35..9a96dbea040d 100644 --- a/packages/kit/src/vite/build/build_service_worker.js +++ b/packages/kit/src/vite/build/build_service_worker.js @@ -1,7 +1,7 @@ import fs from 'fs'; import * as vite from 'vite'; import { s } from '../../utils/misc.js'; -import { deep_merge } from '../utils.js'; +import { merge_vite_configs } from '../utils.js'; import { normalize_path } from '../../utils/url.js'; import { assets_base, remove_svelte_kit } from './utils.js'; @@ -67,12 +67,11 @@ export async function build_service_worker( .trim() ); - /** @type {[any, string[]]} */ - const [merged_config] = deep_merge(vite_config, { + const merged_config = merge_vite_configs(vite_config, { base: assets_base(config.kit), build: { lib: { - entry: service_worker_entry_file, + entry: /** @type {string} */ (service_worker_entry_file), name: 'app', formats: ['es'] }, diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index c5f86d72f672..7bf26864af30 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -14,7 +14,7 @@ import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; import { find_deps, get_default_config } from './build/utils.js'; import { preview } from './preview/index.js'; -import { deep_merge } from './utils.js'; +import { merge_vite_configs } from './utils.js'; const cwd = process.cwd(); @@ -133,11 +133,23 @@ function kit() { } // dev and preview config can be shared - const vite_config = { + return { + base: '/', + build: { + rollupOptions: { + // Vite dependency crawler needs an explicit JS entry point + // eventhough server otherwise works without it + input: `${get_runtime_path(svelte_config.kit)}/client/start.js` + } + }, preview: { port: 3000, strictPort: true }, + resolve: { + alias: get_aliases(svelte_config.kit) + }, + root: cwd, server: { fs: { allow: [ @@ -162,24 +174,6 @@ function kit() { }, spa: false }; - - /** @type {[any, string[]]} */ - const [merged_config] = deep_merge(vite_config, { - base: '/', - build: { - rollupOptions: { - // Vite dependency crawler needs an explicit JS entry point - // eventhough server otherwise works without it - input: `${get_runtime_path(svelte_config.kit)}/client/start.js` - } - }, - resolve: { - alias: get_aliases(svelte_config.kit) - }, - root: cwd - }); - - return merged_config; }, buildStart() { diff --git a/packages/kit/src/vite/utils.js b/packages/kit/src/vite/utils.js index af8a23e87c9d..5fc731ebb96a 100644 --- a/packages/kit/src/vite/utils.js +++ b/packages/kit/src/vite/utils.js @@ -1,3 +1,19 @@ +/** + * @param {...import('vite').UserConfig} configs + * @returns {import('vite').UserConfig} + */ +export function merge_vite_configs(...configs) { + return deep_merge( + ...configs.map((config) => ({ + ...config, + resolve: { + ...config.resolve, + alias: normalize_alias(config.resolve?.alias || {}) + } + })) + ); +} + /** * Takes zero or more objects and returns a new object that has all the values * deeply merged together. None of the original objects will be mutated at any @@ -5,15 +21,13 @@ * objects at any depth. If there's a conflict the last one wins, except for * arrays which will be combined. * @param {...Object} objects - * @returns {[Record, string[]]} a 2-tuple with the merged object, - * and a list of merge conflicts if there were any, in dotted notation + * @returns {Record} the merged object */ export function deep_merge(...objects) { const result = {}; /** @type {string[]} */ - const conflicts = []; - objects.forEach((o) => merge_into(result, o, conflicts)); - return [result, conflicts]; + objects.forEach((o) => merge_into(result, o)); + return result; } /** @@ -21,7 +35,7 @@ export function deep_merge(...objects) { * @param {import('vite').AliasOptions} o * @returns {import('vite').Alias[]} */ -export function normalize_alias(o) { +function normalize_alias(o) { if (Array.isArray(o)) return o; return Object.entries(o).map(([find, replacement]) => ({ find, replacement })); } @@ -30,11 +44,8 @@ export function normalize_alias(o) { * Merges b into a, recursively, mutating a. * @param {Record} a * @param {Record} b - * @param {string[]} conflicts array to accumulate conflicts in - * @param {string[]} path array of property names representing the current - * location in the tree */ -function merge_into(a, b, conflicts = [], path = []) { +function merge_into(a, b) { /** * Checks for "plain old Javascript object", typically made as an object * literal. Excludes Arrays and built-in types like Buffer. @@ -43,38 +54,17 @@ function merge_into(a, b, conflicts = [], path = []) { const is_plain_object = (x) => typeof x === 'object' && x.constructor === Object; for (const prop in b) { - // normalize alias objects to array - if (prop === 'alias' && path[path.length - 1] === 'resolve') { - if (a[prop]) a[prop] = normalize_alias(a[prop]); - if (b[prop]) b[prop] = normalize_alias(b[prop]); - } - if (is_plain_object(b[prop])) { if (!is_plain_object(a[prop])) { - if (a[prop] !== undefined) { - conflicts.push([...path, prop].join('.')); - } a[prop] = {}; } - merge_into(a[prop], b[prop], conflicts, [...path, prop]); + merge_into(a[prop], b[prop]); } else if (Array.isArray(b[prop])) { if (!Array.isArray(a[prop])) { - if (a[prop] !== undefined) { - conflicts.push([...path, prop].join('.')); - } a[prop] = []; } a[prop].push(...b[prop]); } else { - // Since we're inside a for/in loop which loops over enumerable - // properties only, we want parity here and to check if 'a' has - // enumerable-only property 'prop'. Using 'hasOwnProperty' to - // exclude inherited properties is close enough. It is possible - // that someone uses Object.defineProperty to create a direct, - // non-enumerable property but let's not worry about that. - if (Object.prototype.hasOwnProperty.call(a, prop)) { - conflicts.push([...path, prop].join('.')); - } a[prop] = b[prop]; } } diff --git a/packages/kit/src/vite/utils.spec.js b/packages/kit/src/vite/utils.spec.js index 78249d43e3ca..46146aa83b94 100644 --- a/packages/kit/src/vite/utils.spec.js +++ b/packages/kit/src/vite/utils.spec.js @@ -1,9 +1,9 @@ import { test } from 'uvu'; import * as assert from 'uvu/assert'; -import { deep_merge } from './utils.js'; +import { deep_merge, merge_vite_configs } from './utils.js'; test('basic test no conflicts', async () => { - const [merged, conflicts] = deep_merge( + const merged = deep_merge( { version: 1, animalSounds: { @@ -17,6 +17,7 @@ test('basic test no conflicts', async () => { locale: 'en_US' } ); + assert.equal(merged, { version: 1, locale: 'en_US', @@ -25,11 +26,10 @@ test('basic test no conflicts', async () => { duck: 'quack' } }); - assert.equal(conflicts, []); }); test('three way merge no conflicts', async () => { - const [merged, conflicts] = deep_merge( + const merged = deep_merge( { animalSounds: { cow: 'moo' @@ -59,11 +59,10 @@ test('three way merge no conflicts', async () => { } } }); - assert.equal(conflicts, []); }); test('merge with conflicts', async () => { - const [merged, conflicts] = deep_merge( + const merged = deep_merge( { person: { firstName: 'John', @@ -90,11 +89,10 @@ test('merge with conflicts', async () => { address: '123 Main St, Seattle, WA' } }); - assert.equal(conflicts, ['person.address']); }); test('merge with arrays', async () => { - const [merged] = deep_merge( + const merged = deep_merge( { paths: ['/foo', '/bar'] }, @@ -108,7 +106,7 @@ test('merge with arrays', async () => { }); test('empty', async () => { - const [merged] = deep_merge(); + const merged = deep_merge(); assert.equal(merged, {}); }); @@ -135,7 +133,7 @@ test('mutability safety', () => { const snapshot1 = JSON.stringify(input1); const snapshot2 = JSON.stringify(input2); - const [merged] = deep_merge(input1, input2); + const merged = deep_merge(input1, input2); // Mess with the result merged.person.middleInitial = 'Z'; @@ -148,7 +146,7 @@ test('mutability safety', () => { }); test('merge buffer', () => { - const [merged, conflicts] = deep_merge( + const merged = deep_merge( { x: Buffer.from('foo', 'utf-8') }, @@ -157,11 +155,10 @@ test('merge buffer', () => { } ); assert.equal(Object.keys(merged), ['x', 'y']); - assert.equal(conflicts.length, 0); }); test('merge including toString', () => { - const [merged, conflicts] = deep_merge( + const merged = deep_merge( { toString: () => '', constructor: () => '' @@ -170,12 +167,11 @@ test('merge including toString', () => { y: 12345 } ); - assert.equal(conflicts.length, 0); assert.equal(Object.keys(merged), ['toString', 'constructor', 'y']); }); test('merge resolve.alias', () => { - const [merged, conflicts] = deep_merge( + const merged = merge_vite_configs( { resolve: { alias: [{ find: /foo/, replacement: 'bar' }] @@ -189,7 +185,6 @@ test('merge resolve.alias', () => { } } ); - assert.equal(conflicts.length, 0); assert.equal(merged, { resolve: { alias: [ From da99b0bfaeed3d5a0d842f53f692a2e63e24e2f6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 18:40:31 -0400 Subject: [PATCH 59/62] remove unused import --- packages/kit/src/vite/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 7bf26864af30..d3ce14da62d5 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -14,7 +14,6 @@ import { generate_manifest } from '../core/generate_manifest/index.js'; import { get_aliases, get_runtime_path, logger, resolve_entry } from '../core/utils.js'; import { find_deps, get_default_config } from './build/utils.js'; import { preview } from './preview/index.js'; -import { merge_vite_configs } from './utils.js'; const cwd = process.cwd(); From a63c8bd6e4d14665ce8f7f90ad3f21dee3c2e817 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 23 Jun 2022 15:41:48 -0700 Subject: [PATCH 60/62] remove blank line --- packages/kit/src/vite/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index d3ce14da62d5..1b1f53013ec4 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -330,7 +330,6 @@ function kit() { } /** - * * @param {Record} config * @param {Record} enforced_config * @param {string} path From 5ba670e6b6e59baebc042997deb28c7f0c0eef68 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 18:45:44 -0400 Subject: [PATCH 61/62] i think these files were committed by mistake --- packages/kit/src/packaging/test/watch/src/lib/Test.svelte | 1 - packages/kit/src/packaging/test/watch/src/lib/a.js | 1 - packages/kit/src/packaging/test/watch/src/lib/b.ts | 1 - 3 files changed, 3 deletions(-) delete mode 100644 packages/kit/src/packaging/test/watch/src/lib/Test.svelte delete mode 100644 packages/kit/src/packaging/test/watch/src/lib/a.js delete mode 100644 packages/kit/src/packaging/test/watch/src/lib/b.ts diff --git a/packages/kit/src/packaging/test/watch/src/lib/Test.svelte b/packages/kit/src/packaging/test/watch/src/lib/Test.svelte deleted file mode 100644 index 8f19b8ec1674..000000000000 --- a/packages/kit/src/packaging/test/watch/src/lib/Test.svelte +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/kit/src/packaging/test/watch/src/lib/a.js b/packages/kit/src/packaging/test/watch/src/lib/a.js deleted file mode 100644 index c4a2d30fbc2d..000000000000 --- a/packages/kit/src/packaging/test/watch/src/lib/a.js +++ /dev/null @@ -1 +0,0 @@ -export const a = 'a'; diff --git a/packages/kit/src/packaging/test/watch/src/lib/b.ts b/packages/kit/src/packaging/test/watch/src/lib/b.ts deleted file mode 100644 index 137b8ce6429a..000000000000 --- a/packages/kit/src/packaging/test/watch/src/lib/b.ts +++ /dev/null @@ -1 +0,0 @@ -export const b = 'b'; From 4638cb218cf40fcfa147db1de7a36e649ae8e68c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Jun 2022 18:59:13 -0400 Subject: [PATCH 62/62] set env vars earlier --- packages/kit/src/vite/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 1b1f53013ec4..8c96da350cf0 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -103,6 +103,10 @@ function kit() { }; if (command === 'build') { + process.env.VITE_SVELTEKIT_APP_VERSION = svelte_config.kit.version.name; + process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${svelte_config.kit.appDir}/version.json`; + process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${svelte_config.kit.version.pollInterval}`; + manifest_data = sync.all(svelte_config).manifest_data; /** @type {Record} */ @@ -181,10 +185,6 @@ function kit() { rimraf(paths.output_dir); mkdirp(paths.output_dir); - - process.env.VITE_SVELTEKIT_APP_VERSION = svelte_config.kit.version.name; - process.env.VITE_SVELTEKIT_APP_VERSION_FILE = `${svelte_config.kit.appDir}/version.json`; - process.env.VITE_SVELTEKIT_APP_VERSION_POLL_INTERVAL = `${svelte_config.kit.version.pollInterval}`; }, async writeBundle(_options, bundle) {