Skip to content

fix: normalize options.context to native separators - #14525

Closed
stormslowly wants to merge 4 commits into
mainfrom
fix/normalize-context-separator
Closed

stormslowly wants to merge 4 commits into
mainfrom
fix/normalize-context-separator

Conversation

@stormslowly

Copy link
Copy Markdown
Contributor

Why

Fixes #14446 — on Windows, file watching stops after the first change (the dev server keeps running but ignores all later edits). It works on Linux/macOS.

Root cause (confirmed on a Windows runner): the repro's config uses context: __dirname, and the rspack CLI loads the config via jiti, whose __dirname is forward-slash on Windows (e.g. D:/a/project). rspack only defaults context and never normalizes a user-provided one, so the forward-slash value becomes the resolver base and the resolver emits mixed-separator dependency paths (e.g. D:/a\project\src\App.tsx).

watchpack registers file watchers keyed by the raw path but reconstructs incoming OS-event paths via path.join (native \), so the registered key and the event key differ and the change is dropped:

registered: d:/a\project\src\app.tsx   (mixed, from a forward-slash context)
fs event  : d:\a\project\src\app.tsx   (path.join => all backslash)
=> mismatch => change ignored

Single-separator platforms (Linux/macOS) are unaffected.

What

Normalize options.context to the OS-native separator in applyRspackOptionsDefaults (path.resolve), so the resolver base — and therefore every watch dependency path — uses one consistent separator.

  F(options, 'context', () => process.cwd());
+ options.context = path.resolve(options.context!);

No-op on POSIX and for already-native absolute contexts (existing defaults snapshots unchanged).

Verification

Reproduced and fixed on a real Windows runner (instrumented diagnostics in #14524):

scenario (Windows) result
rspack serve, context as-is watch stops after 1st change (REPRODUCED)
rspack serve, context normalized to native sep every change recompiles (FIXED)

Workaround for users on current releases: context: path.resolve(__dirname).

On Windows a config loaded via jiti yields a forward-slash `__dirname`.
Used as the resolver base, it produces mixed-separator dependency paths
(e.g. `D:/a\...\App.tsx`) that watchpack cannot match against its
path.join-reconstructed event paths, so file changes are silently dropped
after the first rebuild — file watching appears to stop. Closes #14446.
Copilot AI review requested due to automatic review settings June 21, 2026 10:13
@stormslowly
stormslowly requested a review from hardfist as a code owner June 21, 2026 10:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a Windows-only file-watching failure by normalizing options.context to OS-native separators during default option application, preventing mixed-separator dependency paths from being emitted and later mismatched by watchpack.

Changes:

  • Normalize options.context via path.resolve after defaulting it to process.cwd().
  • Add an explanatory comment referencing the Windows watch bug (#14446).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/rspack/src/config/defaults.ts Outdated
@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

📦 Binary Size-limit

Comparing f394f57 to chore(deps): bump rspack_resolver to 0.9.3 (#14521) by pshu

🙈 Size remains the same at 67.91MB

@codspeed

codspeed Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 41 untouched benchmarks
⏩ 47 skipped benchmarks1


Comparing fix/normalize-context-separator (f394f57) with main (2310268)

Open in CodSpeed

Footnotes

  1. 47 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Skip path.resolve for an empty context so it stays falsy and the
relative-output-path validation still throws (#14446 review).
@stormslowly
stormslowly requested a review from chenjiahan June 21, 2026 16:36
@stormslowly stormslowly changed the title fix: normalize options.context to native separators (#14446) fix: normalize options.context to native separators Jun 22, 2026
@stormslowly
stormslowly marked this pull request as draft June 22, 2026 08:35
@hardfist

Copy link
Copy Markdown
Contributor

@codex review

@stormslowly stormslowly reopened this Aug 12, 2026
@stormslowly
stormslowly marked this pull request as ready for review August 12, 2026 03:28

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f394f5738d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +68 to +69
if (options.context) {
options.context = path.resolve(options.context);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize context before constructing the Compiler

When a Windows config supplies a forward-slash context, this assignment normalizes only compiler.options.context; createCompiler has already passed the original value to new Compiler (rspack.ts:62), where it is retained as compiler.context (Compiler.ts:310). Consequently plugins and loaders that use the public compiler.context or loaderContext.rootContext still receive the mixed-separator-prone value, while compiler.options.context contains a different path. Normalize before construction or synchronize compiler.context so all context consumers observe the native path.

Useful? React with 👍 / 👎.

@stormslowly

stormslowly commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

After some discussion, we think

  • the configuration passed to rspack core should be well-formed, and the context path should be a valid path string according to the platform
  • the config is better normalized by @rspack/cli

The problem will be fixed by #15162

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.

[Bug]: File watching stops after first change on Windows

3 participants