Turbopack: properly set NODE_ENV for SWC plugins#92579
Merged
Merged
Conversation
Contributor
Stats from current PR✅ No significant changes detected📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📎 Tarball URL |
Merging this PR will not alter performance
Comparing Footnotes
|
bgw
approved these changes
Apr 9, 2026
a0e02f4 to
99ddbb7
Compare
Member
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Contributor
Tests Passed |
99ddbb7 to
62adbc5
Compare
785c7ae to
415c9a8
Compare
c10ad97 to
424da41
Compare
415c9a8 to
3773c9b
Compare
424da41 to
56a1f9f
Compare
3773c9b to
1d41e4b
Compare
56a1f9f to
c413281
Compare
mischnic
added a commit
that referenced
this pull request
Apr 15, 2026
Webpack didn't correctly load relative paths for `swcPlugins`. #92579 will add a test
…builds Thread the actual build mode (NextMode) through to SwcEcmaTransformPluginsTransformer so that TransformPluginMetadataContext receives "production" during `next build` instead of the previously hardcoded "development" string. Fixes #92547 Store node_env in TransformContext instead of SwcEcmaTransformPluginsTransformer The SWC plugin transformer was storing node_env as a field on the struct, which caused it to be locked in at plugin construction time from NextMode. Instead, derive node_env from process.env.NODE_ENV compile-time defines in EcmascriptModuleAsset::parse() and thread it through TransformContext so each file transformation sees the correct environment value. Thread compile_time_info through webpack path to eliminate hardcoded node_env strings Extract node_env_from_compile_time_info() as a shared helper in parse.rs and use it from both EcmascriptModuleAsset::parse() and the webpack analysis path. Thread compile_time_info through WebpackModuleAsset, WebpackChunkAssetReference, WebpackEntryAssetReference, WebpackRuntimeAssetReference, webpack_runtime(), and module_references() so that SWC plugin transforms on webpack bundles also see the correct NODE_ENV. Add a comment in segment_config.rs explaining why the node_env value is irrelevant there (EcmascriptInputTransforms::empty() = no transforms run). Co-Authored-By: Claude <noreply@anthropic.com>
c413281 to
412a6d2
Compare
fe6d57b to
56e5acc
Compare
412a6d2 to
4db4292
Compare
This was referenced Apr 23, 2026
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.

What?
Closes #92650
Closes #92547
When Turbopack runs SWC transform plugins, it passes a
TransformPluginMetadataContextthat includes the currentNODE_ENV. Previously this value was hardcoded to"development"regardless of the actual build mode, causing SWC plugins to misbehave during production builds.Why?
SwcPluginMetadataContextis used by SWC plugins (e.g.babel-plugin-styled-components,@swc/plugin-emotion) to conditionally produce development vs. production output — for instance, injecting display names and data attributes only in development. WithNODE_ENValways set to"development", plugins could never produce their optimised production output, resulting in larger bundles and missing minification innext build.Fixes #92547
How?
NODE_ENVis now derived from theprocess.env.NODE_ENVcompile-time define that is already part ofCompileTimeInfo(the same source of truth used for dead-code elimination). The resolution happens inEcmascriptModuleAsset::parse()via a new shared helpernode_env_from_compile_time_info()inparse.rs, and the value is stored onTransformContextso everyCustomTransformerimplementation can read it fromctx.node_envwithout needing access to the broader compilation context.Key design decisions:
TransformContextis the right place: it is the per-file context passed to everyCustomTransformer::transform()call, so storingnode_envthere follows the existing pattern and avoids coupling the plugin struct to the build mode.compile_time_infois now threaded throughwebpack_runtime(),module_references(), and the webpack reference structs (WebpackModuleAsset,WebpackChunkAssetReference,WebpackEntryAssetReference,WebpackRuntimeAssetReference) so that webpack-bundled files with SWC plugin transforms also receive the correctNODE_ENV.segment_config.rs: passes a placeholder but includes a comment explaining it is irrelevant sinceEcmascriptInputTransforms::empty()means no transforms run.