Skip to content

fix: resolve slash-prefixed lazy() moduleUrl keys in dev and build - #399

Merged
ryansolid merged 1 commit into
nextfrom
fix/issue-390-lazy-leading-slash
Oct 8, 2026
Merged

ryansolid merged 1 commit into
nextfrom
fix/issue-390-lazy-leading-slash

Conversation

@ryansolid

Copy link
Copy Markdown
Member

Fixes #390.

Problem

A hand-written lazy() moduleUrl with a leading slash (lazy(() => import("./Page"), undefined, "/src/Page.tsx")) never resolved. The compiler leaves three-argument calls alone, so the string reached the resolvers as written:

  • Dev: devModuleUrl and its generated mirror built base + "/" + key, giving a protocol-relative //src/Page.tsx. The CSS walk also missed because path.resolve(root, "/src/Page.tsx") is an absolute path outside the project.
  • Build: the runtime looks records up as manifest[moduleUrl], and the baked manifest has no /src/Page.tsx key, so no client assets or module map were emitted.

Fix

Normalize on the plugin side so dev and build agree without a runtime change:

  • The dev resolver (in-process, HTTP bridge, and the generated moduleUrl fallback in devManifestCode) strips leading slashes before building the URL and walking the module graph.
  • The baked virtual:solid-manifest defines a non-enumerable "/" + key alias for each record. for…in, Object.keys, and JSON.stringify still see the manifest unchanged, so registerEntryAssets, _entry, and external manifest consumers aren't affected.

Tests

  • examples/start-ssr: a SlashLazy fixture on /lazy-assets with a "/src/SlashLazy.tsx" key. runLazyAssetChecks asserts that dev preloads /src/SlashLazy.tsx (it was //src/SlashLazy.tsx before the fix) and that prod preloads the manifest's hashed file (no preload was emitted before). The checks also pass under a non-root base.
  • examples/css-matrix/test/bridge.mjs: the HTTP bridge resolves a slash-prefixed key to the same URL and CSS, and the generated fallback resolveSync maps it to the root-relative URL.

Ran locally: start-ssr dev, prod, and base; css-matrix run and bridge; and the ssr example. The new assertions fail on next without the src/ change.

Open question

The issue leaves open whether to normalize in the plugin or in @solidjs/web's resolveAssets. This PR normalizes in the plugin, which covers hand-rolled server entries that import virtual:solid-manifest. A runtime-side manifest[key] ?? manifest[key.slice(1)] would make the build aliases unnecessary. The alternative is rejecting slash keys with an error instead of normalizing them.

Made with Cursor

@changeset-bot

changeset-bot Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ec428e1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solidjs/vite-plugin Patch

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

@pkg-pr-new

pkg-pr-new Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@solidjs/vite-plugin@399

commit: ec428e1

Co-authored-by: Cursor <cursoragent@cursor.com>
@ryansolid
ryansolid force-pushed the fix/issue-390-lazy-leading-slash branch from d6b5613 to ec428e1 Compare October 8, 2026 20:17
@ryansolid
ryansolid merged commit 9aa91f1 into next Oct 8, 2026
6 checks passed
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.

1 participant