Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: generate fallback page before compressing #8972

Merged
merged 3 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rich-llamas-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/adapter-static': patch
---

fix: generate fallback page before compressing
5 changes: 5 additions & 0 deletions .changeset/thirty-ways-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

chore: refactor fallback generation
2 changes: 1 addition & 1 deletion packages/adapter-static/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ See https://kit.svelte.dev/docs/page-options#prerender for more details`
builder.writePrerendered(pages);

if (fallback) {
builder.generateFallback(path.join(pages, fallback));
await builder.generateFallback(path.join(pages, fallback));
}

if (precompress) {
Expand Down
31 changes: 8 additions & 23 deletions packages/kit/src/core/adapt/builder.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { fork } from 'node:child_process';
import { existsSync, statSync, createReadStream, createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream';
import { fileURLToPath } from 'node:url';
import { promisify } from 'node:util';
import zlib from 'node:zlib';
import glob from 'tiny-glob';
import { copy, rimraf, mkdirp } from '../../utils/filesystem.js';
import { generate_manifest } from '../generate_manifest/index.js';
import { get_route_segments } from '../../utils/routing.js';
import { get_env } from '../../exports/vite/utils.js';
import generate_fallback from '../postbuild/fallback.js';
import { write } from '../sync/utils.js';

const pipe = promisify(pipeline);

Expand Down Expand Up @@ -142,31 +142,16 @@ export function create_builder({
}
},

generateFallback(dest) {
// do prerendering in a subprocess so any dangling stuff gets killed upon completion
const script = fileURLToPath(new URL('../postbuild/fallback.js', import.meta.url));

async generateFallback(dest) {
const manifest_path = `${config.kit.outDir}/output/server/manifest-full.js`;

const env = get_env(config.kit.env, 'production');

return new Promise((fulfil, reject) => {
const child = fork(
script,
[dest, manifest_path, JSON.stringify({ ...env.private, ...env.public })],
{
stdio: 'inherit'
}
);

child.on('exit', (code) => {
if (code) {
reject(new Error(`Could not create a fallback page — failed with code ${code}`));
} else {
fulfil(undefined);
}
});
const fallback = await generate_fallback({
manifest_path,
env: { ...env.private, ...env.public }
});

write(dest, fallback);
},

generateManifest: ({ relativePath, routes: subset }) => {
Expand Down
69 changes: 40 additions & 29 deletions packages/kit/src/core/postbuild/fallback.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
import { readFileSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { pathToFileURL } from 'node:url';
import { mkdirp } from '../../utils/filesystem.js';
import { installPolyfills } from '../../exports/node/polyfills.js';
import { load_config } from '../config/index.js';
import { forked } from '../../utils/fork.js';

const [, , dest, manifest_path, env] = process.argv;
export default forked(import.meta.url, generate_fallback);

/** @type {import('types').ValidatedKitConfig} */
const config = (await load_config()).kit;
/**
* @param {{
* manifest_path: string;
* env: Record<string, string>
* }} opts
*/
async function generate_fallback({ manifest_path, env }) {
/** @type {import('types').ValidatedKitConfig} */
const config = (await load_config()).kit;

installPolyfills();
installPolyfills();

const server_root = join(config.outDir, 'output');
const server_root = join(config.outDir, 'output');

/** @type {import('types').ServerInternalModule} */
const { set_building } = await import(pathToFileURL(`${server_root}/server/internal.js`).href);
/** @type {import('types').ServerInternalModule} */
const { set_building } = await import(pathToFileURL(`${server_root}/server/internal.js`).href);

/** @type {import('types').ServerModule} */
const { Server } = await import(pathToFileURL(`${server_root}/server/index.js`).href);
/** @type {import('types').ServerModule} */
const { Server } = await import(pathToFileURL(`${server_root}/server/index.js`).href);

/** @type {import('types').SSRManifest} */
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
/** @type {import('types').SSRManifest} */
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;

set_building(true);
set_building(true);

const server = new Server(manifest);
await server.init({ env: JSON.parse(env) });
const server = new Server(manifest);
await server.init({ env });

const rendered = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
getClientAddress: () => {
throw new Error('Cannot read clientAddress during prerendering');
},
prerendering: {
fallback: true,
dependencies: new Map()
},
read: (file) => readFileSync(join(config.files.assets, file))
});
const response = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
getClientAddress: () => {
throw new Error('Cannot read clientAddress during prerendering');
},
prerendering: {
fallback: true,
dependencies: new Map()
},
read: (file) => readFileSync(join(config.files.assets, file))
});

mkdirp(dirname(dest));
writeFileSync(dest, await rendered.text());
if (response.ok) {
return await response.text();
}

throw new Error(`Could not create a fallback page — failed with status ${response.status}`);
}