Skip to content

Fix server island build error#15888

Merged
matthewp merged 9 commits intomainfrom
server-island-name
Mar 16, 2026
Merged

Fix server island build error#15888
matthewp merged 9 commits intomainfrom
server-island-name

Conversation

@matthewp
Copy link
Contributor

@matthewp matthewp commented Mar 12, 2026

Changes

Testing

  • Add a regression unit test that simulates quote-style conversion and asserts the output contains materialized serverIslandMap/serverIslandNameMap maps.

Docs

  • No docs update needed; this is a bug fix for incorrect runtime behavior.

Rollup can emit server-island placeholders with either single or double quotes, which caused map injection to be skipped in some adapter builds. Match placeholders quote-agnostically and add a regression test that verifies the maps are materialized in output.
@github-actions github-actions bot added the pkg: astro Related to the core `astro` package (scope) label Mar 12, 2026
@changeset-bot
Copy link

changeset-bot bot commented Mar 12, 2026

🦋 Changeset detected

Latest commit: ce7e29a

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@matthewp matthewp changed the title fix(astro): make server-island placeholder replacement quote-agnostic Fix server island build error Mar 12, 2026
@codspeed-hq
Copy link

codspeed-hq bot commented Mar 12, 2026

Merging this PR will not alter performance

✅ 18 untouched benchmarks


Comparing server-island-name (ce7e29a) with main (759f946)

Open in CodSpeed

@matthewp matthewp added the pr preview Apply this label to a PR to generate a preview release label Mar 12, 2026
@matthewp matthewp marked this pull request as ready for review March 12, 2026 18:35
@github-actions github-actions bot removed the pr preview Apply this label to a PR to generate a preview release label Mar 12, 2026
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 12, 2026

astro

npm i https://pkg.pr.new/astro@15888

create-astro

npm i https://pkg.pr.new/create-astro@15888

@astrojs/cloudflare

npm i https://pkg.pr.new/@astrojs/cloudflare@15888

@astrojs/preact

npm i https://pkg.pr.new/@astrojs/preact@15888

@astrojs/check

npm i https://pkg.pr.new/@astrojs/check@15888

@astrojs/language-server

npm i https://pkg.pr.new/@astrojs/language-server@15888

astro-vscode

npm i https://pkg.pr.new/astro-vscode@15888

commit: 2cb31aa

const RESOLVED_SERVER_ISLAND_MANIFEST = '\0' + SERVER_ISLAND_MANIFEST;

export const serverIslandPlaceholderMap = "'$$server-islands-map$$'";
const serverIslandPlaceholderMap = "'$$server-islands-map$$'";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're looking for a solution that is vite 8 friendly, use template literals.

Turns out that oxc/rolldown do a bunch of normalisation with strings, and sometimes it transforms them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, that doesn't matter here, this code isn't loaded by Vite.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It actually does... 😅

I had to apply this change 1cae171

It's just a FYI, no need to change it here. I wanted to let you know

@CaiJimmy
Copy link

CaiJimmy commented Mar 12, 2026

Thanks for the quick fix!

I have encountered now with a different error in preview environment (using the same reproducible example, but with astro package given by pkg-pr-new):

GET / 200 OK (5ms)
GET /.well-known/appspecific/com.chrome.devtools.json 404 Not Found (3ms)
19:43:32 [ERROR] Error: No such module "dist/server/chunks/Island_!~{00b}~.mjs".
    at file:///Users/jimmy/Documents/repro-cf-v6/dist/server/chunks/_virtual_astro_server-island-manifest_zfG9aQW0.mjs:4:19
    at page (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:9222:35)
    at async callComponentAsTemplateResultOrResponse (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:7116:25)
    at async renderToReadableStream (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:7064:26)
    at async renderPage (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:8320:14)
    at async lastNext (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:11522:25)
    at async callMiddleware (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:8412:10)
    at async RenderContext.render (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:11556:73)
    at async App.render (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:12451:20)
    at async Object.handle [as fetch] (file:///Users/jimmy/Documents/repro-cf-v6/dist/server/entry.mjs:12961:20)
GET /_server-islands/Island 500 Internal Server Error (4ms)
image

It's trying to import a non-existent file from chunks folder. The dev server does not work neither. Not sure if this is related. Should I create a separate issue?

@matthewp
Copy link
Contributor Author

@CaiJimmy no, will keep this one.

@matthewp matthewp marked this pull request as draft March 12, 2026 18:51
@CaiJimmy
Copy link

Thanks!

I just tested with the current stable version of Astro 6 and can confirm that it does not generate the dist/server/chunks/Island_!~{00b}~.mjs file neither.

@matthewp matthewp added the pr preview Apply this label to a PR to generate a preview release label Mar 12, 2026
@github-actions github-actions bot removed the pr preview Apply this label to a PR to generate a preview release label Mar 12, 2026
@matthewp
Copy link
Contributor Author

@CaiJimmy can you try with:

npm i https://pkg.pr.new/astro@fbf9d83

@CaiJimmy
Copy link

@matthewp I can confirm that now preview environment working correctly with server:defer, generating the correct chunk file.

But dev server still gives error with prerenderEnvironment: 'node'. I can see in the console that it's a 400 error, but no error log is given currently so I'm afraid that I cannot provide any more useful information to you:

➜  repro-cf-v6 git:(main) ✗ pnpm dev

> repro-cf-v6@0.0.1 dev /Users/jimmy/Documents/repro-cf-v6
> astro dev

20:45:46 [@astrojs/cloudflare] Enabling image processing with Cloudflare Images for production with the "IMAGES" Images binding.
20:45:46 [@astrojs/cloudflare] Enabling sessions with Cloudflare KV with the "SESSION" KV binding.
[vite] connected.
20:45:47 [types] Generated 0ms
20:45:47 [WARN] [content] Content config not loaded
 astro  v6.0.4 ready in 1155 ms
┃ Local    http://localhost:4321/
┃ Network  use --host to expose
20:45:47 watching for file changes...
20:45:48 [200] / 17ms
20:45:48 [200] / 20ms
20:45:48 [vite] 20:45:48 [404] /@id/astro/runtime/client/dev-toolbar/astro_runtime_client_dev-toolbar_entrypoint__js.js.map 9ms
20:45:48 [vite] 20:45:48 [400] /_server-islands/Island 12ms

Is there any way to expose more error stack information here?

@CaiJimmy
Copy link

With prerenderEnvironment: 'workerd', server island in dev server seems to be working correctly.

@matthewp
Copy link
Contributor Author

@CaiJimmy I think I know the dev issue here. It's unrelated to this change so I'll look into that as a separate PR.

@matthewp matthewp marked this pull request as ready for review March 12, 2026 20:02
@matthewp
Copy link
Contributor Author

@CaiJimmy #15891

@CaiJimmy
Copy link

CaiJimmy commented Mar 12, 2026

Thank you!

I'm currently testing this new version on my website, and found that there is some issue with importing third party libraries (using the top level import, not require)

The example server island would be something like this:

---
import { encodeBase64 } from "@oslojs/encoding";
 
const data: Uint8Array = new TextEncoder().encode("hello world");
const encoded = encodeBase64(data);
---

<p>Encoded: {encoded}</p>

The resulting file after running build keeps import { encodeBase64 } from "@oslojs/encoding";, and results error in preview (and I guess also in the real cloudflare worker environment):

Inside ./transition_BPFN3ezl.mjs, there is another direct import from the library:

import { decodeBase64, encodeBase64, decodeHex, encodeHexUpperCase } from '@oslojs/encoding';

Error when running preview:

➜  repro-cf-v6 git:(main) pnpm preview

> repro-cf-v6@0.0.1 preview /Users/jimmy/Documents/repro-cf-v6
> astro preview

21:27:44 [@astrojs/cloudflare] Enabling image processing with Cloudflare Images for production with the "IMAGES" Images binding.
21:27:44 [@astrojs/cloudflare] Enabling sessions with Cloudflare KV with the "SESSION" KV binding.
21:27:44 [@astrojs/cloudflare]
 astro  v13.1.1 ready in 29 ms

┃ Local    http://localhost:4321/

GET / 200 OK (14ms)
21:27:46 [ERROR] Error: No such module "dist/server/chunks/@oslojs/encoding".
  imported from "dist/server/chunks/Island_CZSxsmqZ.mjs"
GET /_server-islands/Island 500 Internal Server Error (17ms)
21:27:46 [ERROR] Error: No such module "dist/server/chunks/@oslojs/encoding".
  imported from "dist/server/chunks/Island_CZSxsmqZ.mjs"
GET /_server-islands/Island 500 Internal Server Error (2ms)

I believe (?) this is not related with https://docs.astro.build/en/guides/integrations-guide/cloudflare/#some-dependencies-might-need-to-be-pre-compiled, because it's using the ES6 export and import syntax.

I have updated the repo with a minimal reproducible example: https://github.com/CaiJimmy/astro-v6-prerender

Should I create a separate issue for this? Seems like a bundle problem.

@matthewp
Copy link
Contributor Author

@CaiJimmy No, I think that might be related to this fix. I'll try and get another test for this scenario and it fixed here.

@github-actions github-actions bot added the pkg: integration Related to any renderer integration (scope) label Mar 13, 2026
@matthewp matthewp added the pr preview Apply this label to a PR to generate a preview release label Mar 13, 2026
@github-actions github-actions bot removed the pr preview Apply this label to a PR to generate a preview release label Mar 13, 2026
@matthewp
Copy link
Contributor Author

@CaiJimmy here's new ones for you to try:

npm i https://pkg.pr.new/astro@a68cdfa
npm i https://pkg.pr.new/@astrojs/cloudflare@a68cdfa

@CaiJimmy
Copy link

Thanks!

With prerenderEnvironment set to workerd, third party libraries are correctly bundled:

/// island_CllqxkrA.mjs
globalThis.process ??= {};
globalThis.process.env ??= {};
import { A as AstroError, ao as InvalidComponentArgs, ap as encodeBase64, l as maybeRenderHead, D as renderTemplate } from "./transition_BffVS1kO.mjs";

However, when it's set to node, it will no longer bundle:

/// island_C0XpBDl0.mjs
globalThis.process ??= {}; globalThis.process.env ??= {};
import { A as AstroError, ao as InvalidComponentArgs, l as maybeRenderHead, D as renderTemplate } from './transition_BPFN3ezl.mjs';
import { encodeBase64 } from '@oslojs/encoding';

The test was done using this example: https://github.com/CaiJimmy/astro-v6-prerender

@matthewp
Copy link
Contributor Author

@CaiJimmy What is incorrect about the second example there? @oslo/encoding is not bundled because dependencies are not bundled by default in Node.js. Does this cause a problem?

@CaiJimmy
Copy link

CaiJimmy commented Mar 13, 2026

@CaiJimmy What is incorrect about the second example there? @oslo/encoding is not bundled because dependencies are not bundled by default in Node.js. Does this cause a problem?

Yes, because this dependency is used by the Server Island script, which will be executed in the Worker environment.

It wouldn't be a problem if the pre-render page itself used it because it would be executed in a normal Node environment.

@matthewp
Copy link
Contributor Author

Right ok, that's interesting. You are hitting the hardest part of this refactor 😅. I've been trying to avoid flipping the order that the environments run, but I might need to do that. Let me try it out.

@matthewp matthewp added the pr preview Apply this label to a PR to generate a preview release label Mar 13, 2026
@github-actions github-actions bot removed the pr preview Apply this label to a PR to generate a preview release label Mar 13, 2026
@matthewp
Copy link
Contributor Author

@CaiJimmy can you try this one?

npm i https://pkg.pr.new/@astrojs/cloudflare@2cb31aa
npm i https://pkg.pr.new/astro@2cb31aa

@CaiJimmy
Copy link

CaiJimmy commented Mar 13, 2026

Thanks!

I have tested it, and it is now compiling and bundling the dependencies correctly.

I have also tested this version on my website and found that Server Island requests are returning empty responses in preview server. I need some time to create a minimal reproducible example, but I think it's probably related to the combination of Server Island and the front-end framework hydration (I'm using Solid.js), because plain text inside Server Island is returned in the response correctly.

Thanks again for the fix!

Edit: here is the minimal reproducible example: https://github.com/CaiJimmy/astro-v6-prerender/blob/main/src/pages/island.astro

Solid.js component (I haven't tested yet other frameworks) inside a Astro Server Island component is not rendered:

---
import A from "./A";
---

<A content={'test'} />
export default function A({ content }: { content?: string }) {
    return (
        <div>
            <p>Content: {content}</p>
        </div>
    );
}

Empty response is returned by the server (it's a 200 response, no error in console):

image

Edit2: I have tested with React, and it has the same issue.
Edit3: This issue is present in both node and workerd prerender environment

nikolailehbrink added a commit to nikolailehbrink/portfolio that referenced this pull request Mar 15, 2026
Server islands used only on prerendered pages produce broken chunk
filenames. Patch swaps build order (prerender first, then SSR) and
uses quote-agnostic placeholder matching.

Tracks: withastro/astro#15888

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@soklovsk
Copy link

Fixes 15903.

@matthewp
Copy link
Contributor Author

@CaiJimmy I think I'm going to release this as I'm confident it fixes most of the server island issues people are facing. Once that's out if you could file a new issue about nested client island inside I'll get that resolved separately.

@matthewp matthewp merged commit 925252e into main Mar 16, 2026
26 checks passed
@matthewp matthewp deleted the server-island-name branch March 16, 2026 12:55
@astrobot-houston astrobot-houston mentioned this pull request Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: astro Related to the core `astro` package (scope) pkg: integration Related to any renderer integration (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v6 / Cloudflare] serverIslandMap?.get is not a function in pre-rendered page

4 participants