Skip to content

Commit

Permalink
[fix] prerender in subprocess
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann committed Jul 22, 2022
1 parent 9aaa9a7 commit e3f1986
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/witty-avocados-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

[breaking] remove Prerendered.assets
3 changes: 2 additions & 1 deletion packages/kit/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
42 changes: 37 additions & 5 deletions packages/kit/src/core/prerender/prerender.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
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';
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<PrerenderErrorHandler>[0]} details
* @param {import('types').ValidatedKitConfig} config
Expand Down Expand Up @@ -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(),
Expand All @@ -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) => {
Expand Down Expand Up @@ -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} */
Expand Down
40 changes: 23 additions & 17 deletions packages/kit/src/vite/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { spawnSync } from 'child_process';
import fs from 'fs';
import path from 'path';
import colors from 'kleur';
Expand All @@ -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';
Expand Down Expand Up @@ -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`,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
},

/**
Expand Down

0 comments on commit e3f1986

Please sign in to comment.