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