fix: Windows path compatibility for web and native (Metro) development#695
Open
YevheniiKotyrlo wants to merge 1 commit intoonejs:mainfrom
Open
fix: Windows path compatibility for web and native (Metro) development#695YevheniiKotyrlo wants to merge 1 commit intoonejs:mainfrom
YevheniiKotyrlo wants to merge 1 commit intoonejs:mainfrom
Conversation
Use pathToFileURL().href for all dynamic import() calls receiving
filesystem paths — ESM import() on Windows rejects bare paths like
C:\path as unsupported protocol "c:".
Use import.meta.dirname instead of new URL('.', import.meta.url).pathname
and join(import.meta.url, '..') — both produce invalid paths on Windows.
Use path.resolve() at the Vite→Metro boundary to normalize forward-slash
paths from Vite config to native backslash paths expected by Metro.
Use normalizePath from Vite for comparisons with facadeModuleId,
moduleIds, manifest keys, and relative() output in the build pipeline —
Vite uses forward slashes internally, path.join/relative use native
backslashes on Windows.
Add toAbsoluteUrl() helper for relative-path-to-file-URL conversion.
Normalize micromatch regex for cross-platform Metro route exclusion.
Fix isPathWithinBounds to use path.sep instead of hardcoded '/'.
Fix test fixtures to use platform-correct paths via resolve().
Extends the pattern established in onejs#640 (urlPathToFilePath).
Fixes onejs#152
Author
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.

Summary
Fix Windows path handling across
one,vxrn,@vxrn/resolve, and@vxrn/vite-plugin-metro— web dev, native (Metro) dev, production build, and production serve all crash on Windows due to 15 distinct path-related issues.Root causes fixed
import()with native paths — ESMimport()on Windows rejects bare paths likeC:\pathas unsupported protocolc:. Fixed withpathToFileURL(path).hrefacross 10 files (8 direct + 9 via a newtoAbsoluteUrl()helper).new URL('.', import.meta.url).pathname— returns/C:/path/...on Windows (leading/before drive letter).join(import.meta.url, '..')— produces.\file:\C:\...on Windows. Both replaced withimport.meta.dirname(available since Node 20.11, already required by this repo).Vite→Metro path boundary — Vite's
config.rootuses forward slashes, Metro'sRootPathUtilsexpects native backslashes. Fixed withpath.resolve()inmetroPlugin.tsandgetMetroConfigFromViteConfig.ts.normalizePathfor Vite internals —path.join()andpath.relative()return backslash paths on Windows, but Vite uses forward slashes forfacadeModuleId,moduleIds, and manifest keys. Middleware chunk lookup (build.ts:352), layoutcontextKey(:429), route chunk lookup (:472), critical CSS (criticalCSSPlugin.ts:66), and image data (imageDataPlugin.ts:15) all fail silently on Windows. Fixed withnormalizePathfrom Vite.micromatch.makeRe()Windows regex — picomatch 2.x auto-detects Windows and produces[\\/]instead of\/, breaking Metro API route exclusion atgetViteMetroPluginOptions.ts:63. Fixed withnormalizeReSource()helper.startsWith(allowed + '/')bounds check — never matches on Windows whereresolve()producesC:\path. Fixed withpath.sepinimageDataPlugin.ts:22.startsWith('../')inisWithin—relative()returns..\otheron Windows,startsWith('../')never matches — function always returnstrue. Fixed withstartsWith('..')+isAbsolute()guard inisWithin.ts:5.dirname(relativePath)in asset URL —'/assets/' + dirname(relative(...))produces/assets/src\img(mixed separators) in Metro asset registration. Fixed with.replace(/\\/g, '/')increateNativeDevEngine.ts:595.filePath.includes('/src/index.ts')— Metro'sfilePathuses\on Windows, soincludes('/src/index.ts')never matches —react-native-svgcompiled JS redirect is skipped. Fixed withpath.sepingetViteMetroPluginOptions.ts:156.Cross-platform safety
Every change is a no-op on POSIX:
pathToFileURLon Linux:file:///usr/src/app.js— valid ESM URLpath.resolve()on absolute POSIX path: returns input unchangednormalizeReSource(): no[\\/]groups on POSIX,.replace()finds no matchesnormalizePath: no backslashes on POSIXExtends the pattern established in #640 (
urlPathToFilePath).Fixes #152
Note: #281 is a separate Windows issue —
[vite:define] Transform failedbecauseloadEnvinvxrnspreadsprocess.envinto Vite'sdefineconfig, and Windows env vars likeProgramFiles(x86)contain characters that aren't valid JS identifiers. Not a path issue — not addressed by this PR.Test plan
CI runs on
ubuntu-latestonly — no Windows runner available. All changes verified manually on both platforms.Linux (WSL — Ubuntu 22.04, Bun 1.3.11, Node 24.3.0)
bun run build— 22/22 packagesbun run lint— 0 errorsbun run format:check— passbun run test:one— 24/24 files, 365 passed + 56 skippedWindows (Windows 11, Bun 1.3.11, Node 25.2.1)
Clean install:
node_modules/+.one/deleted,bun installfrom scratch.bun run build— 22/22 packagesbun run lint— 0 errorsbun run format:check— passbun run test:one— 24/24 files, 365 passed + 56 skippedone devweb (SSG + SSR + SPA) — all render modes workone devnative (Metro) — cold bundle completes, app renders on Android emulatorone build— production build completesone serve— SSG, SSR, SPA, API all respond correctlyone prebuild— generates native project