refactor: iterate viteConfig.environments directly instead of re-invoking plugin config hook#442
Merged
Merged
Conversation
Replace the ViteEnvironmentsConfig/findPlugin/hasPlugin pattern with direct iteration over viteConfig.environments. This supports the RSC environment without requiring manual plugin config hook invocation.
The development.ts refactor (iterating viteConfig.environments directly instead of re-invoking the plugin config hook) changed the contract: loadEntryModulePaths now reads viteConfig.environments.ssr.build.rollupOptions.input to discover entry paths. Add the environments field to the test mock so createServerModuleRunner is exercised as intended.
…double SSR ModuleRunner
loadEntries() called createServerModuleRunner(envConfig) unconditionally,
creating a separate ModuleRunner. When @vitejs/plugin-rsc later performed
cross-environment imports via import.meta.viteRsc.import('ssr', ...),
RunnableDevEnvironment.runner lazy getter created a second independent
ModuleRunner — causing duplicate '(ssr) connected' logs and duplicate
HMR connections.
For RunnableDevEnvironment instances, use envConfig.runner (the same
cached getter the RSC plugin uses) instead of createServerModuleRunner.
Generalize the rollupOptions.input type from { index?: string } to
Record<string, string> and iterate over all entries instead of only
the 'index' key. This is required when vite environments use
non-standard entry names (e.g., when @vitejs/plugin-rsc registers
its own build environments).
🦋 Changeset detectedLatest commit: 6098208 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refactor environment discovery to iterate
viteConfig.environmentsdirectlyRemoves the fragile
findPlugin/hasPluginpattern that re-invoked the plugin's config hook to discover environment entry paths. Instead, readsviteConfig.environmentsdirectly — the same source of truth Vite already provides.Why
The old approach called the plugin's
confighook a second time at runtime to reconstruct environment configuration. This broke when another plugin (like@vitejs/plugin-rsc) modified the same environments during its ownconfighook — the re-invocation could produce a different result or fail outright.The new approach iterates
viteConfig.environmentsdirectly, which is always available after Vite resolves its config. No plugin introspection needed.Changes
development.ts(environment config) —loadEntryModulePaths()now walksviteConfig.environmentsdirectly, instead of re-invoking the plugin's config hook on a synthetic object. Removes thefindPlugin/hasPluginintrospection helpers and theViteEnvironmentsConfiginterface. Because the new path reads already-resolved config, it also strips Vite's internal\0null-byte prefix from virtual module IDs. The file deletes ~90 lines total. Returnsnull(not{}) when no environments match — the caller handles both identically.development.ts(runner reuse) —loadEntries()usesisRunnableDevEnvironment(envConfig).runnerwhere available, falling back tocreateServerModuleRunner(). Avoids creating a duplicateModuleRunnerwhen@vitejs/plugin-rsclater accessesenvConfig.runnervia its lazy getter for cross-environment imports.plugin.ts— GeneralizesrollupOptions.inputfrom{ index?: string }toRecord<string, string>. Iterates all input entries, not just the one namedindex. Required when Vite environments register entries under non-standard names.development.test.ts— Addsenvironmentsfield to the mock config soloadEntryModulePathsis exercised as intended.Verification
tscbuild produces no errorsnull) when none match