From ababb3cced0ef1b8b5914539aa61869372973516 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 16 Aug 2022 17:15:11 +0200 Subject: [PATCH 1/3] [fix] Lazy load Svelte components to reenable no-ssr use cases Fixes #5909 --- .changeset/tender-bottles-cheer.md | 5 ++++ .../kit/src/runtime/server/page/render.js | 2 +- packages/kit/src/vite/build/build_server.js | 6 +++- packages/kit/src/vite/dev/index.js | 30 +++++++++++-------- .../no-ssr/browser-only-global/+page.svelte | 5 ++++ .../kit/test/apps/basics/test/client.test.js | 6 ++++ packages/kit/types/internal.d.ts | 7 +---- 7 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 .changeset/tender-bottles-cheer.md create mode 100644 packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte diff --git a/.changeset/tender-bottles-cheer.md b/.changeset/tender-bottles-cheer.md new file mode 100644 index 000000000000..fd86682f256a --- /dev/null +++ b/.changeset/tender-bottles-cheer.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +Lazy load Svelte components to reenable no-ssr use cases diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js index b3b237fce971..bef9b109a817 100644 --- a/packages/kit/src/runtime/server/page/render.js +++ b/packages/kit/src/runtime/server/page/render.js @@ -112,7 +112,7 @@ export async function render_response({ url: state.prerendering ? new PrerenderingURL(event.url) : event.url, data: branch.reduce((acc, { data }) => (Object.assign(acc, data), acc), {}) }, - components: branch.map(({ node }) => node.component) + components: await Promise.all(branch.map(({ node }) => node.component())) }; // TODO remove this for 1.0 diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js index 7e3df1a9dc6f..e7c358fdaf0d 100644 --- a/packages/kit/src/vite/build/build_server.js +++ b/packages/kit/src/vite/build/build_server.js @@ -239,6 +239,8 @@ export async function build_server(options, client) { /** @type {string[]} */ const imports = []; + // String representation of + /** @type {import('types').SSRNode} */ /** @type {string[]} */ const exports = [`export const index = ${i};`]; @@ -255,7 +257,9 @@ export async function build_server(options, client) { stylesheets.push(...entry.stylesheets); exports.push( - `export { default as component } from '../${vite_manifest[node.component].file}';`, + `export const component = async () => (await import('../${ + vite_manifest[node.component].file + }')).default;`, `export const file = '${entry.file}';` // TODO what is this? ); } diff --git a/packages/kit/src/vite/dev/index.js b/packages/kit/src/vite/dev/index.js index 5b196823630e..438c94fb0e7c 100644 --- a/packages/kit/src/vite/dev/index.js +++ b/packages/kit/src/vite/dev/index.js @@ -82,19 +82,23 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) { result.stylesheets = []; if (node.component) { - const { module, module_node, url } = await resolve(node.component); - - module_nodes.push(module_node); - - result.component = module.default; - result.file = url.endsWith('.svelte') ? url : url + '?import'; // TODO what is this for? - - prevent_illegal_vite_imports( - module_node, - illegal_imports, - extensions, - svelte_config.kit.outDir - ); + result.component = async () => { + const { module_node, module, url } = await resolve( + /** @type {string} */ (node.component) + ); + + module_nodes.push(module_node); + result.file = url.endsWith('.svelte') ? url : url + '?import'; // TODO what is this for? + + prevent_illegal_vite_imports( + module_node, + illegal_imports, + extensions, + svelte_config.kit.outDir + ); + + return module.default; + }; } if (node.shared) { diff --git a/packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte b/packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte new file mode 100644 index 000000000000..de016a962d9f --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte @@ -0,0 +1,5 @@ + + +

Works

diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index 4326213bc254..6bc1d7099d17 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -614,3 +614,9 @@ test.describe('Page Store', () => { ); }); }); + +test('Can use browser-only global on client-only page', async ({ page, read_errors }) => { + await page.goto('/no-ssr/browser-only-global'); + await expect(page.locator('p')).toHaveText('Works'); + expect(read_errors('/no-ssr/browser-only-global')).toBe(undefined); +}); diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts index 4a5e001e1cfe..5897892a92bb 100644 --- a/packages/kit/types/internal.d.ts +++ b/packages/kit/types/internal.d.ts @@ -195,7 +195,7 @@ export interface SSREndpoint { } export interface SSRNode { - component: SSRComponent; + component: SSRComponentLoader; /** index into the `components` array in client-manifest.js */ index: number; /** client-side module URL for this component */ @@ -280,11 +280,6 @@ export interface SSRErrorPage { id: '__error'; } -export interface SSRPagePart { - id: string; - load: SSRComponentLoader; -} - export type SSRRoute = SSREndpoint | SSRPage; export interface SSRState { From 2e34188216e76076d095d5b61050bf871aa4bfaa Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 16 Aug 2022 16:02:50 -0400 Subject: [PATCH 2/3] fix order of operations --- .../kit/src/runtime/server/page/render.js | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js index bef9b109a817..f992daa8a006 100644 --- a/packages/kit/src/runtime/server/page/render.js +++ b/packages/kit/src/runtime/server/page/render.js @@ -79,20 +79,6 @@ export async function render_response({ } if (resolve_opts.ssr) { - for (const { node } of branch) { - if (node.imports) { - node.imports.forEach((url) => modulepreloads.add(url)); - } - - if (node.stylesheets) { - node.stylesheets.forEach((url) => stylesheets.add(url)); - } - - if (node.inline_styles) { - Object.entries(await node.inline_styles()).forEach(([k, v]) => inline_styles.set(k, v)); - } - } - const session = writable($session); /** @type {Record} */ @@ -143,6 +129,20 @@ export async function render_response({ } rendered = options.root.render(props); + + for (const { node } of branch) { + if (node.imports) { + node.imports.forEach((url) => modulepreloads.add(url)); + } + + if (node.stylesheets) { + node.stylesheets.forEach((url) => stylesheets.add(url)); + } + + if (node.inline_styles) { + Object.entries(await node.inline_styles()).forEach(([k, v]) => inline_styles.set(k, v)); + } + } } else { rendered = { head: '', html: '', css: { code: '', map: null } }; } From ab1e88010cb3c0fae016121782273ecc12010a8b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 16 Aug 2022 16:10:33 -0400 Subject: [PATCH 3/3] lint --- .../basics/src/routes/no-ssr/browser-only-global/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte b/packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte index de016a962d9f..2e48a4f8ebd7 100644 --- a/packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/no-ssr/browser-only-global/+page.svelte @@ -1,5 +1,5 @@

Works