Commit Graph

1 Commits

Author SHA1 Message Date
James Anderson efa18a3f80 fix(pages-router): include _app module assets in served page HTML (#1232)
* fix(pages-router): include _app module assets in served page HTML

When a Pages Router page renders, vinext's prod server collects asset
tags only for the matched page module. _app.tsx — which wraps every
page — is omitted, so any CSS/JS it imports is built and emitted but
never <link>ed from the rendered HTML.

For SCSS users this is the LHF-5 cluster from the Next.js deploy suite:
when global.scss is imported via _app.tsx, Vite compiles it correctly
and emits assets/_app-*.css, but the browser never sees a
<link rel="stylesheet"> for it. The page renders with the user-agent
default colour (rgb(0, 0, 0)) instead of the SCSS-defined colour.

Fix: embed the resolved pages/_app file path at build time and include
it in the moduleIds passed to collectAssetTags, so the SSR manifest's
CSS/JS entries for _app are emitted alongside the page's own.

Includes a regression test (tests/scss.test.ts) plus a fixture page
that imports a .scss file with a variable. The test covers App Router
dev, App Router production build, Pages Router dev, and the Pages
Router production server end-to-end (build → start prod server →
fetch page → assert linked stylesheet has the resolved colour).

Skipped automatically when sass is not installed — vinext relies on
Vite's built-in SCSS preprocessor, which requires the user to install
sass (or sass-embedded) themselves. Matches Vite's model.

* fix: isolate SCSS fixture and silence TS check for optional sass import

The first revision of this PR added an SCSS fixture under
tests/fixtures/app-basic/app/nextjs-compat/scss-test/. That directory
is scanned by every test that boots the shared app-basic fixture, so
when sass is not installed (CI default) every page in app-basic fails
the route-graph scan and 500s. jsx-in-js, app-css, node-modules-css,
and ~dozens of integration tests went red as a result (CI run
https://github.com/cloudflare/vinext/actions/runs/25913568939).

The TypeScript check job also failed because `await import("sass")`
produces TS2307 when sass isn't declared as a workspace dep.

Fixes:

- Drop the shared fixture under app-basic. tests/scss.test.ts now
  materialises its Pages Router SCSS fixture in a per-test tmpdir
  (same pattern as the existing Pages Router scenario), so the shared
  fixture's route-graph scan never sees a .scss import. No other test
  is affected.

- The App Router test scenarios from the first revision are removed.
  They required additional node_modules wiring for @vitejs/plugin-rsc
  to resolve from a tmpdir and weren't needed to validate the fix —
  the actual change is in the Pages Router asset-collection path, and
  the Pages Router tests exercise it end-to-end (dev + production
  build + linked stylesheet assertion).

- Replace @ts-expect-error with @ts-ignore on the dynamic sass import.
  sass may or may not be installed depending on the environment; when
  it is, there's no type error to expect and @ts-expect-error itself
  errors as unused. @ts-ignore is the right tool for an optional peer.

The pages-server-entry.ts fix from the first revision is unchanged —
this commit only re-shapes the test surface so it doesn't poison the
shared fixture.
2026-05-15 12:15:54 +01:00