Skip to content

Commit

Permalink
Turbopack: Allow client components from foreign code in app routes (#…
Browse files Browse the repository at this point in the history
…64751)

This extends #64520 to cover cases where client components originate
from node_modules (foreign code).

Test Plan: Extended the integration test to cover this

Closes #64412
Fixes PACK-3014

---------

Co-authored-by: OJ Kwon <[email protected]>
  • Loading branch information
2 people authored and lubieowoce committed Sep 3, 2024
1 parent 6473113 commit 2c80812
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 27 deletions.
11 changes: 2 additions & 9 deletions packages/next-swc/crates/next-core/src/next_edge/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,8 @@ pub async fn get_edge_resolve_options_context(
.map(ToString::to_string),
);

match ty {
ServerContextType::AppRSC { .. } => custom_conditions.push("react-server".to_string()),
ServerContextType::AppRoute { .. }
| ServerContextType::Pages { .. }
| ServerContextType::PagesData { .. }
| ServerContextType::PagesApi { .. }
| ServerContextType::AppSSR { .. }
| ServerContextType::Middleware { .. }
| ServerContextType::Instrumentation { .. } => {}
if ty.supports_react_server() {
custom_conditions.push("react-server".to_string());
};

let resolve_options_context = ResolveOptionsContext {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-swc/crates/next-core/src/next_import_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ async fn rsc_aliases(
}

if runtime == NextRuntime::Edge {
if matches!(ty, ServerContextType::AppRSC { .. }) {
if ty.supports_react_server() {
alias["react"] = format!("next/dist/compiled/react{react_channel}/react.react-server");
alias["react-dom"] =
format!("next/dist/compiled/react-dom{react_channel}/react-dom.react-server");
Expand Down
41 changes: 24 additions & 17 deletions packages/next-swc/crates/next-core/src/next_server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ pub enum ServerContextType {
Instrumentation,
}

impl ServerContextType {
pub fn supports_react_server(&self) -> bool {
matches!(
self,
ServerContextType::AppRSC { .. }
| ServerContextType::AppRoute { .. }
| ServerContextType::PagesApi { .. }
)
}
}

#[turbo_tasks::function]
pub async fn get_server_resolve_options_context(
project_path: Vc<FileSystemPath>,
Expand Down Expand Up @@ -152,18 +163,10 @@ pub async fn get_server_resolve_options_context(
.map(ToString::to_string),
);

match ty {
ServerContextType::AppRSC { .. }
| ServerContextType::AppRoute { .. }
| ServerContextType::PagesApi { .. }
| ServerContextType::Middleware { .. } => {
custom_conditions.push("react-server".to_string())
}
ServerContextType::Pages { .. }
| ServerContextType::PagesData { .. }
| ServerContextType::AppSSR { .. }
| ServerContextType::Instrumentation { .. } => {}
if ty.supports_react_server() {
custom_conditions.push("react-server".to_string());
};

let external_cjs_modules_plugin = ExternalCjsModulesResolvePlugin::new(
project_path,
project_path.root(),
Expand Down Expand Up @@ -325,7 +328,7 @@ pub async fn get_server_module_options_context(
let mut foreign_next_server_rules =
get_next_server_transforms_rules(next_config, ty.into_value(), mode, true, next_runtime)
.await?;
let internal_custom_rules =
let mut internal_custom_rules =
get_next_server_internal_transforms_rules(ty.into_value(), *next_config.mdx_rs().await?)
.await?;

Expand Down Expand Up @@ -622,10 +625,16 @@ pub async fn get_server_module_options_context(
ecmascript_client_reference_transition_name,
} => {
next_server_rules.extend(source_transform_rules);

let mut common_next_server_rules = vec![
get_next_react_server_components_transform_rule(next_config, true, Some(app_dir))
.await?,
];

if let Some(ecmascript_client_reference_transition_name) =
ecmascript_client_reference_transition_name
{
next_server_rules.push(get_ecma_transform_rule(
common_next_server_rules.push(get_ecma_transform_rule(
Box::new(ClientDirectiveTransformer::new(
ecmascript_client_reference_transition_name,
)),
Expand All @@ -634,10 +643,8 @@ pub async fn get_server_module_options_context(
));
}

next_server_rules.push(
get_next_react_server_components_transform_rule(next_config, true, Some(app_dir))
.await?,
);
next_server_rules.extend(common_next_server_rules.iter().cloned());
internal_custom_rules.extend(common_next_server_rules);

let module_options_context = ModuleOptionsContext {
esm_url_rewrite_behavior: Some(UrlRewriteBehavior::Full),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe('referencing a client component in an app route', () => {
it('responds without error', async () => {
expect(JSON.parse(await next.render('/runtime'))).toEqual({
clientComponent: 'function',
myModuleClientComponent: 'function',
})
})
})
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { NextResponse } from 'next/server'
import { ClientComponent } from '../../ClientComponent'
import { MyModuleClientComponent } from 'my-module/MyModuleClientComponent'

export function GET() {
return NextResponse.json({
clientComponent: typeof ClientComponent,
myModuleClientComponent: typeof MyModuleClientComponent,
})
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2c80812

Please sign in to comment.