Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix: infer publicPath "auto" for a relative Vite base (base: "./")#893

Merged
gioboa merged 1 commit into
module-federation:mainfrom
smeng9:fix/relative-base-publicPath-auto
Jul 10, 2026
Merged

fix: infer publicPath "auto" for a relative Vite base (base: "./")#893
gioboa merged 1 commit into
module-federation:mainfrom
smeng9:fix/relative-base-publicPath-auto

Conversation

@smeng9

@smeng9 smeng9 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Problem

A relative Vite base (base: "./") exists so a build can be hosted under any folder without knowing that folder at build time — you deploy the same output to /, /app/, /some/deep/path/, etc., and every asset URL is resolved relative to wherever the entry actually loaded from. That's the whole point of "./": "relative to whatever folder I choose to host under." Vite documents exactly this value: ./ (for embedded deployment).

The Module Federation publicPath should follow the same principle: it should be determined automatically at runtime from the location the remote entry was loaded from. Instead, when a remote is built with base: "./" (and no explicit publicPath), the generated mf-manifest.json bakes in a literal "./":

// mf-manifest.json
"metaData": { ..., "publicPath": "./" }

A literal "./" publicPath defeats the purpose. publicPath tells the MF runtime where to load the remote's chunks from, and "./" gets resolved relative to the host document — i.e. the host site's root (or whatever page is consuming the remote) — not the folder the remote entry was actually served from. So the moment the remote is hosted under a subfolder, or consumed from a host on a different path/origin, its shared/exposed chunks resolve to the wrong location and fail to load.

A relative base is precisely the case where the location must be inferred from the remote entry script at runtime — webpack's "auto" — rather than pinned to the consumer's root.

Root cause

resolvePublicPath in src/utils/pathNormalization.ts:

if (!originalBase) {
  return 'auto';            // unset base → infer at runtime ✅
}
if (viteBase) {
  return ensureTrailingSlash(viteBase);   // "./"  →  ensureTrailingSlash("./")  →  "./"  ❌
}

For base: "./", originalBase is truthy so the 'auto' branch is skipped, and ensureTrailingSlash("./") returns the literal "./". A relative base falls through to the literal branch instead of being treated as "infer at runtime".

Fix

Treat a relative base the same as an unset base — return "auto":

if (viteBase) {
  if (viteBase === './') {
    return 'auto';
  }
  return ensureTrailingSlash(viteBase);
}

The check matches exactly "./" because that is the only relative value Vite ever produces for a resolved config.base. Vite's config resolution maps base: "./" (and base: "") to exactly "./" for a client build, and normalizes any other "."-prefixed base (e.g. ".", "../") to "/" with a warning ("The value can only be an absolute URL, ./, or an empty string"). So a broader check like startsWith('./') or a === '.' branch would be dead code.

Absolute bases (/foo/) and full-URL bases (https://cdn/) are unaffected. The dev (serve) path is unaffected because it already passes no originalBase and returns "auto" early (and Vite resolves a relative base to "/" in serve anyway).

Tests

Added unit coverage for resolvePublicPath in src/utils/__tests__/pathNormalization.test.ts, including the relative-base cases ("./" and ".""auto") plus characterization tests for the explicit-publicPath, "auto"-as-unset, unset-base, and absolute-base paths.

  • pnpm test → all unit tests pass (642)
  • pnpm typecheck → clean
  • oxfmt --check src → clean

@smeng9 smeng9 force-pushed the fix/relative-base-publicPath-auto branch 10 times, most recently from e609632 to 6753a17 Compare July 10, 2026 02:25
When a remote is built with a relative Vite base (`base: "./"` or "."),
`resolvePublicPath` returned the literal relative value (via
`ensureTrailingSlash("./")` -> "./") and emitted it as the manifest's
`metaData.publicPath`.

A relative publicPath is not usable by the Module Federation runtime: it
resolves remote chunks relative to the host document instead of the remote
entry, so consuming a remote from a different origin/path fails to load its
assets. A relative base is precisely the case where the runtime should infer
the location from the remote entry script, i.e. webpack's "auto".

Treat a relative base ("./" or ".") as "auto", matching the existing behavior
for an unset base.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@smeng9 smeng9 force-pushed the fix/relative-base-publicPath-auto branch from 6753a17 to fed7fe8 Compare July 10, 2026 02:27
@smeng9 smeng9 marked this pull request as ready for review July 10, 2026 02:29
@pkg-pr-new

pkg-pr-new Bot commented Jul 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@module-federation/vite@893

commit: fed7fe8

@gioboa gioboa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests With Different Frameworks

Image

@gioboa gioboa merged commit 1ecfcc1 into module-federation:main Jul 10, 2026
19 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.

2 participants