Skip to content

Fix(Integration): Load browser manifest via fetch to avoid import attributes - #443

Merged
1aron merged 1 commit into
master-co:rcfrom
0Miles:fix/browser-manifest-facade-import-attributes
Jul 24, 2026
Merged

Fix(Integration): Load browser manifest via fetch to avoid import attributes#443
1aron merged 1 commit into
master-co:rcfrom
0Miles:fix/browser-manifest-facade-import-attributes

Conversation

@0Miles

@0Miles 0Miles commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Problem

Apps using Master CSS in runtime mode render a blank page with no obvious console error on Safari < 17.2 — which includes every iOS 15 and iOS 16 device (iOS 16 tops out at 16.7).

The browser manifest facades generate a loader like:

const loadMasterCSSManifestModule = new Function('specifier', "return import(specifier, { with: { type: 'json' } })");

JSON import attributes (import(url, { with: { type: 'json' } })) are only supported in Safari 17.2+, Chrome 123+, Firefox 130+. On older engines, evaluating that dynamic import — even inside new Function — throws:

SyntaxError: import call expects exactly one argument.

Because the manifest facade runs at the top level of the app entry module, this aborts entry evaluation, so the framework never mounts and the page stays blank. There's no clear console error, which makes it very hard to diagnose.

It's also invisible to build-time checks: the syntax lives inside a new Function string, so esbuild/Rollup/Vite target scans never parse or flag it. (I spent a while scanning bundles with --target=safari16 and they all reported "clean" for exactly this reason.)

Fix

Load the manifest with fetch(...).then(r => r.json()) in the two browser facades:

  • toBrowserManifestFacadeModule
  • the browser branch of toUniversalManifestFacadeModule (renamed loadMasterCSSManifestFromImportloadMasterCSSManifestFromFetch)

fetch is universally supported and needs no new Function bundler-hiding indirection. The Node facades (toNodeManifestFacadeModule and the loadMasterCSSManifestFromFile branch) keep the JSON import attribute, since Node supports it and those paths only run when typeof window === 'undefined'.

Verification

  • Repro + fix confirmed on a real iOS 15.5 Safari simulator (WebKit): before, the entry chunk fails to evaluate and the app is blank; after, it bootstraps normally.
  • packages/integration tests updated + a browser-facade regression test added; full suite passes (12/12), type-check and lint clean.

Notes

  • The manifest preload tag is still emitted as rel="modulepreload" as="json" (hardcoded across the vite/webpack/nuxt/astro integrations). It's harmless with a fetch load but slightly inconsistent; happy to follow up separately to switch it to rel="preload" as="fetch" if you'd prefer.

…ributes

The browser manifest facades built a loader with
`new Function('specifier', "return import(specifier, { with: { type: 'json' } })")`.
JSON import attributes (`with { type: 'json' }`) are only supported in Safari
17.2+, Chrome 123+ and Firefox 130+. On older engines, notably every iOS 15
and iOS 16 (Safari < 17.2), evaluating that dynamic import, even inside
`new Function`, throws `SyntaxError: import call expects exactly one argument`
while the entry module is evaluated. Because the manifest facade runs at the
top level of the app entry, the whole app fails to bootstrap and renders a
blank page with no obvious console error.

The syntax is invisible to build-time tooling because it lives inside a
`new Function` string, so bundler and esbuild target checks never flag it.

Load the manifest with `fetch().then(r => r.json())` in the browser facades
(`toBrowserManifestFacadeModule` and the browser branch of
`toUniversalManifestFacadeModule`). Fetch is universally supported and needs no
bundler-hiding indirection. The Node facades keep the JSON import attribute,
since Node supports it. Verified on an iOS 15.5 Safari simulator: blank before,
mounts after.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

@0Miles is attempting to deploy a commit to the Aoyue Team on Vercel.

A member of the Team first needs to authorize it.

@0Miles
0Miles requested a review from 1aron July 24, 2026 05:49
@0Miles 0Miles self-assigned this Jul 24, 2026
@1aron
1aron requested a review from Copilot July 24, 2026 08:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the @master/css-integration manifest facade generators to avoid JSON import attributes in browser runtime facades, preventing Safari < 17.2 (iOS 15/16) from failing module evaluation and rendering a blank page at app bootstrap.

Changes:

  • Switch the browser manifest facade generator to load the manifest via fetch(...).json() instead of a JSON import attribute hidden behind new Function.
  • Update the universal facade generator’s browser branch to use the same fetch-based loader (renaming the helper accordingly).
  • Extend integration tests to assert the browser facade avoids import attributes (and new Function) and that the universal facade’s browser branch uses fetch.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/integration/src/manifest-facade.ts Replaces browser-side JSON import-attribute loading with a fetch(...).json() loader in browser and universal facades.
packages/integration/tests/module.test.ts Adds assertions to prevent regressions back to import attributes / new Function for browser manifest loading.
Comments suppressed due to low confidence (1)

packages/integration/src/manifest-facade.ts:103

  • loadMasterCSSManifestFromFetch returns response.json() without validating response.ok. If the manifest URL 404s (or returns an HTML error page), this will throw a low-signal JSON parse error instead of a clear fetch failure. Add an OK check and throw an explicit error including status + URL.
    `async function loadMasterCSSManifestFromFetch(url) {`,
    `    const specifier = typeof url === 'string' ? url : url.href;`,
    `    const response = await fetch(specifier);`,
    `    return response.json();`,
    `}`,

Comment on lines +54 to +55
`const masterCSSManifestResponse = await fetch(typeof masterCSSManifestURL === 'string' ? masterCSSManifestURL : masterCSSManifestURL.href);`,
`export default await masterCSSManifestResponse.json();`,
@1aron
1aron merged commit 22d9542 into master-co:rc Jul 24, 2026
6 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants