Repository navigation
Define isolation guarantees for picks through named reexports #26
Description
When route metadata is reexported from a page module, selecting only route from the wrapper still loads the page's component dependency and CSS. Selecting route directly from the page isolates them. I'd like to clarify the intended boundary before proposing a production change.
My consumer loads route metadata in an isolated server runner to generate static artifacts. It currently rewrites named reexport sources to pass the selected names through. Removing that workaround would simplify the integration, but unconditional propagation has an identity problem.
Reproduction
Executable fixture and assertions, based on 90a19eeb5c58becb0b5d599527c99452eab6f1c5.
git clone --branch fix/named-reexport-picks https://github.com/everton-dgn/filesystem-routing.git
cd filesystem-routing
git checkout 805f1624409fe0cf825916023b47af6171687b90
pnpm install --frozen-lockfile
pnpm exec vitest run test/named-reexport-picks.spec.ts
EXPECT_TRANSITIVE_PICK=1 pnpm exec vitest run test/named-reexport-picks.spec.tsThe first test run characterizes the current behavior and passes all 14 cases. The second asks for transitive isolation and fails in three cases: dev SSR, client build and SSR build.
The relevant pattern is:
// wrapper.tsx
export { default, route } from "./page.tsx";
// consumer
import { route } from "./wrapper.tsx?pick=route&lang.tsx";The selected wrapper retains export { route } from "./page.tsx". The source module is loaded without a pick. The fixture gives the component dependency an observable side effect and sets sideEffects: true, so the build comparison does not depend on ordinary dead-code elimination.
Why a source rewrite is insufficient
A test-only rewrite to ./page.tsx?pick=route&lang.tsx isolates the component dependency. When another consumer imports the full page, however, it creates a second instance:
| Source in the selected wrapper | Same metadata object as the full page | Metadata initializer calls |
|---|---|---|
| Original source | yes | 1 |
| Source with propagated pick | no | 2 |
This happens in dev SSR and in the executed SSR bundle. It is related to the module-identity concern in #16 and #17. This fixture uses an observable initializer; it does not reproduce registerServerReference or the HTTP 405 path itself.
Moving metadata into a separate module works with the current API: it avoids loading the component dependency and preserves the same metadata instance. That adds an explicit module boundary for consumers to maintain.
Contract question
Should picks remain module-local, with separate metadata modules as the supported pattern, or would a narrowly scoped selection mechanism for isolated loading graphs fit this package?
Any transitive behavior would need to define module identity, aliases, multiple selected names, existing queries, explicit side effects and $css. The reproduction also confirms that export * stays unchanged; expanding its behavior is outside this proposal.
Validated with Node 24.15.0, Vite 6.4.3 and Vitest 2.1.9. The full suite passes 127 tests; TypeScript, build and formatting checks pass. Vite 7/8, HMR and browser execution were not tested. The linked commit contains only the reproduction tests.
Activity