1use std::collections::BTreeSet;
2
3use anyhow::{Result, bail};
4use serde::{Deserialize, Serialize};
5use turbo_rcstr::{RcStr, rcstr};
6use turbo_tasks::{ResolvedVc, TaskInput, Vc, trace::TraceRawVcs};
7use turbo_tasks_fs::FileSystemPath;
8use turbopack::{
9 css::chunk::CssChunkType,
10 module_options::{
11 CssOptionsContext, EcmascriptOptionsContext, ExternalsTracingOptions, JsxTransformOptions,
12 ModuleOptionsContext, ModuleRule, TypeofWindow, TypescriptTransformOptions,
13 },
14 resolve_options_context::ResolveOptionsContext,
15 transition::Transition,
16};
17use turbopack_core::{
18 chunk::{
19 ChunkingConfig, MangleType, MinifyType, SourceMapsType,
20 module_id_strategies::ModuleIdStrategy,
21 },
22 compile_time_defines,
23 compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReferences},
24 environment::{
25 Environment, ExecutionEnvironment, NodeJsEnvironment, NodeJsVersion, RuntimeVersions,
26 },
27 free_var_references,
28 module_graph::export_usage::OptionExportUsageInfo,
29 target::CompileTarget,
30};
31use turbopack_ecmascript::{chunk::EcmascriptChunkType, references::esm::UrlRewriteBehavior};
32use turbopack_ecmascript_plugins::transform::directives::{
33 client::ClientDirectiveTransformer, client_disallowed::ClientDisallowedDirectiveTransformer,
34};
35use turbopack_node::{
36 execution_context::ExecutionContext,
37 transforms::postcss::{PostCssConfigLocation, PostCssTransformOptions},
38};
39use turbopack_nodejs::NodeJsChunkingContext;
40
41use super::{
42 resolve::ExternalCjsModulesResolvePlugin,
43 transforms::{get_next_server_internal_transforms_rules, get_next_server_transforms_rules},
44};
45use crate::{
46 app_structure::CollectedRootParams,
47 mode::NextMode,
48 next_build::get_postcss_package_mapping,
49 next_client::RuntimeEntries,
50 next_config::NextConfig,
51 next_font::local::NextFontLocalResolvePlugin,
52 next_import_map::{get_next_edge_and_server_fallback_import_map, get_next_server_import_map},
53 next_server::resolve::ExternalPredicate,
54 next_shared::{
55 resolve::{
56 ModuleFeatureReportResolvePlugin, NextExternalResolvePlugin,
57 NextNodeSharedRuntimeResolvePlugin, get_invalid_client_only_resolve_plugin,
58 get_invalid_styled_jsx_resolve_plugin,
59 },
60 transforms::{
61 EcmascriptTransformStage, emotion::get_emotion_transform_rule, get_ecma_transform_rule,
62 next_react_server_components::get_next_react_server_components_transform_rule,
63 react_remove_properties::get_react_remove_properties_transform_rule,
64 relay::get_relay_transform_rule, remove_console::get_remove_console_transform_rule,
65 styled_components::get_styled_components_transform_rule,
66 styled_jsx::get_styled_jsx_transform_rule,
67 swc_ecma_transform_plugins::get_swc_ecma_transform_plugin_rule,
68 },
69 webpack_rules::{WebpackLoaderBuiltinCondition, webpack_loader_options},
70 },
71 transform_options::{
72 get_decorators_transform_options, get_jsx_transform_options,
73 get_typescript_transform_options,
74 },
75 util::{
76 NextRuntime, OptionEnvMap, defines, foreign_code_context_condition,
77 get_transpiled_packages, internal_assets_conditions, load_next_js_templateon,
78 module_styles_rule_condition,
79 },
80};
81
82#[turbo_tasks::value(shared)]
83#[derive(Debug, Clone, Hash, TaskInput)]
84pub enum ServerContextType {
85 Pages {
86 pages_dir: FileSystemPath,
87 },
88 PagesApi {
89 pages_dir: FileSystemPath,
90 },
91 PagesData {
92 pages_dir: FileSystemPath,
93 },
94 AppSSR {
95 app_dir: FileSystemPath,
96 },
97 AppRSC {
98 app_dir: FileSystemPath,
99 ecmascript_client_reference_transition_name: Option<RcStr>,
100 client_transition: Option<ResolvedVc<Box<dyn Transition>>>,
101 },
102 AppRoute {
103 app_dir: FileSystemPath,
104 ecmascript_client_reference_transition_name: Option<RcStr>,
105 },
106 Middleware {
107 app_dir: Option<FileSystemPath>,
108 ecmascript_client_reference_transition_name: Option<RcStr>,
109 },
110 Instrumentation {
111 app_dir: Option<FileSystemPath>,
112 ecmascript_client_reference_transition_name: Option<RcStr>,
113 },
114}
115
116impl ServerContextType {
117 pub fn should_use_react_server_condition(&self) -> bool {
118 matches!(
119 self,
120 ServerContextType::AppRSC { .. }
121 | ServerContextType::AppRoute { .. }
122 | ServerContextType::Middleware { .. }
123 | ServerContextType::Instrumentation { .. }
124 )
125 }
126}
127
128#[turbo_tasks::function]
129pub async fn get_server_resolve_options_context(
130 project_path: FileSystemPath,
131 ty: ServerContextType,
132 mode: Vc<NextMode>,
133 next_config: Vc<NextConfig>,
134 execution_context: Vc<ExecutionContext>,
135 collected_root_params: Option<Vc<CollectedRootParams>>,
136) -> Result<Vc<ResolveOptionsContext>> {
137 let next_server_import_map = get_next_server_import_map(
138 project_path.clone(),
139 ty.clone(),
140 next_config,
141 mode,
142 execution_context,
143 collected_root_params,
144 )
145 .to_resolved()
146 .await?;
147 let next_server_fallback_import_map =
148 get_next_edge_and_server_fallback_import_map(project_path.clone(), NextRuntime::NodeJs)
149 .to_resolved()
150 .await?;
151
152 let foreign_code_context_condition =
153 foreign_code_context_condition(next_config, project_path.clone()).await?;
154 let root_dir = project_path.root().owned().await?;
155 let module_feature_report_resolve_plugin =
156 ModuleFeatureReportResolvePlugin::new(project_path.clone())
157 .to_resolved()
158 .await?;
159 let invalid_client_only_resolve_plugin =
160 get_invalid_client_only_resolve_plugin(project_path.clone())
161 .to_resolved()
162 .await?;
163 let invalid_styled_jsx_client_only_resolve_plugin =
164 get_invalid_styled_jsx_resolve_plugin(project_path.clone())
165 .to_resolved()
166 .await?;
167
168 let mut external_packages: Vec<RcStr> = load_next_js_templateon(
170 project_path.clone(),
171 rcstr!("dist/lib/server-external-packages.json"),
172 )
173 .await?;
174
175 let mut transpiled_packages = get_transpiled_packages(next_config, project_path.clone())
176 .owned()
177 .await?;
178
179 transpiled_packages.extend(
180 (*next_config.optimize_package_imports().await?)
181 .iter()
182 .cloned(),
183 );
184
185 let server_external_packages = &*next_config.server_external_packages().await?;
186
187 let conflicting_packages = transpiled_packages
188 .iter()
189 .filter(|package| server_external_packages.contains(package))
190 .collect::<Vec<_>>();
191
192 if !conflicting_packages.is_empty() {
193 bail!(
194 "The packages specified in the 'transpilePackages' conflict with the \
195 'serverExternalPackages': {:?}",
196 conflicting_packages
197 );
198 }
199
200 external_packages.extend(server_external_packages.iter().cloned());
202
203 external_packages.retain(|item| !transpiled_packages.contains(item));
204
205 let server_external_packages_plugin = ExternalCjsModulesResolvePlugin::new(
206 project_path.clone(),
207 project_path.root().owned().await?,
208 ExternalPredicate::Only(ResolvedVc::cell(external_packages)).cell(),
209 *next_config.import_externals().await?,
210 )
211 .to_resolved()
212 .await?;
213
214 let mut custom_conditions: Vec<_> = mode.await?.custom_resolve_conditions().collect();
215 custom_conditions.extend(NextRuntime::NodeJs.custom_resolve_conditions());
216
217 if ty.should_use_react_server_condition() {
218 custom_conditions.push(rcstr!("react-server"));
219 };
220
221 let external_cjs_modules_plugin = if *next_config.bundle_pages_router_dependencies().await? {
222 server_external_packages_plugin
223 } else {
224 ExternalCjsModulesResolvePlugin::new(
225 project_path.clone(),
226 project_path.root().owned().await?,
227 ExternalPredicate::AllExcept(ResolvedVc::cell(transpiled_packages)).cell(),
228 *next_config.import_externals().await?,
229 )
230 .to_resolved()
231 .await?
232 };
233
234 let next_external_plugin = NextExternalResolvePlugin::new(project_path.clone())
235 .to_resolved()
236 .await?;
237 let next_node_shared_runtime_plugin =
238 NextNodeSharedRuntimeResolvePlugin::new(project_path.clone(), ty.clone())
239 .to_resolved()
240 .await?;
241
242 let mut before_resolve_plugins = match &ty {
243 ServerContextType::Pages { .. }
244 | ServerContextType::AppSSR { .. }
245 | ServerContextType::AppRSC { .. } => {
246 vec![
247 ResolvedVc::upcast(
248 NextFontLocalResolvePlugin::new(project_path.clone())
249 .to_resolved()
250 .await?,
251 ),
252 ResolvedVc::upcast(module_feature_report_resolve_plugin),
253 ]
254 }
255 ServerContextType::PagesData { .. }
256 | ServerContextType::PagesApi { .. }
257 | ServerContextType::AppRoute { .. }
258 | ServerContextType::Middleware { .. }
259 | ServerContextType::Instrumentation { .. } => {
260 vec![ResolvedVc::upcast(module_feature_report_resolve_plugin)]
261 }
262 };
263
264 let after_resolve_plugins = match ty {
265 ServerContextType::Pages { .. }
266 | ServerContextType::PagesApi { .. }
267 | ServerContextType::PagesData { .. } => {
268 vec![
269 ResolvedVc::upcast(next_node_shared_runtime_plugin),
270 ResolvedVc::upcast(external_cjs_modules_plugin),
271 ResolvedVc::upcast(next_external_plugin),
272 ]
273 }
274 ServerContextType::AppSSR { .. }
275 | ServerContextType::AppRSC { .. }
276 | ServerContextType::AppRoute { .. } => {
277 vec![
278 ResolvedVc::upcast(next_node_shared_runtime_plugin),
279 ResolvedVc::upcast(server_external_packages_plugin),
280 ResolvedVc::upcast(next_external_plugin),
281 ]
282 }
283 ServerContextType::Middleware { .. } | ServerContextType::Instrumentation { .. } => {
284 vec![
285 ResolvedVc::upcast(next_node_shared_runtime_plugin),
286 ResolvedVc::upcast(server_external_packages_plugin),
287 ResolvedVc::upcast(next_external_plugin),
288 ]
289 }
290 };
291
292 match ty {
300 ServerContextType::Pages { .. } | ServerContextType::PagesApi { .. } => {
301 }
303 ServerContextType::PagesData { .. }
304 | ServerContextType::AppRSC { .. }
305 | ServerContextType::AppRoute { .. }
306 | ServerContextType::Middleware { .. }
307 | ServerContextType::Instrumentation { .. } => {
308 before_resolve_plugins.push(ResolvedVc::upcast(invalid_client_only_resolve_plugin));
309 before_resolve_plugins.push(ResolvedVc::upcast(
310 invalid_styled_jsx_client_only_resolve_plugin,
311 ));
312 }
313 ServerContextType::AppSSR { .. } => {
314 }
317 }
318
319 let resolve_options_context = ResolveOptionsContext {
320 enable_node_modules: Some(root_dir.clone()),
321 enable_node_externals: true,
322 enable_node_native_modules: true,
323 module: true,
324 custom_conditions,
325 import_map: Some(next_server_import_map),
326 fallback_import_map: Some(next_server_fallback_import_map),
327 before_resolve_plugins,
328 after_resolve_plugins,
329 ..Default::default()
330 };
331
332 Ok(ResolveOptionsContext {
333 enable_typescript: true,
334 enable_react: true,
335 enable_mjs_extension: true,
336 custom_extensions: next_config.resolve_extension().owned().await?,
337 tsconfig_path: next_config
338 .typescript_tsconfig_path()
339 .await?
340 .as_ref()
341 .map(|p| project_path.join(p))
342 .transpose()?,
343 rules: vec![(
344 foreign_code_context_condition,
345 resolve_options_context.clone().resolved_cell(),
346 )],
347 ..resolve_options_context
348 }
349 .cell())
350}
351
352#[turbo_tasks::function]
353async fn next_server_defines(define_env: Vc<OptionEnvMap>) -> Result<Vc<CompileTimeDefines>> {
354 Ok(defines(&*define_env.await?).cell())
355}
356
357#[turbo_tasks::function]
358async fn next_server_free_vars(define_env: Vc<OptionEnvMap>) -> Result<Vc<FreeVarReferences>> {
359 Ok(free_var_references!(..defines(&*define_env.await?).into_iter()).cell())
360}
361
362#[turbo_tasks::function]
363pub async fn get_server_compile_time_info(
364 cwd: RcStr,
365 define_env: Vc<OptionEnvMap>,
366 node_version: ResolvedVc<NodeJsVersion>,
367) -> Result<Vc<CompileTimeInfo>> {
368 CompileTimeInfo::builder(
369 Environment::new(ExecutionEnvironment::NodeJsLambda(
370 NodeJsEnvironment {
371 compile_target: CompileTarget::current().to_resolved().await?,
372 node_version,
373 cwd: ResolvedVc::cell(Some(cwd)),
374 }
375 .resolved_cell(),
376 ))
377 .to_resolved()
378 .await?,
379 )
380 .defines(next_server_defines(define_env).to_resolved().await?)
381 .free_var_references(next_server_free_vars(define_env).to_resolved().await?)
382 .cell()
383 .await
384}
385
386#[turbo_tasks::function]
387pub async fn get_tracing_compile_time_info() -> Result<Vc<CompileTimeInfo>> {
388 CompileTimeInfo::builder(
389 Environment::new(ExecutionEnvironment::NodeJsLambda(
390 NodeJsEnvironment::default().resolved_cell(),
391 ))
392 .to_resolved()
393 .await?,
394 )
395 .defines(
419 compile_time_defines!(
420 process.env.TURBOPACK = true,
421 )
423 .resolved_cell(),
424 )
425 .cell()
426 .await
427}
428
429#[turbo_tasks::function]
430pub async fn get_server_module_options_context(
431 project_path: FileSystemPath,
432 execution_context: ResolvedVc<ExecutionContext>,
433 ty: ServerContextType,
434 mode: Vc<NextMode>,
435 next_config: Vc<NextConfig>,
436 next_runtime: NextRuntime,
437 encryption_key: ResolvedVc<RcStr>,
438 environment: ResolvedVc<Environment>,
439) -> Result<Vc<ModuleOptionsContext>> {
440 let next_mode = mode.await?;
441 let mut next_server_rules = get_next_server_transforms_rules(
442 next_config,
443 ty.clone(),
444 mode,
445 false,
446 next_runtime,
447 encryption_key,
448 )
449 .await?;
450 let mut foreign_next_server_rules = get_next_server_transforms_rules(
451 next_config,
452 ty.clone(),
453 mode,
454 true,
455 next_runtime,
456 encryption_key,
457 )
458 .await?;
459 let mut internal_custom_rules = get_next_server_internal_transforms_rules(
460 ty.clone(),
461 next_config.mdx_rs().await?.is_some(),
462 )
463 .await?;
464
465 let foreign_code_context_condition =
466 foreign_code_context_condition(next_config, project_path.clone()).await?;
467 let postcss_transform_options = PostCssTransformOptions {
468 postcss_package: Some(
469 get_postcss_package_mapping(project_path.clone())
470 .to_resolved()
471 .await?,
472 ),
473 config_location: PostCssConfigLocation::ProjectPathOrLocalPath,
474 ..Default::default()
475 };
476 let postcss_foreign_transform_options = PostCssTransformOptions {
477 config_location: PostCssConfigLocation::ProjectPath,
481 ..postcss_transform_options.clone()
482 };
483 let enable_postcss_transform = Some(postcss_transform_options.resolved_cell());
484 let enable_foreign_postcss_transform = Some(postcss_foreign_transform_options.resolved_cell());
485
486 let mut loader_conditions = BTreeSet::new();
487 loader_conditions.extend(mode.await?.webpack_loader_conditions());
488 loader_conditions.extend(next_runtime.webpack_loader_conditions());
489
490 let mut foreign_conditions = loader_conditions.clone();
494 foreign_conditions.insert(WebpackLoaderBuiltinCondition::Foreign);
495 let foreign_enable_webpack_loaders =
496 *webpack_loader_options(project_path.clone(), next_config, foreign_conditions).await?;
497
498 let enable_webpack_loaders =
500 *webpack_loader_options(project_path.clone(), next_config, loader_conditions).await?;
501
502 let tree_shaking_mode_for_user_code = *next_config
503 .tree_shaking_mode_for_user_code(next_mode.is_development())
504 .await?;
505 let tree_shaking_mode_for_foreign_code = *next_config
506 .tree_shaking_mode_for_foreign_code(next_mode.is_development())
507 .await?;
508 let versions = RuntimeVersions(Default::default()).cell();
509
510 let tsconfig = get_typescript_transform_options(project_path.clone())
512 .to_resolved()
513 .await?;
514 let decorators_options = get_decorators_transform_options(project_path.clone());
515 let enable_mdx_rs = *next_config.mdx_rs().await?;
516
517 let jsx_runtime_options =
525 get_jsx_transform_options(project_path.clone(), mode, None, false, next_config)
526 .to_resolved()
527 .await?;
528 let rsc_jsx_runtime_options =
529 get_jsx_transform_options(project_path.clone(), mode, None, true, next_config)
530 .to_resolved()
531 .await?;
532
533 let source_transform_rules: Vec<ModuleRule> = vec![
535 get_swc_ecma_transform_plugin_rule(next_config, project_path.clone()).await?,
536 get_relay_transform_rule(next_config, project_path.clone()).await?,
537 get_emotion_transform_rule(next_config).await?,
538 get_react_remove_properties_transform_rule(next_config).await?,
539 get_remove_console_transform_rule(next_config).await?,
540 ]
541 .into_iter()
542 .flatten()
543 .collect();
544
545 let styled_components_transform_rule =
548 get_styled_components_transform_rule(next_config).await?;
549 let styled_jsx_transform_rule = get_styled_jsx_transform_rule(next_config, versions).await?;
550
551 let source_maps = if *next_config.server_source_maps().await? {
552 SourceMapsType::Full
553 } else {
554 SourceMapsType::None
555 };
556 let module_options_context = ModuleOptionsContext {
557 ecmascript: EcmascriptOptionsContext {
558 enable_typeof_window_inlining: Some(TypeofWindow::Undefined),
559 import_externals: *next_config.import_externals().await?,
560 ignore_dynamic_requests: true,
561 source_maps,
562 ..Default::default()
563 },
564 execution_context: Some(execution_context),
565 environment: Some(environment),
566 css: CssOptionsContext {
567 source_maps,
568 module_css_condition: Some(module_styles_rule_condition()),
569 ..Default::default()
570 },
571 tree_shaking_mode: tree_shaking_mode_for_user_code,
572 side_effect_free_packages: next_config.optimize_package_imports().owned().await?,
573 enable_externals_tracing: if next_mode.is_production() {
574 Some(
575 ExternalsTracingOptions {
576 tracing_root: project_path,
577 compile_time_info: get_tracing_compile_time_info().to_resolved().await?,
578 }
579 .resolved_cell(),
580 )
581 } else {
582 None
583 },
584 keep_last_successful_parse: next_mode.is_development(),
585
586 ..Default::default()
587 };
588
589 let module_options_context = match ty {
590 ServerContextType::Pages { .. }
591 | ServerContextType::PagesData { .. }
592 | ServerContextType::PagesApi { .. } => {
593 let mut custom_source_transform_rules: Vec<ModuleRule> =
594 vec![styled_components_transform_rule, styled_jsx_transform_rule]
595 .into_iter()
596 .flatten()
597 .collect();
598
599 if let ServerContextType::Pages { .. } = ty {
600 custom_source_transform_rules.push(
601 get_next_react_server_components_transform_rule(next_config, false, None)
602 .await?,
603 );
604 }
605
606 next_server_rules.extend(custom_source_transform_rules.iter().cloned());
607 next_server_rules.extend(source_transform_rules);
608
609 foreign_next_server_rules.extend(custom_source_transform_rules);
610 foreign_next_server_rules.extend(internal_custom_rules);
611
612 let url_rewrite_behavior = Some(
613 if let ServerContextType::PagesApi { .. } = ty {
615 UrlRewriteBehavior::Full
616 } else {
617 UrlRewriteBehavior::Relative
618 },
619 );
620
621 let module_options_context = ModuleOptionsContext {
622 ecmascript: EcmascriptOptionsContext {
623 esm_url_rewrite_behavior: url_rewrite_behavior,
624 ..module_options_context.ecmascript
625 },
626 ..module_options_context
627 };
628
629 let foreign_code_module_options_context = ModuleOptionsContext {
630 module_rules: foreign_next_server_rules.clone(),
631 enable_webpack_loaders: foreign_enable_webpack_loaders,
632 enable_postcss_transform: enable_foreign_postcss_transform,
634 tree_shaking_mode: tree_shaking_mode_for_foreign_code,
635 ..module_options_context.clone()
636 };
637
638 let internal_module_options_context = ModuleOptionsContext {
639 ecmascript: EcmascriptOptionsContext {
640 enable_typescript_transform: Some(
641 TypescriptTransformOptions::default().resolved_cell(),
642 ),
643 enable_jsx: Some(JsxTransformOptions::default().resolved_cell()),
644 ..module_options_context.ecmascript.clone()
645 },
646 module_rules: foreign_next_server_rules,
647 ..module_options_context.clone()
648 };
649
650 ModuleOptionsContext {
651 ecmascript: EcmascriptOptionsContext {
652 enable_jsx: Some(jsx_runtime_options),
653 enable_typescript_transform: Some(tsconfig),
654 enable_decorators: Some(decorators_options.to_resolved().await?),
655 ..module_options_context.ecmascript
656 },
657 enable_webpack_loaders,
658 enable_postcss_transform,
659 enable_mdx_rs,
660 rules: vec![
661 (
662 foreign_code_context_condition,
663 foreign_code_module_options_context.resolved_cell(),
664 ),
665 (
666 internal_assets_conditions().await?,
667 internal_module_options_context.resolved_cell(),
668 ),
669 ],
670 module_rules: next_server_rules,
671 ..module_options_context
672 }
673 }
674 ServerContextType::AppSSR { app_dir, .. } => {
675 let mut custom_source_transform_rules: Vec<ModuleRule> =
676 vec![styled_components_transform_rule, styled_jsx_transform_rule]
677 .into_iter()
678 .flatten()
679 .collect();
680
681 foreign_next_server_rules.extend(custom_source_transform_rules.iter().cloned());
682 foreign_next_server_rules.extend(internal_custom_rules);
683
684 custom_source_transform_rules.push(
685 get_next_react_server_components_transform_rule(next_config, false, Some(app_dir))
686 .await?,
687 );
688
689 next_server_rules.extend(custom_source_transform_rules.clone());
690 next_server_rules.extend(source_transform_rules);
691
692 let foreign_code_module_options_context = ModuleOptionsContext {
693 module_rules: foreign_next_server_rules.clone(),
694 enable_webpack_loaders: foreign_enable_webpack_loaders,
695 enable_postcss_transform: enable_foreign_postcss_transform,
697 tree_shaking_mode: tree_shaking_mode_for_foreign_code,
698 ..module_options_context.clone()
699 };
700 let internal_module_options_context = ModuleOptionsContext {
701 ecmascript: EcmascriptOptionsContext {
702 enable_typescript_transform: Some(
703 TypescriptTransformOptions::default().resolved_cell(),
704 ),
705 ..module_options_context.ecmascript.clone()
706 },
707 module_rules: foreign_next_server_rules,
708 ..module_options_context.clone()
709 };
710
711 ModuleOptionsContext {
712 ecmascript: EcmascriptOptionsContext {
713 enable_jsx: Some(jsx_runtime_options),
714 enable_typescript_transform: Some(tsconfig),
715 enable_decorators: Some(decorators_options.to_resolved().await?),
716 ..module_options_context.ecmascript
717 },
718 enable_webpack_loaders,
719 enable_postcss_transform,
720 enable_mdx_rs,
721 rules: vec![
722 (
723 foreign_code_context_condition,
724 foreign_code_module_options_context.resolved_cell(),
725 ),
726 (
727 internal_assets_conditions().await?,
728 internal_module_options_context.resolved_cell(),
729 ),
730 ],
731 module_rules: next_server_rules,
732 ..module_options_context
733 }
734 }
735 ServerContextType::AppRSC {
736 app_dir,
737 ecmascript_client_reference_transition_name,
738 ..
739 } => {
740 let mut custom_source_transform_rules: Vec<ModuleRule> =
741 vec![styled_components_transform_rule, styled_jsx_transform_rule]
742 .into_iter()
743 .flatten()
744 .collect();
745
746 if let Some(ecmascript_client_reference_transition_name) =
747 ecmascript_client_reference_transition_name
748 {
749 custom_source_transform_rules.push(get_ecma_transform_rule(
750 Box::new(ClientDirectiveTransformer::new(
751 ecmascript_client_reference_transition_name,
752 )),
753 enable_mdx_rs.is_some(),
754 EcmascriptTransformStage::Preprocess,
755 ));
756 }
757
758 foreign_next_server_rules.extend(custom_source_transform_rules.iter().cloned());
759 foreign_next_server_rules.extend(internal_custom_rules);
760
761 custom_source_transform_rules.push(
762 get_next_react_server_components_transform_rule(next_config, true, Some(app_dir))
763 .await?,
764 );
765
766 next_server_rules.extend(custom_source_transform_rules.clone());
767 next_server_rules.extend(source_transform_rules);
768
769 let foreign_code_module_options_context = ModuleOptionsContext {
770 module_rules: foreign_next_server_rules.clone(),
771 enable_webpack_loaders: foreign_enable_webpack_loaders,
772 enable_postcss_transform: enable_foreign_postcss_transform,
774 tree_shaking_mode: tree_shaking_mode_for_foreign_code,
775 ..module_options_context.clone()
776 };
777 let internal_module_options_context = ModuleOptionsContext {
778 ecmascript: EcmascriptOptionsContext {
779 enable_typescript_transform: Some(
780 TypescriptTransformOptions::default().resolved_cell(),
781 ),
782 ..module_options_context.ecmascript.clone()
783 },
784 module_rules: foreign_next_server_rules,
785 ..module_options_context.clone()
786 };
787 ModuleOptionsContext {
788 ecmascript: EcmascriptOptionsContext {
789 enable_jsx: Some(rsc_jsx_runtime_options),
790 enable_typescript_transform: Some(tsconfig),
791 enable_decorators: Some(decorators_options.to_resolved().await?),
792 ..module_options_context.ecmascript
793 },
794 enable_webpack_loaders,
795 enable_postcss_transform,
796 enable_mdx_rs,
797 rules: vec![
798 (
799 foreign_code_context_condition,
800 foreign_code_module_options_context.resolved_cell(),
801 ),
802 (
803 internal_assets_conditions().await?,
804 internal_module_options_context.resolved_cell(),
805 ),
806 ],
807 module_rules: next_server_rules,
808 ..module_options_context
809 }
810 }
811 ServerContextType::AppRoute {
812 app_dir,
813 ecmascript_client_reference_transition_name,
814 } => {
815 next_server_rules.extend(source_transform_rules);
816
817 let mut common_next_server_rules = vec![
818 get_next_react_server_components_transform_rule(next_config, true, Some(app_dir))
819 .await?,
820 ];
821
822 if let Some(ecmascript_client_reference_transition_name) =
823 ecmascript_client_reference_transition_name
824 {
825 common_next_server_rules.push(get_ecma_transform_rule(
826 Box::new(ClientDirectiveTransformer::new(
827 ecmascript_client_reference_transition_name,
828 )),
829 enable_mdx_rs.is_some(),
830 EcmascriptTransformStage::Preprocess,
831 ));
832 }
833
834 next_server_rules.extend(common_next_server_rules.iter().cloned());
835 internal_custom_rules.extend(common_next_server_rules);
836
837 let module_options_context = ModuleOptionsContext {
838 ecmascript: EcmascriptOptionsContext {
839 esm_url_rewrite_behavior: Some(UrlRewriteBehavior::Full),
840 ..module_options_context.ecmascript
841 },
842 ..module_options_context
843 };
844 let foreign_code_module_options_context = ModuleOptionsContext {
845 module_rules: internal_custom_rules.clone(),
846 enable_webpack_loaders: foreign_enable_webpack_loaders,
847 enable_postcss_transform: enable_foreign_postcss_transform,
849 tree_shaking_mode: tree_shaking_mode_for_foreign_code,
850 ..module_options_context.clone()
851 };
852 let internal_module_options_context = ModuleOptionsContext {
853 ecmascript: EcmascriptOptionsContext {
854 enable_typescript_transform: Some(
855 TypescriptTransformOptions::default().resolved_cell(),
856 ),
857 ..module_options_context.ecmascript.clone()
858 },
859 module_rules: internal_custom_rules,
860 ..module_options_context.clone()
861 };
862 ModuleOptionsContext {
863 ecmascript: EcmascriptOptionsContext {
864 enable_jsx: Some(rsc_jsx_runtime_options),
865 enable_typescript_transform: Some(tsconfig),
866 enable_decorators: Some(decorators_options.to_resolved().await?),
867 ..module_options_context.ecmascript
868 },
869 enable_webpack_loaders,
870 enable_postcss_transform,
871 enable_mdx_rs,
872 rules: vec![
873 (
874 foreign_code_context_condition,
875 foreign_code_module_options_context.resolved_cell(),
876 ),
877 (
878 internal_assets_conditions().await?,
879 internal_module_options_context.resolved_cell(),
880 ),
881 ],
882 module_rules: next_server_rules,
883 ..module_options_context
884 }
885 }
886 ServerContextType::Middleware {
887 app_dir,
888 ecmascript_client_reference_transition_name,
889 }
890 | ServerContextType::Instrumentation {
891 app_dir,
892 ecmascript_client_reference_transition_name,
893 } => {
894 let mut custom_source_transform_rules: Vec<ModuleRule> =
895 vec![styled_components_transform_rule, styled_jsx_transform_rule]
896 .into_iter()
897 .flatten()
898 .collect();
899
900 if let Some(ecmascript_client_reference_transition_name) =
901 ecmascript_client_reference_transition_name
902 {
903 custom_source_transform_rules.push(get_ecma_transform_rule(
904 Box::new(ClientDirectiveTransformer::new(
905 ecmascript_client_reference_transition_name,
906 )),
907 enable_mdx_rs.is_some(),
908 EcmascriptTransformStage::Preprocess,
909 ));
910 } else {
911 custom_source_transform_rules.push(get_ecma_transform_rule(
912 Box::new(ClientDisallowedDirectiveTransformer::new(
913 "next/dist/client/use-client-disallowed.js".to_string(),
914 )),
915 enable_mdx_rs.is_some(),
916 EcmascriptTransformStage::Preprocess,
917 ));
918 }
919
920 custom_source_transform_rules.push(
921 get_next_react_server_components_transform_rule(next_config, true, app_dir).await?,
922 );
923
924 internal_custom_rules.extend(custom_source_transform_rules.iter().cloned());
925
926 next_server_rules.extend(custom_source_transform_rules);
927 next_server_rules.extend(source_transform_rules);
928
929 let module_options_context = ModuleOptionsContext {
930 ecmascript: EcmascriptOptionsContext {
931 esm_url_rewrite_behavior: Some(UrlRewriteBehavior::Full),
932 ..module_options_context.ecmascript
933 },
934 ..module_options_context
935 };
936 let foreign_code_module_options_context = ModuleOptionsContext {
937 module_rules: internal_custom_rules.clone(),
938 enable_webpack_loaders: foreign_enable_webpack_loaders,
939 enable_postcss_transform: enable_foreign_postcss_transform,
941 tree_shaking_mode: tree_shaking_mode_for_foreign_code,
942 ..module_options_context.clone()
943 };
944 let internal_module_options_context = ModuleOptionsContext {
945 ecmascript: EcmascriptOptionsContext {
946 enable_typescript_transform: Some(
947 TypescriptTransformOptions::default().resolved_cell(),
948 ),
949 ..module_options_context.ecmascript.clone()
950 },
951 module_rules: internal_custom_rules,
952 ..module_options_context.clone()
953 };
954 ModuleOptionsContext {
955 ecmascript: EcmascriptOptionsContext {
956 enable_jsx: Some(jsx_runtime_options),
957 enable_typescript_transform: Some(tsconfig),
958 enable_decorators: Some(decorators_options.to_resolved().await?),
959 ..module_options_context.ecmascript
960 },
961 enable_webpack_loaders,
962 enable_postcss_transform,
963 enable_mdx_rs,
964 rules: vec![
965 (
966 foreign_code_context_condition,
967 foreign_code_module_options_context.resolved_cell(),
968 ),
969 (
970 internal_assets_conditions().await?,
971 internal_module_options_context.resolved_cell(),
972 ),
973 ],
974 module_rules: next_server_rules,
975 ..module_options_context
976 }
977 }
978 }
979 .cell();
980
981 Ok(module_options_context)
982}
983
984#[turbo_tasks::function]
985pub fn get_server_runtime_entries(
986 _ty: ServerContextType,
987 _mode: Vc<NextMode>,
988) -> Vc<RuntimeEntries> {
989 let runtime_entries = vec![];
990 Vc::cell(runtime_entries)
991}
992
993#[derive(Clone, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Serialize, Deserialize)]
994pub struct ServerChunkingContextOptions {
995 pub mode: Vc<NextMode>,
996 pub root_path: FileSystemPath,
997 pub node_root: FileSystemPath,
998 pub node_root_to_root_path: RcStr,
999 pub environment: Vc<Environment>,
1000 pub module_id_strategy: Vc<Box<dyn ModuleIdStrategy>>,
1001 pub export_usage: Vc<OptionExportUsageInfo>,
1002 pub turbo_minify: Vc<bool>,
1003 pub turbo_source_maps: Vc<bool>,
1004 pub no_mangling: Vc<bool>,
1005 pub scope_hoisting: Vc<bool>,
1006}
1007
1008#[turbo_tasks::function]
1009pub async fn get_server_chunking_context_with_client_assets(
1010 options: ServerChunkingContextOptions,
1011 client_root: FileSystemPath,
1012 asset_prefix: Option<RcStr>,
1013) -> Result<Vc<NodeJsChunkingContext>> {
1014 let ServerChunkingContextOptions {
1015 mode,
1016 root_path,
1017 node_root,
1018 node_root_to_root_path,
1019 environment,
1020 module_id_strategy,
1021 export_usage,
1022 turbo_minify,
1023 turbo_source_maps,
1024 no_mangling,
1025 scope_hoisting,
1026 } = options;
1027
1028 let next_mode = mode.await?;
1029 let mut builder = NodeJsChunkingContext::builder(
1033 root_path,
1034 node_root.clone(),
1035 node_root_to_root_path,
1036 client_root.clone(),
1037 node_root.join("server/chunks/ssr")?,
1038 client_root.join("static/media")?,
1039 environment.to_resolved().await?,
1040 next_mode.runtime_type(),
1041 )
1042 .asset_prefix(asset_prefix)
1043 .minify_type(if *turbo_minify.await? {
1044 MinifyType::Minify {
1045 mangle: (!*no_mangling.await?).then_some(MangleType::Deterministic),
1047 }
1048 } else {
1049 MinifyType::NoMinify
1050 })
1051 .source_maps(if *turbo_source_maps.await? {
1052 SourceMapsType::Full
1053 } else {
1054 SourceMapsType::None
1055 })
1056 .module_id_strategy(module_id_strategy.to_resolved().await?)
1057 .export_usage(*export_usage.await?)
1058 .file_tracing(next_mode.is_production());
1059
1060 if next_mode.is_development() {
1061 builder = builder.use_file_source_map_uris();
1062 } else {
1063 builder = builder
1064 .chunking_config(
1065 Vc::<EcmascriptChunkType>::default().to_resolved().await?,
1066 ChunkingConfig {
1067 min_chunk_size: 20_000,
1068 max_chunk_count_per_group: 100,
1069 max_merge_chunk_size: 100_000,
1070 ..Default::default()
1071 },
1072 )
1073 .chunking_config(
1074 Vc::<CssChunkType>::default().to_resolved().await?,
1075 ChunkingConfig {
1076 max_merge_chunk_size: 100_000,
1077 ..Default::default()
1078 },
1079 )
1080 .module_merging(*scope_hoisting.await?);
1081 }
1082
1083 Ok(builder.build())
1084}
1085
1086#[turbo_tasks::function]
1087pub async fn get_server_chunking_context(
1088 options: ServerChunkingContextOptions,
1089) -> Result<Vc<NodeJsChunkingContext>> {
1090 let ServerChunkingContextOptions {
1091 mode,
1092 root_path,
1093 node_root,
1094 node_root_to_root_path,
1095 environment,
1096 module_id_strategy,
1097 export_usage,
1098 turbo_minify,
1099 turbo_source_maps,
1100 no_mangling,
1101 scope_hoisting,
1102 } = options;
1103 let next_mode = mode.await?;
1104 let mut builder = NodeJsChunkingContext::builder(
1108 root_path,
1109 node_root.clone(),
1110 node_root_to_root_path,
1111 node_root.clone(),
1112 node_root.join("server/chunks")?,
1113 node_root.join("server/assets")?,
1114 environment.to_resolved().await?,
1115 next_mode.runtime_type(),
1116 )
1117 .minify_type(if *turbo_minify.await? {
1118 MinifyType::Minify {
1119 mangle: (!*no_mangling.await?).then_some(MangleType::OptimalSize),
1120 }
1121 } else {
1122 MinifyType::NoMinify
1123 })
1124 .source_maps(if *turbo_source_maps.await? {
1125 SourceMapsType::Full
1126 } else {
1127 SourceMapsType::None
1128 })
1129 .module_id_strategy(module_id_strategy.to_resolved().await?)
1130 .export_usage(*export_usage.await?)
1131 .file_tracing(next_mode.is_production());
1132
1133 if next_mode.is_development() {
1134 builder = builder.use_file_source_map_uris()
1135 } else {
1136 builder = builder
1137 .chunking_config(
1138 Vc::<EcmascriptChunkType>::default().to_resolved().await?,
1139 ChunkingConfig {
1140 min_chunk_size: 20_000,
1141 max_chunk_count_per_group: 100,
1142 max_merge_chunk_size: 100_000,
1143 ..Default::default()
1144 },
1145 )
1146 .chunking_config(
1147 Vc::<CssChunkType>::default().to_resolved().await?,
1148 ChunkingConfig {
1149 max_merge_chunk_size: 100_000,
1150 ..Default::default()
1151 },
1152 )
1153 .module_merging(*scope_hoisting.await?);
1154 }
1155
1156 Ok(builder.build())
1157}