Skip to content

Fix/1422 swc jsx development - #1493

Merged
dannyhw merged 6 commits into
callstack:mainfrom
whydidoo:fix/1422-swc-jsx-development
Oct 16, 2026
Merged

dannyhw merged 6 commits into
callstack:mainfrom
whydidoo:fix/1422-swc-jsx-development

Conversation

@whydidoo

Copy link
Copy Markdown
Collaborator

Part of #1422.

Summary

getSwcLoaderOptions (used by getJsTransformRules) set jsc.transform.react.development from the JSX runtime instead of the build mode. As a result:

  • dev builds on the default automatic runtime emitted jsx instead of jsxDEV, so they had no __source/__self, accurate component stacks or "open in editor";
  • classic production builds kept the dev transforms.
 getSwcLoaderOptions
-  react.development = jsxRuntime === 'classic'
+  react.development = options.development   # only when passed explicitly
 RepackPlugin.apply
+  builtin:swc-loader rules (incl. oneOf / nested rules) without explicit `development`
+    → development = mode === 'development'
  • New development option on getSwcLoaderOptions and getJsTransformRules({ swc: { development } }).
  • Dev builds now import <importSource>/jsx-dev-runtime. If a custom importSource doesn't ship it, set swc: { development: false }.

Test plan

  • tests/integration/src/plugins/RepackPlugin.test.ts (Rspack): with getJsTransformRules() + RepackPlugin, development mode gives true, production gives false, and an explicit development: false is kept. These were red before the change.

getSwcLoaderOptions tied jsc.transform.react.development to the JSX
runtime, so development builds with the default automatic runtime emitted
`jsx` instead of `jsxDEV` and lost __source/__self, accurate component
stacks and "open in editor", while classic production builds kept them.

Config helpers don't know the mode, so RepackPlugin now sets `development`
from `mode` for every builtin:swc-loader rule that doesn't set it
explicitly. getSwcLoaderOptions and getJsTransformRules accept a
`development` option to override it.

Part of callstack#1422
Development builds now import `<importSource>/jsx-dev-runtime`; document
the `development: false` override for import sources without it and that
the mode-based default comes from RepackPlugin.

Part of callstack#1422
@changeset-bot

changeset-bot Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a7a6386

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

@vercel

vercel Bot commented Oct 10, 2026

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

Comment thread packages/repack/src/plugins/utils/setSwcJsxDevelopment.ts Outdated

@dannyhw dannyhw 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.

Thanks for picking this up. The bug is real, and the getSwcLoaderOptions change fixes it. I checked tester-app with its app code routed through getJsTransformRules: on main a dev bundle has 0 app fileName entries (no jsxDEV source info). With this PR it has 78. Prod has 0 in both.

My main concern is that the RepackPlugin walker (setSwcJsxDevelopment) turns out to be unnecessary. Rspack's builtin:swc-loader already fills in jsc.transform.react.development from mode when it's unset and jsc.transform exists. An explicit value is kept, because the merge only fills unset fields.

I checked this on Rspack 1.0.0, 1.1.0, 1.3.0, 1.6.0 and 2.2.9, leaving development unset:

  • Dev: automatic gives jsxDEV + fileName, and classic gives __source.
  • Prod: neither runtime gives either.
  • An explicit false is kept.

I also built tester-app with only the getSwcLoaderOptions change and the walker removed. The output matches the full PR exactly: 78 in dev, 0 in prod.

So leaving the field unset in the helper is the whole fix. Inline suggestions:

  1. Drop setSwcJsxDevelopment and the RepackPlugin hook. Sorry, I know its unit tests were only just added at review request.
  2. Update the docs, JSDoc and changeset to say Rspack's builtin:swc-loader sets the default, not RepackPlugin.
  3. Make the integration tests check the compiled output instead of compiler.options.

Keeping the new development override option makes sense. Patch changeset is fine. If you'd rather keep the walker as insurance for older Rspack 1.x (the 1.x docs don't mention this behaviour, though the 1.0.0 source has it), I wouldn't block on that. In that case, though, the docs should still say that Rspack does this by default.

Comment thread packages/repack/src/plugins/RepackPlugin.ts Outdated
Comment thread packages/repack/src/plugins/utils/setSwcJsxDevelopment.ts Outdated
Comment thread packages/repack/src/utils/getSwcLoaderOptions.ts Outdated
Comment thread packages/repack/src/utils/getSwcLoaderOptions.ts Outdated
Comment thread packages/repack/src/utils/getJsTransformRules.ts Outdated
Comment thread website/src/latest/api/utils/get-swc-loader-options.md Outdated
Comment thread website/src/latest/api/plugins/repack.md Outdated
Comment thread .changeset/swc-jsx-development-mode.md Outdated
Comment thread tests/integration/src/plugins/RepackPlugin.test.ts Outdated

@dannyhw dannyhw 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.

Thanks for the quick turnaround, this looks great. I re-checked a7a63865 locally:

  • The new swc-jsx-development integration tests pass (6/6 on Rspack).
  • With main's jsxRuntime === 'classic' logic temporarily restored, exactly the two buggy cases fail (automatic in dev, classic in prod), so the tests catch the regression.
  • The full integration suite and the repack unit tests pass, and typecheck is clean.

@dannyhw
dannyhw merged commit 32c32c0 into callstack:main Oct 16, 2026
3 of 4 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.

3 participants