Skip to content

Conversation

@hi-ogawa
Copy link
Contributor

@hi-ogawa hi-ogawa commented Jan 16, 2026

Summary

Add import.meta.viteRsc.import() - a more ergonomic API for cross-environment module loading.

import.meta.viteRsc.import: <T>(
  specifier: string,
  options: { environment: "ssr" | "rsc" },
) => Promise<T>

Comparison

Before (loadModule):

// vite.config.ts - must configure entry manually
export default {
  environments: {
    ssr: {
      build: {
        rollupOptions: {
          input: { index: './entry.ssr.tsx' }
        }
      }
    }
  }
}

// entry.rsc.tsx
const ssrModule = await import.meta.viteRsc.loadModule<typeof import('./entry.ssr')>(
  'ssr',
  'index'
);

After (import):

// vite.config.ts - no explicit `rollupOptions.input` needed

// entry.rsc.tsx
const ssrModule = await import.meta.viteRsc.import<typeof import('./entry.ssr')>(
  './entry.ssr',
  { environment: 'ssr' }
);

How it works

  • Dev: Uses __VITE_ENVIRONMENT_RUNNER_IMPORT__ (same as loadModule)
  • Build: Auto-discovers imports, emits entries, generates manifest (__vite_rsc_env_imports_manifest.js)

Documentation

  • README.md - API documentation with comparison
  • types/index.d.ts - TypeScript types with JSDoc

Test plan

  • Implement transform plugin
  • Test build mode with starter example
  • Verify entry auto-discovery works
  • Test dev mode

🤖 Generated with Claude Code

hi-ogawa and others added 16 commits January 16, 2026 12:25
- Add architecture.md documenting build pipeline and data flow
- Add bundler-comparison.md comparing RSC approaches across bundlers
- Add implementation plan for new ergonomic import API
- Stub import-environment.ts plugin file

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add import-environment plugin with transform/renderChunk hooks
- Dev mode: rewrite to globalThis.__VITE_ENVIRONMENT_RUNNER_IMPORT__
- Build mode: emit marker, resolve in renderChunk to relative import
- Auto-discover entries and inject into target environment's input
- Handle empty SSR input case in buildApp orchestration

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Document the preferred implementation using static import functions
in a manifest file, which supports custom entryFileNames and enables
proper static analysis by bundlers.

Key additions:
- Manifest with static import functions (not dynamic lookups)
- Bidirectional support (RSC → SSR and SSR → RSC)
- Updated data flow showing entry injection after both scans
- Per-environment manifest generation

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…leNames

Replace hardcoded output filenames with a manifest approach that supports
custom entryFileNames config. The manifest uses static import functions
for proper bundler analysis.

Changes:
- Transform emits manifest lookup instead of markers
- resolveId marks manifest as external during build
- generateBundle tracks resolvedId → outputFileName mapping
- writeEnvironmentImportsManifest generates manifest after all builds
- Split entry injection for bidirectional support (RSC↔SSR)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace direct rollupOptions.input mutation with:
- Virtual scan placeholder for scan builds without configured entries
- emitFile in buildStart for emitting discovered entries in real builds

This follows the fullstack plugin pattern and provides cleaner separation
between scan and real build phases.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Use a placeholder in transform and replace with correct relative path
in renderChunk, similar to how BUILD_ASSETS_MANIFEST_NAME is handled.
This ensures manifest imports work correctly for nested chunk outputs.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Let Rollup auto-name emitted chunks instead of deriving entry names
from specifiers. The actual output filename is tracked via
generateBundle anyway, so the explicit name was unnecessary.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…tMetaMap

Add fileName field to EnvironmentImportMeta instead of tracking output
filenames in a separate map. This simplifies the data structure and
removes the TODO about merging the maps.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Use toRelativeId() for manifest keys instead of absolute paths.
This ensures stable builds across different machines/environments.

Before: "/home/user/.../entry.ssr.tsx"
After:  "src/framework/entry.ssr.tsx"

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Change from `Record<resolvedId, meta>` to `Record<sourceEnv, Record<resolvedId, meta>>`.
This properly handles the case where the same module is imported from multiple
source environments, avoiding overwrites.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@hi-ogawa hi-ogawa force-pushed the 01-16-feat_rsc_add_import_._environment_._ branch from de75327 to b2b877a Compare January 16, 2026 07:25
hi-ogawa and others added 9 commits January 16, 2026 16:40
Add documentation for the new import.meta.viteRsc.import() API in both
README.md and types/index.d.ts with JSDoc, examples, and type signatures.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…esolution

- Replace `rscBundle` with `bundles: Record<string, OutputBundle>` in RscPluginManager
- Lookup fileName from bundles in writeEnvironmentImportsManifest instead of mutating meta
- Remove generateBundle hook from import-environment plugin (no longer needed)
- Remove unused fileName field from EnvironmentImportMeta type

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…nv][resolvedId]

- Update type definition to add targetEnv as middle key
- Update write logic in transform to use new structure
- Update buildStart to lookup by targetEnv directly (more efficient)
- Update writeEnvironmentImportsManifest to iterate by targetEnv

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@hi-ogawa hi-ogawa marked this pull request as ready for review January 16, 2026 08:42
@hi-ogawa hi-ogawa marked this pull request as draft January 16, 2026 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants