Skip to content

Define isolation guarantees for picks through named reexports #26

Open

Description

@everton-dgn

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.ts

The 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions