From 5c15b4799f10bbf498dad8de2651d503ce97a523 Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Mon, 28 Oct 2024 21:12:21 +0800 Subject: [PATCH 1/6] feat: Allow plugins to change the base for server-islands URLs --- packages/astro/src/container/index.ts | 2 ++ packages/astro/src/core/app/types.ts | 1 + packages/astro/src/core/build/plugins/plugin-manifest.ts | 1 + packages/astro/src/core/render-context.ts | 1 + packages/astro/src/runtime/server/render/server-islands.ts | 5 +++-- packages/astro/src/types/public/config.ts | 4 ++++ packages/astro/src/types/public/internal.ts | 4 ++++ 7 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/astro/src/container/index.ts b/packages/astro/src/container/index.ts index 2564e28750ac..b81256a5582e 100644 --- a/packages/astro/src/container/index.ts +++ b/packages/astro/src/container/index.ts @@ -150,6 +150,7 @@ function createManifest( clientDirectives: manifest?.clientDirectives ?? getDefaultClientDirectives(), renderers: renderers ?? manifest?.renderers ?? [], base: manifest?.base ?? ASTRO_CONFIG_DEFAULTS.base, + serverIslandDynamicBase: manifest?.serverIslandDynamicBase, componentMetadata: manifest?.componentMetadata ?? new Map(), inlinedScripts: manifest?.inlinedScripts ?? new Map(), i18n: manifest?.i18n, @@ -228,6 +229,7 @@ type AstroContainerManifest = Pick< | 'renderers' | 'assetsPrefix' | 'base' + | 'serverIslandDynamicBase' | 'routes' | 'assets' | 'entryModules' diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts index 0fb627f718a1..5ae368d61dc9 100644 --- a/packages/astro/src/core/app/types.ts +++ b/packages/astro/src/core/app/types.ts @@ -48,6 +48,7 @@ export type SSRManifest = { routes: RouteInfo[]; site?: string; base: string; + serverIslandDynamicBase?: string; trailingSlash: 'always' | 'never' | 'ignore'; buildFormat: 'file' | 'directory' | 'preserve'; compressHTML: boolean; diff --git a/packages/astro/src/core/build/plugins/plugin-manifest.ts b/packages/astro/src/core/build/plugins/plugin-manifest.ts index 12fdf65b17bb..c85c6d1a2e2b 100644 --- a/packages/astro/src/core/build/plugins/plugin-manifest.ts +++ b/packages/astro/src/core/build/plugins/plugin-manifest.ts @@ -259,6 +259,7 @@ function buildManifest( routes, site: settings.config.site, base: settings.config.base, + serverIslandDynamicBase: settings.config.serverIslandDynamicBase, trailingSlash: settings.config.trailingSlash, compressHTML: settings.config.compressHTML, assetsPrefix: settings.config.build.assetsPrefix, diff --git a/packages/astro/src/core/render-context.ts b/packages/astro/src/core/render-context.ts index 611b9cbcbe68..7b28ebbab9a2 100644 --- a/packages/astro/src/core/render-context.ts +++ b/packages/astro/src/core/render-context.ts @@ -367,6 +367,7 @@ export class RenderContext { // calling the render() function will populate the object with scripts, styles, etc. const result: SSRResult = { base: manifest.base, + serverIslandDynamicBase: manifest.serverIslandDynamicBase, cancelled: false, clientDirectives, inlinedScripts, diff --git a/packages/astro/src/runtime/server/render/server-islands.ts b/packages/astro/src/runtime/server/render/server-islands.ts index 97bf1d3314e5..f8178fa8e86c 100644 --- a/packages/astro/src/runtime/server/render/server-islands.ts +++ b/packages/astro/src/runtime/server/render/server-islands.ts @@ -80,8 +80,9 @@ export function renderServerIsland( const hostId = crypto.randomUUID(); - const slash = result.base.endsWith('/') ? '' : '/'; - let serverIslandUrl = `${result.base}${slash}_server-islands/${componentId}${result.trailingSlash === 'always' ? '/' : ''}`; + const _base = result.serverIslandDynamicBase ?? result.base; + const slash = _base.endsWith('/') ? '' : '/'; + let serverIslandUrl = `${_base}${slash}_server-islands/${componentId}${result.trailingSlash === 'always' ? '/' : ''}`; // Determine if its safe to use a GET request const potentialSearchParams = createSearchParams( diff --git a/packages/astro/src/types/public/config.ts b/packages/astro/src/types/public/config.ts index 43aea0743a69..45b020bf099b 100644 --- a/packages/astro/src/types/public/config.ts +++ b/packages/astro/src/types/public/config.ts @@ -1975,6 +1975,10 @@ export interface AstroConfig extends AstroConfigType { // This is a more detailed type than zod validation gives us. // TypeScript still confirms zod validation matches this type. integrations: AstroIntegration[]; + + // Private: + // This is not configurable directly by the user. But may be configured by an integration. + serverIslandDynamicBase?: string; } /** * An inline Astro config that takes highest priority when merging with the user config, diff --git a/packages/astro/src/types/public/internal.ts b/packages/astro/src/types/public/internal.ts index a17ee76506a0..065840c61556 100644 --- a/packages/astro/src/types/public/internal.ts +++ b/packages/astro/src/types/public/internal.ts @@ -214,6 +214,10 @@ export interface SSRResult { */ cancelled: boolean; base: string; + // serverIslandDynamicBase allows users to specify that server islands will be served from a separate domain. + // This is an advanced option and won't be used in most cases. This should only be used if the static assets and + // SSR server are served on separate domains. + serverIslandDynamicBase?: string; styles: Set; scripts: Set; links: Set; From 2f7e3842df7a0bce213fda10f76fcad150fcdf5e Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Mon, 28 Oct 2024 13:21:29 +0000 Subject: [PATCH 2/6] Add changeset --- .changeset/famous-beds-tan.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/famous-beds-tan.md diff --git a/.changeset/famous-beds-tan.md b/.changeset/famous-beds-tan.md new file mode 100644 index 000000000000..89f238fb92fb --- /dev/null +++ b/.changeset/famous-beds-tan.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +feat: Allow integrations to change the base for server-islands URLs From d8f9f94233d875622d9d1c88272058d02a1185f6 Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Tue, 29 Oct 2024 09:08:55 +0800 Subject: [PATCH 3/6] doc: Add fallback explanation to SSRResult change --- packages/astro/src/types/public/internal.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/astro/src/types/public/internal.ts b/packages/astro/src/types/public/internal.ts index 065840c61556..c02653a83871 100644 --- a/packages/astro/src/types/public/internal.ts +++ b/packages/astro/src/types/public/internal.ts @@ -217,6 +217,7 @@ export interface SSRResult { // serverIslandDynamicBase allows users to specify that server islands will be served from a separate domain. // This is an advanced option and won't be used in most cases. This should only be used if the static assets and // SSR server are served on separate domains. + // If this is not set, it will use `base` instead. serverIslandDynamicBase?: string; styles: Set; scripts: Set; From 03b145bf2df81d401fec15770f1721fea1fa30dd Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Fri, 22 Nov 2024 17:55:52 +0000 Subject: [PATCH 4/6] test: Ensure that when we build with server islands that the baseURL is added --- packages/astro/test/server-islands.test.js | 103 +++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/packages/astro/test/server-islands.test.js b/packages/astro/test/server-islands.test.js index 913650a95029..470dd0488aff 100644 --- a/packages/astro/test/server-islands.test.js +++ b/packages/astro/test/server-islands.test.js @@ -77,6 +77,61 @@ describe('Server islands', () => { }); }); + describe('SSR (change base URL)', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + before(async () => { + fixture = await loadFixture({ + root: './fixtures/server-islands/ssr', + adapter: testAdapter(), + integrations: [ + { + name: 'change-base-url', + hooks: { + 'astro:config:setup': async ({ updateConfig, command }) => { + if (command === 'build') { + updateConfig({ + serverIslandDynamicBase: 'https://api.example.com', + }); + } + }, + }, + }, + ], + }); + }); + + describe('prod', () => { + before(async () => { + process.env.ASTRO_KEY = 'eKBaVEuI7YjfanEXHuJe/pwZKKt3LkAHeMxvTU7aR0M='; + await fixture.build(); + }); + + after(async () => { + delete process.env.ASTRO_KEY; + }); + + it('server island script has base URL', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/'); + const response = await app.render(request); + const html = await response.text(); + + const $ = cheerio.load(html); + const serverIslandEl = $('h2#island'); + assert.equal(serverIslandEl.length, 0); + + const serverIslandScript = $('script[data-island-id]'); + assert.equal(serverIslandScript.length, 1, 'has the island script'); + + assert.match( + serverIslandScript.text(), + /await fetch\('https:\/\/api.example.com\/_server-islands\//i, + ); + }); + }); + }); + describe('Hybrid mode', () => { /** @type {import('./test-utils').Fixture} */ let fixture; @@ -118,4 +173,52 @@ describe('Server islands', () => { }); }); }); + + describe('Hybrid mode (change base URL)', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + before(async () => { + fixture = await loadFixture({ + root: './fixtures/server-islands/hybrid', + integrations: [ + { + name: 'change-base-url', + hooks: { + 'astro:config:setup': async ({ updateConfig, command }) => { + if (command === 'build') { + updateConfig({ + serverIslandDynamicBase: 'https://api.example.com', + }); + } + }, + }, + }, + ], + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build({ + adapter: testAdapter(), + }); + }); + + it('Omits the island HTML from the static HTML', async () => { + let html = await fixture.readFile('/client/index.html'); + + const $ = cheerio.load(html); + const serverIslandEl = $('h2#island'); + assert.equal(serverIslandEl.length, 0); + + const serverIslandScript = $('script[data-island-id]'); + assert.equal(serverIslandScript.length, 1, 'has the island script'); + + assert.match( + serverIslandScript.text(), + /await fetch\('https:\/\/api.example.com\/_server-islands\//i, + ); + }); + }); + }); }); From 593cc7772e599cd27075c63fbaac798b4f06203c Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Mon, 25 Nov 2024 21:38:58 +0000 Subject: [PATCH 5/6] doc: Add better documentation to the serverIslandDynamicBase config option --- packages/astro/src/types/public/config.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/astro/src/types/public/config.ts b/packages/astro/src/types/public/config.ts index 45b020bf099b..b31ccc874c5c 100644 --- a/packages/astro/src/types/public/config.ts +++ b/packages/astro/src/types/public/config.ts @@ -1978,6 +1978,11 @@ export interface AstroConfig extends AstroConfigType { // Private: // This is not configurable directly by the user. But may be configured by an integration. + // + // Setting this option will change the base path to deploy server islands to. + // This changes the path of any server islands that are emitted in the client HTML. + // If this is unset, this will fallback to the user supplied `base` config option, and if that is unset, + // then a relative URL will be used (ie: `/_server-islands/`). serverIslandDynamicBase?: string; } /** From 1376964e86f633c42df08ee262d2c704ef1614d5 Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Wed, 27 Nov 2024 19:23:59 +0000 Subject: [PATCH 6/6] change patch to minor --- .changeset/famous-beds-tan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/famous-beds-tan.md b/.changeset/famous-beds-tan.md index 89f238fb92fb..7cd64270cdb2 100644 --- a/.changeset/famous-beds-tan.md +++ b/.changeset/famous-beds-tan.md @@ -1,5 +1,5 @@ --- -"astro": patch +"astro": minor --- feat: Allow integrations to change the base for server-islands URLs