Commit Graph

3 Commits

Author SHA1 Message Date
James Anderson 0b7721dba6 perf(build): minify server build environments by default (#1777)
* fix(build): minify server build environments by default

Vite only minifies the client environment; non-client (rsc/ssr and the
Cloudflare worker) environments default build.minify to false, so the
deployed worker and SSR renderer ship unminified. Add a build-only
configEnvironment default that sets minify: true for server environments,
yielding to any explicit user/plugin minify setting (including false).

* fix(build): patch route classification before minify; build fixtures unminified for output introspection

Minifying server environments by default exposed two problems:

1. Real bug: build-time route classification ran in `generateBundle`, but
   rolldown's minifier renames the top-level `__VINEXT_CLASS` function and
   mangles its `routeIdx` parameter before that hook runs, so the stub regex
   never matched and the patch silently no-op'd — every route fell back to the
   Layer 3 runtime probe in production. Move the injection to a `renderChunk`
   hook with `order: "pre"` so it runs before minification; the patched body is
   then minified along with the rest of the chunk (the runtime calls it by
   reference, not by name).

2. Test artifacts: three build tests introspect emitted server chunks for
   readable identifiers (registerConfiguredCacheAdapters, __VINEXT_CLASS) or
   depend on unminified chunking (MDX frontmatter leak check). These are
   test-only concerns — the runtime behavior is unchanged. Build their fixtures
   with `build.minify: false` (a user-overridable default) so the assertions
   stay deterministic.

* fix(build): drop now-unused RouteClassificationChunk export (knip)

The renderChunk refactor removed the external consumer of this type; keep it
as a local type so knip passes.

* test(build): guard minified classification path; fix stale generateBundle refs

Re-add real regression coverage that the route-classification injector runs
before minification (the production default). The prior fix made three tests
pass by building with minify:false, which is exactly the config where the old
post-minify generateBundle code also passed — so the tests no longer guarded
the bug.

- classification integration: add a production-default (minify on) suite that
  asserts minify-robust signals (injected switch dispatch shape + the
  module-graph reason literal, which is build-time-only). Verified it FAILS when
  the injector is reverted to a post-minify generateBundle hook.
- cache adapters: assert the minify-safe LOCAL_ADAPTER_MARKER under the default
  minified build instead of grepping the renamed registerConfiguredCacheAdapters
  symbol.
- tsconfig path alias (#659): run minified; the old not.toContain('title:
  "Second Post"') was a quote-escaping artifact (frontmatter renders as MDX
  content identically in both builds, not a minify leak) — replaced with a real
  parse-error/raw-YAML guard.
- update stale generateBundle references to renderChunk in injector error
  strings, app-rsc-entry stubs, and index.ts comments; note the per-chunk patch
  assumption near the renderChunk hook.

* test(build): run classification tests against minified output (no minify:false)

Previously the dispatch-logic suites built the fixture with minify:false so they
could regex-extract and eval the readable __VINEXT_CLASS function — but that is
the one config where the original post-minify-hook bug also passes, so it masked
the regression. Rewrite the extractors to be name-agnostic: derive the (mangled)
dispatch function name from its property-keyed call site (__buildTimeClassifications/
__buildTimeReasons — property keys survive minification) and eval the body
(string-literal values like "static" also survive). All suites now build with
vinext's production defaults (minify on). Verified by reproducing the bug
(disabling the patch): the minified tests fail with "was not patched".

* refactor(build): rename buildGenerateBundleReplacement; fix stale generateBundle doc refs

Address review nits: the classification dispatch builder still carried the old
hook name (it now runs in renderChunk, not generateBundle). Rename it to
buildClassificationReplacement (parallel to buildReasonsReplacement) and fix two
stale 'generateBundle' doc comments (route-classification-manifest.ts:203,
layout-classification.ts:130) to say renderChunk.
2026-06-06 22:55:04 +01:00
Divanshu Chauhan (divkix) fef54db9b4 fix: skip MDX files during RSC scan-build to prevent parse errors (#668)
* fix: skip MDX files during RSC scan-build to prevent parse errors (issue #659)

Adds a vinext:rsc-scan-mdx-guard plugin that runs with enforce:"pre"
to ensure MDX files are skipped before rsc:scan-strip processes them.
This prevents es-module-lexer parse errors when MDX files contain
frontmatter (---) or JSX that isn't valid JavaScript syntax.

Also adds a regression test that uses MDX files with YAML frontmatter
loaded via import.meta.glob to verify the build succeeds.

* fix(mdx): return stub module for undetected MDX files during scan-build

The guard plugin was a no-op that passed raw MDX through unchanged. When
rsc:scan-strip received this raw MDX, es-module-lexer.parse() failed on
frontmatter (---) and JSX syntax.

The real fix is in vinext:mdx: when mdxDelegate is null (no MDX files in app/
or pages/), return a valid JS stub module instead of undefined. This handles
MDX files that enter the build graph via import.meta.glob outside app/pages.

- Remove vinext:rsc-scan-mdx-guard plugin (was a no-op)
- Modify vinext:mdx to return stub module when mdxDelegate is null
- Remove app/mdx-probe/page.mdx from test (was hiding the bug)
- Replace fragile '---' assertion with specific frontmatter checks

Fixes issue #659

* fix(mdx): lazily compile globbed mdx imports

Compile plain .mdx files on demand when they enter the graph via import.meta.glob outside app/pages so scan-build stops crashing without discarding runtime content. Restore the existing happy-path MDX fixture, add focused lazy-compilation coverage, and extract shared Cloudflare fixture setup to keep the regression tests honest.

* fix review issues

* fix: use absolute path for root tsconfig alias to fix import.meta.glob resolution

toViteAliasReplacement was returning "/" (Vite root-relative convention) when
the tsconfig path alias pointed to the project root (e.g. "@/*": ["./*"]).
This worked for regular imports but broke import.meta.glob because Vite's
glob plugin resolves patterns via this.resolve(), which couldn't properly
resolve the "/" replacement to matching filesystem files.

Changed to return the absolute path instead, which works correctly for both
regular imports and glob pattern resolution.

Signed-off-by: Divanshu Chauhan <divkix@divkix.me>
Made-with: Cursor

* refactor: address review feedback on MDX lazy initialization

- Add clarifying comments for mdxDelegatePromise caching semantics
- Document subtle control flow when hasUserMdxPlugin is true
- Suppress duplicate warning on on-demand MDX init (only warn during detection)
- Add case-insensitive extension check in transform hook
- Add test for query parameter edge cases (?raw, ?v=123, etc.)

* refactor: address review feedback on MDX handling

- Merge duplicate query-param MDX skip tests in pages-router.test.ts
- Tighten hasUserMdxPlugin control flow comment for clarity
- Make scanDirForMdx case-insensitive to align with transform check

Refs: PR #668 review feedback

* docs: clarify mdx delegate fallback comment

* chore: trigger ci

---------

Signed-off-by: Divanshu Chauhan <divkix@divkix.me>
2026-03-29 19:51:50 +01:00
Steve Faulkner 5f1681bce7 Fix tsconfig alias transforms for RSC builds (#655)
* Fix tsconfig alias transforms for RSC builds

* Fix flaky compressed streaming timing test
2026-03-22 14:07:29 -05:00