diff --git a/.changeset/witty-avocados-admire.md b/.changeset/witty-avocados-admire.md new file mode 100644 index 000000000000..a5368e39f720 --- /dev/null +++ b/.changeset/witty-avocados-admire.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +[breaking] remove Prerendered.assets diff --git a/packages/kit/rollup.config.js b/packages/kit/rollup.config.js index 7fa7819d249d..1abcaa774219 100644 --- a/packages/kit/rollup.config.js +++ b/packages/kit/rollup.config.js @@ -61,9 +61,10 @@ export default [ { input: { cli: 'src/cli.js', + hooks: 'src/hooks.js', node: 'src/node/index.js', 'node/polyfills': 'src/node/polyfills.js', - hooks: 'src/hooks.js', + prerender: 'src/core/prerender/prerender.js', vite: 'src/vite/index.js' }, output: { diff --git a/packages/kit/src/core/prerender/prerender.js b/packages/kit/src/core/prerender/prerender.js index 6d6b58187f14..79460040ea6c 100644 --- a/packages/kit/src/core/prerender/prerender.js +++ b/packages/kit/src/core/prerender/prerender.js @@ -1,5 +1,6 @@ import { readFileSync, writeFileSync } from 'fs'; import { dirname, join } from 'path'; +import sade from 'sade'; import { pathToFileURL, URL } from 'url'; import { mkdirp, posixify, walk } from '../../utils/filesystem.js'; import { installPolyfills } from '../../node/polyfills.js'; @@ -7,12 +8,27 @@ import { is_root_relative, resolve } from '../../utils/url.js'; import { queue } from './queue.js'; import { crawl } from './crawl.js'; import { escape_html_attr } from '../../utils/escape.js'; +import { logger } from '../utils.js'; +import { load_config } from '../config/index.js'; /** * @typedef {import('types').PrerenderErrorHandler} PrerenderErrorHandler * @typedef {import('types').Logger} Logger */ +const prog = sade('prerender'); +prog + .command('run', '', { default: true }) + .describe('Runs prerendering. Only for internal use') + .option('--client_out_dir', "Vite's output directory", '') + .option('--results_path', 'Where to put the results', '') + .option('--manifest_path', "SvelteKit's manifest file", '') + .option('--verbose', 'Whether logging should be verbose', false) + .action(async (opts) => { + prerender(opts); + }); +prog.parse(process.argv, { unknown: (arg) => `Unknown option: ${arg}` }); + /** * @param {Parameters[0]} details * @param {import('types').ValidatedKitConfig} config @@ -49,15 +65,24 @@ function normalise_error_handler(log, config) { const OK = 2; const REDIRECT = 3; +/** + * @param {string} path + * @param {import('types').Prerendered} prerendered + */ +const output_and_exit = (path, prerendered) => { + writeFileSync(path, JSON.stringify(prerendered)); + process.exit(0); +}; + /** * @param {{ - * config: import('types').ValidatedKitConfig; * client_out_dir: string; + * results_path: string; * manifest_path: string; - * log: Logger; + * verbose: boolean; * }} opts */ -export async function prerender({ config, client_out_dir, manifest_path, log }) { +export async function prerender({ client_out_dir, results_path, manifest_path, verbose }) { /** @type {import('types').Prerendered} */ const prerendered = { pages: new Map(), @@ -66,10 +91,17 @@ export async function prerender({ config, client_out_dir, manifest_path, log }) paths: [] }; + /** @type {import('types').ValidatedKitConfig} */ + const config = (await load_config()).kit; + if (!config.prerender.enabled) { - return prerendered; + output_and_exit(results_path, prerendered); + return; } + /** @type {import('types').Logger} */ + const log = logger({ verbose }); + installPolyfills(); const { fetch } = globalThis; globalThis.fetch = async (info, init) => { @@ -349,7 +381,7 @@ export async function prerender({ config, client_out_dir, manifest_path, log }) mkdirp(dirname(file)); writeFileSync(file, await rendered.text()); - return prerendered; + output_and_exit(results_path, prerendered); } /** @return {string} */ diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js index 950cae8e25b5..1be6d3528aaf 100644 --- a/packages/kit/src/vite/index.js +++ b/packages/kit/src/vite/index.js @@ -1,3 +1,4 @@ +import { spawnSync } from 'child_process'; import fs from 'fs'; import path from 'path'; import colors from 'kleur'; @@ -7,7 +8,6 @@ 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 '../core/prerender/prerender.js'; import { load_config } from '../core/config/index.js'; import { dev } from './dev/index.js'; import { generate_manifest } from '../core/generate_manifest/index.js'; @@ -273,9 +273,8 @@ function kit() { * then use this hook to kick off builds for the server and service worker. */ async writeBundle(_options, bundle) { - log = logger({ - verbose: vite_config.logLevel === 'info' - }); + const verbose = vite_config.logLevel === 'info'; + log = logger({ verbose }); fs.writeFileSync( `${paths.client_out_dir}/${svelte_config.kit.appDir}/version.json`, @@ -320,12 +319,26 @@ function kit() { process.env.SVELTEKIT_SERVER_BUILD_COMPLETED = 'true'; log.info('Prerendering'); - prerendered = await prerender({ - config: svelte_config.kit, - client_out_dir: vite_config.build.outDir, - manifest_path, - log - }); + const results_path = `${svelte_config.kit.outDir}/generated/prerendered.json`; + + // do prerendering in a subprocess so any dangling stuff gets killed upon completion + spawnSync( + 'node', + [ + './node_modules/@sveltejs/kit/dist/prerender.js', + '--client_out_dir', + vite_config.build.outDir, + '--results_path', + results_path, + '--manifest_path', + manifest_path, + '--verbose', + '' + verbose + ], + { stdio: 'inherit' } + ); + + prerendered = JSON.parse(fs.readFileSync(results_path, 'utf8')); if (options.service_worker_entry_file) { if (svelte_config.kit.paths.assets) { @@ -364,13 +377,6 @@ function kit() { `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` ); } - - if (svelte_config.kit.prerender.enabled) { - // this is necessary to close any open db connections, etc. - // TODO: prerender in a subprocess so we can exit in isolation and then remove this - // https://github.com/sveltejs/kit/issues/5306 - process.exit(0); - } }, /**