Skip to content

fix(assets-loader): join public paths with path.posix so remote assets work on Windows - #1457

Open
KallinikosMil wants to merge 2 commits into
callstack:mainfrom
KallinikosMil:fix/assets-loader-posix-public-path
Open

fix(assets-loader): join public paths with path.posix so remote assets work on Windows#1457
KallinikosMil wants to merge 2 commits into
callstack:mainfrom
KallinikosMil:fix/assets-loader-posix-public-path

Conversation

@KallinikosMil

Copy link
Copy Markdown
Contributor

Summary

On Windows, any bundle that contains a remote asset fails to build:

Module build failed (from ../../packages/repack/dist/loaders/assetsLoader/index.js):
TypeError: Invalid URL
    at new URL (node:internal/url:818:25)
    at convertToRemoteAssets (…/assetsLoader/convertToRemoteAssets.js:23:25)

The cause is in convertToRemoteAssets:

// works on both unix & windows
const publicPathURL = new URL(path.join(remotePublicPath, assetPath));

path.join is a filesystem-path function. On Windows it rewrites the separators to backslashes and, because https: is not a drive letter, prefixes the result with .\:

path.join('https://example.com/assets', 'assets/images')
  Linux/macOS → 'https:/example.com/assets/assets/images'      (new URL accepts this)
  Windows     → '.\https:\example.com\assets\assets\images'    (new URL throws)

extractAssets has the same shape one level up — publicPath = path.join(customPublicPath, publicPath) — on a value that is served over HTTP and is always forward-slashed. It is a bit ironic: the line immediately above each of these already normalises the path with pathSeparatorRegexp so it uses forward slashes, and the path.join then undoes that on Windows.

Fix

Both values are URLs, not filesystem paths, so they are now joined with path.posix.join. On Linux and macOS path.join is path.posix.join, so output there is byte-for-byte unchanged — this is a no-op everywhere the loader currently works. Two lines, plus comments saying why so it does not get "fixed" back.

Found the same way as #1450: running pnpm test on Windows against main. The tester app was the one that surfaced it, since it builds a real bundle with a remote asset for both platforms.

Verification (Windows, current main)

before after
tester-app (apps/tester-app, vitest) 3 files: 1 failed, 2 passed · 4 failed, 10 passed — all four Invalid URL 3 passed · 14 / 14
@callstack/repack (jest) 34 / 34 suites, 312 / 312 34 / 34, 312 / 312, 22 / 22 snapshots
pnpm lint:ci
pnpm typecheck 11 / 11 11 / 11

Checked and not touched: the other path.join calls in assetsLoader.ts (lines 174–188) build the on-disk destination for extracted files, which genuinely is a filesystem path — those are correct as they are.

Related, not fixed here

tests/integration is still red on Windows after this (50 of 58). With this change the eight Invalid URL failures are gone from it, but the remaining ones are all in the test harness rather than the loader: the memfs volume.toTree() snapshots expect /out/… and receive \out/…. That is a separate fix in the test setup, and I would rather keep this PR to the production bug.

This also unblocks the windows-latest matrix you asked for on #1450@callstack/repack, repack-dev-server, metro-compat, resolver-cases and tester-app are all green on Windows now, so that follow-up can cover everything except tests/integration honestly rather than excluding two workspaces.

🤖 Generated with Claude Code

https://claude.ai/code/session_018U3wcP5Qm39cas5MtVVabw

…s work on Windows

`convertToRemoteAssets` built the remote asset URL with
`path.join(remotePublicPath, assetPath)`. On Windows that rewrites the
separators to backslashes and, because `https:` is not a drive letter,
prefixes the result with `.\` — so `new URL` throws `Invalid URL` and any
bundle that contains a remote asset fails to build. `extractAssets` did the
same to `publicPath`, which is served over HTTP and always uses forward
slashes.

Both values are URLs, not filesystem paths, so they are now joined with
`path.posix.join`. On Linux and macOS `path.join` and `path.posix.join` are
the same function, so the output there is unchanged.

Before, on Windows: tester-app 4 failed / 10 passed, every failure
`TypeError: Invalid URL` from the assets loader. After: 14 / 14.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018U3wcP5Qm39cas5MtVVabw
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

@KallinikosMil is attempting to deploy a commit to the Callstack Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot

changeset-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3a2e375

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

This PR includes changesets to release 6 packages
Name Type
@callstack/repack Patch
@callstack/repack-plugin-expo-modules Patch
@callstack/repack-plugin-nativewind Patch
@callstack/repack-plugin-reanimated Patch
@callstack/repack-dev-server Patch
@callstack/repack-init 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

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