diff --git a/crates/pack-core/src/client/context.rs b/crates/pack-core/src/client/context.rs index 102d4cc2fd..dc610099a3 100644 --- a/crates/pack-core/src/client/context.rs +++ b/crates/pack-core/src/client/context.rs @@ -278,7 +278,7 @@ pub async fn get_client_module_options_context( } else { false }; - let jsx_runtime_options = get_jsx_transform_options( + let jsx_transform_options = get_jsx_transform_options( project_path.clone(), mode, false, @@ -381,7 +381,6 @@ pub async fn get_client_module_options_context( enable_typescript_transform: Some( TypescriptTransformOptions::default().resolved_cell(), ), - enable_jsx: Some(JsxTransformOptions::default().resolved_cell()), ignore_dynamic_requests: true, ..Default::default() }, @@ -406,6 +405,7 @@ pub async fn get_client_module_options_context( let foreign_codes_options_context = ModuleOptionsContext { ecmascript: EcmascriptOptionsContext { enable_typeof_window_inlining: None, + enable_jsx: Some(jsx_transform_options), ..module_options_context.ecmascript }, enable_webpack_loaders: foreign_enable_webpack_loaders, @@ -417,6 +417,7 @@ pub async fn get_client_module_options_context( let internal_context = ModuleOptionsContext { ecmascript: EcmascriptOptionsContext { + enable_jsx: Some(JsxTransformOptions::default().resolved_cell()), ..module_options_context.ecmascript.clone() }, enable_postcss_transform: None, @@ -428,7 +429,7 @@ pub async fn get_client_module_options_context( // we try resolve it once at the root and pass down a context to all // the modules. ecmascript: EcmascriptOptionsContext { - enable_jsx: Some(jsx_runtime_options), + enable_jsx: Some(jsx_transform_options), enable_typescript_transform: Some(tsconfig), enable_decorators: Some(decorators_options.to_resolved().await?), ..module_options_context.ecmascript.clone() diff --git a/crates/pack-core/src/config.rs b/crates/pack-core/src/config.rs index e64d92d8ee..8d7a28f5d2 100644 --- a/crates/pack-core/src/config.rs +++ b/crates/pack-core/src/config.rs @@ -123,6 +123,7 @@ pub struct Config { provider: Option>, images: Option, pub styles: Option, + react: Option, optimization: Option, stats: Option, persistent_caching: Option, @@ -240,6 +241,14 @@ pub struct ExternalAdvanced { pub sub_path: Option, } +#[turbo_tasks::value(eq = "manual")] +#[derive(Clone, Debug, PartialEq, Default, Deserialize, OperationValue)] +#[serde(rename_all = "camelCase")] +pub struct ReactConfig { + /// JSX runtime mode: "automatic" (default) or "classic" + pub runtime: Option, +} + #[turbo_tasks::value(eq = "manual")] #[derive(Clone, Debug, PartialEq, Default, Deserialize, OperationValue)] #[serde(rename_all = "camelCase")] @@ -944,6 +953,11 @@ impl Config { self.styles.clone().unwrap_or_default().cell() } + #[turbo_tasks::function] + pub fn react(&self) -> Vc { + self.react.clone().unwrap_or_default().cell() + } + #[turbo_tasks::function] pub fn output(&self) -> Vc { self.output.clone().unwrap_or_default().cell() diff --git a/crates/pack-core/src/transform_options.rs b/crates/pack-core/src/transform_options.rs index 3c3f81f12d..ee54a29f2a 100644 --- a/crates/pack-core/src/transform_options.rs +++ b/crates/pack-core/src/transform_options.rs @@ -121,13 +121,9 @@ pub async fn get_jsx_transform_options( enable_react_refresh: bool, ) -> Result> { let tsconfig = get_typescript_options(project_path.clone()).await?; - let is_emotion_enabled = config.styles().await?.emotion.is_some(); + let react_config = config.react().await?; - // [NOTE]: ref: WEB-901 - // next.js does not allow to overriding react runtime config via tsconfig / - // jsconfig, it forces overrides into automatic runtime instead. - // [TODO]: we need to emit / validate config message like next.js devserver does let react_transform_options = JsxTransformOptions { development: mode.await?.is_react_development(), // https://github.com/vercel/next.js/blob/3dc2c1c7f8441cdee31da9f7e0986d654c7fd2e7/packages/next/src/build/swc/options.ts#L112 @@ -137,7 +133,7 @@ pub async fn get_jsx_transform_options( } else { None }, - runtime: Some("automatic".into()), + runtime: react_config.runtime.clone().or(Some("automatic".into())), react_refresh: enable_react_refresh, }; diff --git a/crates/pack-tests/tests/snapshot/basic/foreign_jsx_transform/config.json b/crates/pack-tests/tests/snapshot/basic/foreign_jsx_transform/config.json index 675f949692..7face3a7db 100644 --- a/crates/pack-tests/tests/snapshot/basic/foreign_jsx_transform/config.json +++ b/crates/pack-tests/tests/snapshot/basic/foreign_jsx_transform/config.json @@ -5,6 +5,9 @@ "import": "input/index.js", "name": "main" } - ] + ], + "react": { + "runtime": "classic" + } } } \ No newline at end of file diff --git a/crates/pack-tests/tests/snapshot/basic/foreign_jsx_transform/issues/Ecmascript-file-had-an-error-df4108.txt b/crates/pack-tests/tests/snapshot/basic/foreign_jsx_transform/issues/Ecmascript-file-had-an-error-df4108.txt deleted file mode 100644 index 91234d3ca6..0000000000 --- a/crates/pack-tests/tests/snapshot/basic/foreign_jsx_transform/issues/Ecmascript-file-had-an-error-df4108.txt +++ /dev/null @@ -1,13 +0,0 @@ -error - [analysis] /basic/foreign_jsx_transform/node_modules/foreign-jsx-transform/index.js:1:0 Ecmascript file had an error - + v-------------v - 1 + /** @jsx jsx */ - + ^-------------^ - 2 | var a = 1; - 3 | export default a; - - pragma cannot be set when runtime is automatic - - Import trace: - Browser: - ./basic/foreign_jsx_transform/node_modules/foreign-jsx-transform/index.js - ./basic/foreign_jsx_transform/input/index.js \ No newline at end of file