1use std::collections::BTreeMap;
2
3use anyhow::{Context, Result};
4use rustc_hash::FxHashMap;
5use turbo_rcstr::{RcStr, rcstr};
6use turbo_tasks::{FxIndexMap, ResolvedVc, Vc, fxindexmap};
7use turbo_tasks_fs::{FileSystem, FileSystemPath};
8use turbopack_core::{
9 reference_type::{CommonJsReferenceSubType, ReferenceType},
10 resolve::{
11 AliasPattern, ExternalTraced, ExternalType, ResolveAliasMap, SubpathValue,
12 node::node_cjs_resolve_options,
13 options::{ConditionValue, ImportMap, ImportMapping, ResolvedMap},
14 parse::Request,
15 pattern::Pattern,
16 resolve,
17 },
18 source::Source,
19};
20use turbopack_node::execution_context::ExecutionContext;
21
22use crate::{
23 embed_js::{VIRTUAL_PACKAGE_NAME, next_js_fs},
24 mode::NextMode,
25 next_client::context::ClientContextType,
26 next_config::NextConfig,
27 next_edge::unsupported::NextEdgeUnsupportedModuleReplacer,
28 next_font::google::{
29 GOOGLE_FONTS_INTERNAL_PREFIX, NextFontGoogleCssModuleReplacer,
30 NextFontGoogleFontFileReplacer, NextFontGoogleReplacer,
31 },
32 next_server::context::ServerContextType,
33 util::NextRuntime,
34};
35
36const EDGE_UNSUPPORTED_NODE_INTERNALS: [&str; 44] = [
43 "child_process",
44 "cluster",
45 "console",
46 "constants",
47 "crypto",
48 "dgram",
49 "diagnostics_channel",
50 "dns",
51 "dns/promises",
52 "domain",
53 "fs",
54 "fs/promises",
55 "http",
56 "http2",
57 "https",
58 "inspector",
59 "module",
60 "net",
61 "os",
62 "path",
63 "path/posix",
64 "path/win32",
65 "perf_hooks",
66 "process",
67 "punycode",
68 "querystring",
69 "readline",
70 "repl",
71 "stream",
72 "stream/promises",
73 "stream/web",
74 "string_decoder",
75 "sys",
76 "timers",
77 "timers/promises",
78 "tls",
79 "trace_events",
80 "tty",
81 "v8",
82 "vm",
83 "wasi",
84 "worker_threads",
85 "zlib",
86 "pnpapi",
87];
88
89#[turbo_tasks::function]
92pub async fn get_next_client_import_map(
93 project_path: FileSystemPath,
94 ty: ClientContextType,
95 next_config: Vc<NextConfig>,
96 next_mode: Vc<NextMode>,
97 execution_context: Vc<ExecutionContext>,
98) -> Result<Vc<ImportMap>> {
99 let mut import_map = ImportMap::empty();
100
101 insert_next_shared_aliases(
102 &mut import_map,
103 project_path.clone(),
104 execution_context,
105 next_config,
106 next_mode,
107 false,
108 )
109 .await?;
110
111 insert_optimized_module_aliases(&mut import_map, project_path.clone()).await?;
112
113 insert_alias_option(
114 &mut import_map,
115 &project_path,
116 next_config.resolve_alias_options(),
117 ["browser"],
118 )
119 .await?;
120
121 match &ty {
122 ClientContextType::Pages { .. } => {}
123 ClientContextType::App { app_dir } => {
124 let react_flavor = if *next_config.enable_ppr().await?
125 || *next_config.enable_taint().await?
126 || *next_config.enable_view_transition().await?
127 || *next_config.enable_router_bfcache().await?
128 {
129 "-experimental"
130 } else {
131 ""
132 };
133
134 import_map.insert_exact_alias(
135 "react",
136 request_to_import_mapping(
137 app_dir.clone(),
138 &format!("next/dist/compiled/react{react_flavor}"),
139 ),
140 );
141 import_map.insert_wildcard_alias(
142 "react/",
143 request_to_import_mapping(
144 app_dir.clone(),
145 &format!("next/dist/compiled/react{react_flavor}/*"),
146 ),
147 );
148 import_map.insert_exact_alias(
149 "react-dom",
150 request_to_import_mapping(
151 app_dir.clone(),
152 &format!("next/dist/compiled/react-dom{react_flavor}"),
153 ),
154 );
155 import_map.insert_exact_alias(
156 "react-dom/static",
157 request_to_import_mapping(
158 app_dir.clone(),
159 "next/dist/compiled/react-dom-experimental/static",
160 ),
161 );
162 import_map.insert_exact_alias(
163 "react-dom/static.edge",
164 request_to_import_mapping(
165 app_dir.clone(),
166 "next/dist/compiled/react-dom-experimental/static.edge",
167 ),
168 );
169 import_map.insert_exact_alias(
170 "react-dom/static.browser",
171 request_to_import_mapping(
172 app_dir.clone(),
173 "next/dist/compiled/react-dom-experimental/static.browser",
174 ),
175 );
176 let react_client_package = get_react_client_package(next_config).await?;
177 import_map.insert_exact_alias(
178 "react-dom/client",
179 request_to_import_mapping(
180 app_dir.clone(),
181 &format!("next/dist/compiled/react-dom{react_flavor}/{react_client_package}"),
182 ),
183 );
184 import_map.insert_wildcard_alias(
185 "react-dom/",
186 request_to_import_mapping(
187 app_dir.clone(),
188 &format!("next/dist/compiled/react-dom{react_flavor}/*"),
189 ),
190 );
191 import_map.insert_wildcard_alias(
192 "react-server-dom-webpack/",
193 request_to_import_mapping(app_dir.clone(), "react-server-dom-turbopack/*"),
194 );
195 import_map.insert_wildcard_alias(
196 "react-server-dom-turbopack/",
197 request_to_import_mapping(
198 app_dir.clone(),
199 &format!("next/dist/compiled/react-server-dom-turbopack{react_flavor}/*"),
200 ),
201 );
202 insert_exact_alias_or_js(
203 &mut import_map,
204 "next/head",
205 request_to_import_mapping(
206 project_path.clone(),
207 "next/dist/client/components/noop-head",
208 ),
209 );
210 insert_exact_alias_or_js(
211 &mut import_map,
212 "next/dynamic",
213 request_to_import_mapping(project_path.clone(), "next/dist/shared/lib/app-dynamic"),
214 );
215 insert_exact_alias_or_js(
216 &mut import_map,
217 "next/link",
218 request_to_import_mapping(project_path.clone(), "next/dist/client/app-dir/link"),
219 );
220 insert_exact_alias_or_js(
221 &mut import_map,
222 "next/form",
223 request_to_import_mapping(project_path.clone(), "next/dist/client/app-dir/form"),
224 );
225 }
226 ClientContextType::Fallback => {}
227 ClientContextType::Other => {}
228 }
229
230 insert_exact_alias_map(
232 &mut import_map,
233 project_path.clone(),
234 fxindexmap! {
235 "server-only" => "next/dist/compiled/server-only/index".to_string(),
236 "client-only" => "next/dist/compiled/client-only/index".to_string(),
237 "next/dist/compiled/server-only" => "next/dist/compiled/server-only/index".to_string(),
238 "next/dist/compiled/client-only" => "next/dist/compiled/client-only/index".to_string(),
239 },
240 );
241
242 match ty {
243 ClientContextType::Pages { .. }
244 | ClientContextType::App { .. }
245 | ClientContextType::Fallback => {
246 for (original, alias) in NEXT_ALIASES {
247 import_map.insert_exact_alias(
248 format!("node:{original}"),
249 request_to_import_mapping(project_path.clone(), alias),
250 );
251 }
252 }
253 ClientContextType::Other => {}
254 }
255
256 insert_turbopack_dev_alias(&mut import_map).await?;
257 insert_instrumentation_client_alias(&mut import_map, project_path).await?;
258
259 Ok(import_map.cell())
260}
261
262#[turbo_tasks::function]
265pub async fn get_next_client_fallback_import_map(ty: ClientContextType) -> Result<Vc<ImportMap>> {
266 let mut import_map = ImportMap::empty();
267
268 match ty {
269 ClientContextType::Pages {
270 pages_dir: context_dir,
271 }
272 | ClientContextType::App {
273 app_dir: context_dir,
274 } => {
275 for (original, alias) in NEXT_ALIASES {
276 import_map.insert_exact_alias(
277 original,
278 request_to_import_mapping(context_dir.clone(), alias),
279 );
280 }
281 }
282 ClientContextType::Fallback => {}
283 ClientContextType::Other => {}
284 }
285
286 insert_turbopack_dev_alias(&mut import_map).await?;
287
288 Ok(import_map.cell())
289}
290
291#[turbo_tasks::function]
293pub async fn get_next_server_import_map(
294 project_path: FileSystemPath,
295 ty: ServerContextType,
296 next_config: Vc<NextConfig>,
297 next_mode: Vc<NextMode>,
298 execution_context: Vc<ExecutionContext>,
299) -> Result<Vc<ImportMap>> {
300 let mut import_map = ImportMap::empty();
301
302 insert_next_shared_aliases(
303 &mut import_map,
304 project_path.clone(),
305 execution_context,
306 next_config,
307 next_mode,
308 false,
309 )
310 .await?;
311
312 insert_alias_option(
313 &mut import_map,
314 &project_path,
315 next_config.resolve_alias_options(),
316 [],
317 )
318 .await?;
319
320 let external = ImportMapping::External(None, ExternalType::CommonJs, ExternalTraced::Traced)
321 .resolved_cell();
322
323 import_map.insert_exact_alias("next/dist/server/require-hook", external);
324 match ty {
325 ServerContextType::Pages { .. }
326 | ServerContextType::PagesData { .. }
327 | ServerContextType::PagesApi { .. } => {
328 import_map.insert_exact_alias("react", external);
329 import_map.insert_wildcard_alias("react/", external);
330 import_map.insert_exact_alias("react-dom", external);
331 import_map.insert_exact_alias("react-dom/client", external);
332 import_map.insert_wildcard_alias("react-dom/", external);
333 import_map.insert_exact_alias("styled-jsx", external);
334 import_map.insert_exact_alias(
335 "styled-jsx/style",
336 ImportMapping::External(
337 Some(rcstr!("styled-jsx/style.js")),
338 ExternalType::CommonJs,
339 ExternalTraced::Traced,
340 )
341 .resolved_cell(),
342 );
343 import_map.insert_wildcard_alias("styled-jsx/", external);
344 import_map.insert_wildcard_alias("next/dist/build/utils", external);
346 }
347 ServerContextType::AppSSR { .. }
348 | ServerContextType::AppRSC { .. }
349 | ServerContextType::AppRoute { .. } => {
350 insert_exact_alias_or_js(
351 &mut import_map,
352 "next/head",
353 request_to_import_mapping(
354 project_path.clone(),
355 "next/dist/client/components/noop-head",
356 ),
357 );
358 insert_exact_alias_or_js(
359 &mut import_map,
360 "next/dynamic",
361 request_to_import_mapping(project_path.clone(), "next/dist/shared/lib/app-dynamic"),
362 );
363 insert_exact_alias_or_js(
364 &mut import_map,
365 "next/link",
366 request_to_import_mapping(project_path.clone(), "next/dist/client/app-dir/link"),
367 );
368 insert_exact_alias_or_js(
369 &mut import_map,
370 "next/form",
371 request_to_import_mapping(project_path.clone(), "next/dist/client/app-dir/form"),
372 );
373 }
374 ServerContextType::Middleware { .. } | ServerContextType::Instrumentation { .. } => {}
375 }
376
377 insert_next_server_special_aliases(
378 &mut import_map,
379 project_path.clone(),
380 ty,
381 NextRuntime::NodeJs,
382 next_config,
383 )
384 .await?;
385
386 Ok(import_map.cell())
387}
388
389#[turbo_tasks::function]
391pub async fn get_next_edge_import_map(
392 project_path: FileSystemPath,
393 ty: ServerContextType,
394 next_config: Vc<NextConfig>,
395 next_mode: Vc<NextMode>,
396 execution_context: Vc<ExecutionContext>,
397) -> Result<Vc<ImportMap>> {
398 let mut import_map = ImportMap::empty();
399
400 insert_wildcard_alias_map(
404 &mut import_map,
405 project_path.clone(),
406 fxindexmap! {
407 "next/dist/build/" => "next/dist/esm/build/*".to_string(),
408 "next/dist/client/" => "next/dist/esm/client/*".to_string(),
409 "next/dist/shared/" => "next/dist/esm/shared/*".to_string(),
410 "next/dist/pages/" => "next/dist/esm/pages/*".to_string(),
411 "next/dist/lib/" => "next/dist/esm/lib/*".to_string(),
412 "next/dist/server/" => "next/dist/esm/server/*".to_string(),
413 "next/dist/api/" => "next/dist/esm/api/*".to_string(),
414 },
415 );
416
417 insert_exact_alias_map(
419 &mut import_map,
420 project_path.clone(),
421 fxindexmap! {
422 "next/app" => "next/dist/api/app".to_string(),
423 "next/document" => "next/dist/api/document".to_string(),
424 "next/dynamic" => "next/dist/api/dynamic".to_string(),
425 "next/form" => "next/dist/api/form".to_string(),
426 "next/head" => "next/dist/api/head".to_string(),
427 "next/headers" => "next/dist/api/headers".to_string(),
428 "next/image" => "next/dist/api/image".to_string(),
429 "next/link" => "next/dist/api/link".to_string(),
430 "next/form" => "next/dist/api/form".to_string(),
431 "next/navigation" => "next/dist/api/navigation".to_string(),
432 "next/router" => "next/dist/api/router".to_string(),
433 "next/script" => "next/dist/api/script".to_string(),
434 "next/server" => "next/dist/api/server".to_string(),
435 "next/og" => "next/dist/api/og".to_string(),
436
437 "next/dist/compiled/@vercel/og/index.node.js" => "next/dist/compiled/@vercel/og/index.edge.js".to_string(),
439 },
440 );
441
442 insert_next_shared_aliases(
443 &mut import_map,
444 project_path.clone(),
445 execution_context,
446 next_config,
447 next_mode,
448 true,
449 )
450 .await?;
451
452 insert_optimized_module_aliases(&mut import_map, project_path.clone()).await?;
453
454 insert_alias_option(
455 &mut import_map,
456 &project_path,
457 next_config.resolve_alias_options(),
458 [],
459 )
460 .await?;
461
462 match &ty {
463 ServerContextType::Pages { .. }
464 | ServerContextType::PagesData { .. }
465 | ServerContextType::PagesApi { .. }
466 | ServerContextType::Middleware { .. }
467 | ServerContextType::Instrumentation { .. } => {}
468 ServerContextType::AppSSR { .. }
469 | ServerContextType::AppRSC { .. }
470 | ServerContextType::AppRoute { .. } => {
471 insert_exact_alias_or_js(
472 &mut import_map,
473 "next/head",
474 request_to_import_mapping(
475 project_path.clone(),
476 "next/dist/client/components/noop-head",
477 ),
478 );
479 insert_exact_alias_or_js(
480 &mut import_map,
481 "next/dynamic",
482 request_to_import_mapping(project_path.clone(), "next/dist/shared/lib/app-dynamic"),
483 );
484 insert_exact_alias_or_js(
485 &mut import_map,
486 "next/link",
487 request_to_import_mapping(project_path.clone(), "next/dist/client/app-dir/link"),
488 );
489 }
490 }
491
492 insert_next_server_special_aliases(
493 &mut import_map,
494 project_path.clone(),
495 ty.clone(),
496 NextRuntime::Edge,
497 next_config,
498 )
499 .await?;
500
501 match ty {
504 ServerContextType::AppSSR { .. }
505 | ServerContextType::AppRSC { .. }
506 | ServerContextType::AppRoute { .. }
507 | ServerContextType::Middleware { .. }
508 | ServerContextType::Instrumentation { .. }
509 | ServerContextType::Pages { .. }
510 | ServerContextType::PagesData { .. }
511 | ServerContextType::PagesApi { .. } => {
512 insert_unsupported_node_internal_aliases(&mut import_map).await?;
513 }
514 }
515
516 Ok(import_map.cell())
517}
518
519#[turbo_tasks::function]
521pub async fn get_next_edge_and_server_fallback_import_map(
522 project_path: FileSystemPath,
523 runtime: NextRuntime,
524) -> Result<Vc<ImportMap>> {
525 let mut fallback_import_map = ImportMap::empty();
526
527 let external_cjs_if_node = move |context_dir: FileSystemPath, request: &str| match runtime {
528 NextRuntime::Edge => request_to_import_mapping(context_dir, request),
529 NextRuntime::NodeJs => external_request_to_cjs_import_mapping(context_dir, request),
530 };
531
532 fallback_import_map.insert_exact_alias(
533 "@opentelemetry/api",
534 ImportMapping::Alternatives(vec![external_cjs_if_node(
537 project_path,
538 "next/dist/compiled/@opentelemetry/api",
539 )])
540 .resolved_cell(),
541 );
542 Ok(fallback_import_map.cell())
543}
544
545async fn insert_unsupported_node_internal_aliases(import_map: &mut ImportMap) -> Result<()> {
549 let unsupported_replacer = ImportMapping::Dynamic(ResolvedVc::upcast(
550 NextEdgeUnsupportedModuleReplacer::new()
551 .to_resolved()
552 .await?,
553 ))
554 .resolved_cell();
555
556 EDGE_UNSUPPORTED_NODE_INTERNALS.iter().for_each(|module| {
557 import_map.insert_alias(AliasPattern::exact(*module), unsupported_replacer);
558 });
559 Ok(())
560}
561
562pub fn get_next_client_resolved_map(
563 _context: FileSystemPath,
564 _root: FileSystemPath,
565 _mode: NextMode,
566) -> Vc<ResolvedMap> {
567 let glob_mappings = vec![];
568 ResolvedMap {
569 by_glob: glob_mappings,
570 }
571 .cell()
572}
573
574static NEXT_ALIASES: [(&str, &str); 23] = [
575 ("assert", "next/dist/compiled/assert"),
576 ("buffer", "next/dist/compiled/buffer"),
577 ("constants", "next/dist/compiled/constants-browserify"),
578 ("crypto", "next/dist/compiled/crypto-browserify"),
579 ("domain", "next/dist/compiled/domain-browser"),
580 ("http", "next/dist/compiled/stream-http"),
581 ("https", "next/dist/compiled/https-browserify"),
582 ("os", "next/dist/compiled/os-browserify"),
583 ("path", "next/dist/compiled/path-browserify"),
584 ("punycode", "next/dist/compiled/punycode"),
585 ("process", "next/dist/build/polyfills/process"),
586 ("querystring", "next/dist/compiled/querystring-es3"),
587 ("stream", "next/dist/compiled/stream-browserify"),
588 ("string_decoder", "next/dist/compiled/string_decoder"),
589 ("sys", "next/dist/compiled/util"),
590 ("timers", "next/dist/compiled/timers-browserify"),
591 ("tty", "next/dist/compiled/tty-browserify"),
592 ("url", "next/dist/compiled/native-url"),
593 ("util", "next/dist/compiled/util"),
594 ("vm", "next/dist/compiled/vm-browserify"),
595 ("zlib", "next/dist/compiled/browserify-zlib"),
596 ("events", "next/dist/compiled/events"),
597 ("setImmediate", "next/dist/compiled/setimmediate"),
598];
599
600async fn insert_next_server_special_aliases(
601 import_map: &mut ImportMap,
602 project_path: FileSystemPath,
603 ty: ServerContextType,
604 runtime: NextRuntime,
605 next_config: Vc<NextConfig>,
606) -> Result<()> {
607 let external_cjs_if_node = move |context_dir: FileSystemPath, request: &str| match runtime {
608 NextRuntime::Edge => request_to_import_mapping(context_dir, request),
609 NextRuntime::NodeJs => external_request_to_cjs_import_mapping(context_dir, request),
610 };
611 let external_esm_if_node = move |context_dir: FileSystemPath, request: &str| match runtime {
612 NextRuntime::Edge => request_to_import_mapping(context_dir, request),
613 NextRuntime::NodeJs => external_request_to_esm_import_mapping(context_dir, request),
614 };
615
616 import_map.insert_exact_alias(
617 "next/dist/compiled/@vercel/og/index.node.js",
618 external_esm_if_node(
619 project_path.clone(),
620 "next/dist/compiled/@vercel/og/index.node.js",
621 ),
622 );
623
624 import_map.insert_exact_alias(
625 "next/dist/server/ReactDOMServerPages",
626 ImportMapping::Alternatives(vec![
627 request_to_import_mapping(project_path.clone(), "react-dom/server.edge"),
628 request_to_import_mapping(project_path.clone(), "react-dom/server.browser"),
629 ])
630 .resolved_cell(),
631 );
632
633 match &ty {
634 ServerContextType::Pages { .. } | ServerContextType::PagesApi { .. } => {}
635 ServerContextType::PagesData { .. } => {}
636 ServerContextType::AppSSR { app_dir }
638 | ServerContextType::AppRSC { app_dir, .. }
639 | ServerContextType::AppRoute { app_dir, .. } => {
640 let next_package = get_next_package(app_dir.clone()).owned().await?;
641 import_map.insert_exact_alias(
642 "styled-jsx",
643 request_to_import_mapping(next_package.clone(), "styled-jsx"),
644 );
645 import_map.insert_wildcard_alias(
646 "styled-jsx/",
647 request_to_import_mapping(next_package.clone(), "styled-jsx/*"),
648 );
649
650 rsc_aliases(
651 import_map,
652 project_path.clone(),
653 ty.clone(),
654 runtime,
655 next_config,
656 )
657 .await?;
658 }
659 ServerContextType::Middleware { .. } | ServerContextType::Instrumentation { .. } => {
660 rsc_aliases(
661 import_map,
662 project_path.clone(),
663 ty.clone(),
664 runtime,
665 next_config,
666 )
667 .await?;
668 }
669 }
670
671 match &ty {
677 ServerContextType::Pages { .. } => {
678 insert_exact_alias_map(
679 import_map,
680 project_path.clone(),
681 fxindexmap! {
682 "server-only" => "next/dist/compiled/server-only/empty".to_string(),
683 "client-only" => "next/dist/compiled/client-only/index".to_string(),
684 "next/dist/compiled/server-only" => "next/dist/compiled/server-only/empty".to_string(),
685 "next/dist/compiled/client-only" => "next/dist/compiled/client-only/index".to_string(),
686 },
687 );
688 }
689 ServerContextType::PagesData { .. }
690 | ServerContextType::PagesApi { .. }
691 | ServerContextType::AppRSC { .. }
692 | ServerContextType::AppRoute { .. }
693 | ServerContextType::Middleware { .. }
694 | ServerContextType::Instrumentation { .. } => {
695 insert_exact_alias_map(
696 import_map,
697 project_path.clone(),
698 fxindexmap! {
699 "server-only" => "next/dist/compiled/server-only/empty".to_string(),
700 "client-only" => "next/dist/compiled/client-only/error".to_string(),
701 "next/dist/compiled/server-only" => "next/dist/compiled/server-only/empty".to_string(),
702 "next/dist/compiled/client-only" => "next/dist/compiled/client-only/error".to_string(),
703 },
704 );
705 }
706 ServerContextType::AppSSR { .. } => {
707 insert_exact_alias_map(
708 import_map,
709 project_path.clone(),
710 fxindexmap! {
711 "server-only" => "next/dist/compiled/server-only/index".to_string(),
712 "client-only" => "next/dist/compiled/client-only/index".to_string(),
713 "next/dist/compiled/server-only" => "next/dist/compiled/server-only/index".to_string(),
714 "next/dist/compiled/client-only" => "next/dist/compiled/client-only/index".to_string(),
715 },
716 );
717 }
718 }
719
720 import_map.insert_exact_alias(
721 "@vercel/og",
722 external_cjs_if_node(project_path.clone(), "next/dist/server/og/image-response"),
723 );
724
725 Ok(())
726}
727
728async fn get_react_client_package(next_config: Vc<NextConfig>) -> Result<&'static str> {
729 let react_production_profiling = *next_config.enable_react_production_profiling().await?;
730 let react_client_package = if react_production_profiling {
731 "profiling"
732 } else {
733 "client"
734 };
735
736 Ok(react_client_package)
737}
738
739async fn apply_vendored_react_aliases_server(
742 import_map: &mut ImportMap,
743 project_path: FileSystemPath,
744 ty: ServerContextType,
745 runtime: NextRuntime,
746 next_config: Vc<NextConfig>,
747) -> Result<()> {
748 let ppr = *next_config.enable_ppr().await?;
749 let taint = *next_config.enable_taint().await?;
750 let router_bfcache = *next_config.enable_router_bfcache().await?;
751 let view_transition = *next_config.enable_view_transition().await?;
752 let react_channel = if ppr || taint || view_transition || router_bfcache {
753 "-experimental"
754 } else {
755 ""
756 };
757 let react_condition = if ty.should_use_react_server_condition() {
758 "server"
759 } else {
760 "client"
761 };
762
763 let mut react_alias = FxIndexMap::default();
769 if runtime == NextRuntime::NodeJs && react_condition == "client" {
770 react_alias.extend(fxindexmap! {
771 "react" => format!("next/dist/server/route-modules/app-page/vendored/ssr/react"),
773 "react/compiler-runtime" => format!("next/dist/server/route-modules/app-page/vendored/ssr/react-compiler-runtime"),
774 "react/jsx-dev-runtime" => format!("next/dist/server/route-modules/app-page/vendored/ssr/react-jsx-dev-runtime"),
775 "react/jsx-runtime" => format!("next/dist/server/route-modules/app-page/vendored/ssr/react-jsx-runtime"),
776 "react-dom" => format!("next/dist/server/route-modules/app-page/vendored/ssr/react-dom"),
778 "react-dom/client" => format!("next/dist/compiled/react-dom{react_channel}/client"),
779 "react-dom/server" => format!("next/dist/compiled/react-dom{react_channel}/server.node"),
780 "react-dom/server.browser" => format!("next/dist/compiled/react-dom{react_channel}/server.browser"),
781 "react-dom/server.edge" => format!("next/dist/compiled/react-dom{react_channel}/server.edge"),
783 "react-dom/static" => format!("next/dist/compiled/react-dom{react_channel}/static.node"),
784 "react-dom/static.browser" => format!("next/dist/compiled/react-dom{react_channel}/static.browser"),
785 "react-dom/static.edge" => format!("next/dist/compiled/react-dom{react_channel}/static.edge"),
786 "react-server-dom-webpack/client" => format!("next/dist/server/route-modules/app-page/vendored/ssr/react-server-dom-turbopack-client"),
788 "react-server-dom-webpack/server" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
789 "react-server-dom-webpack/server.node" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
790 "react-server-dom-webpack/static" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/static.node"),
791 "react-server-dom-turbopack/client" => format!("next/dist/server/route-modules/app-page/vendored/ssr/react-server-dom-turbopack-client"),
792 "react-server-dom-turbopack/server" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
793 "react-server-dom-turbopack/server.node" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
794 "react-server-dom-turbopack/static.edge" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/static.edge"),
795 })
796 } else if runtime == NextRuntime::NodeJs && react_condition == "server" {
797 react_alias.extend(fxindexmap! {
798 "react" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react"),
800 "react/compiler-runtime" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-compiler-runtime"),
801 "react/jsx-dev-runtime" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-jsx-dev-runtime"),
802 "react/jsx-runtime" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-jsx-runtime"),
803 "react-dom" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-dom"),
805 "react-dom/client" => format!("next/dist/compiled/react-dom{react_channel}/client"),
806 "react-dom/server" => format!("next/dist/compiled/react-dom{react_channel}/server.node"),
807 "react-dom/server.browser" => format!("next/dist/compiled/react-dom{react_channel}/server.browser"),
808 "react-dom/server.edge" => format!("next/dist/compiled/react-dom{react_channel}/server.edge"),
810 "react-dom/static" => format!("next/dist/compiled/react-dom{react_channel}/static.node"),
811 "react-dom/static.browser" => format!("next/dist/compiled/react-dom{react_channel}/static.browser"),
812 "react-dom/static.edge" => format!("next/dist/compiled/react-dom{react_channel}/static.edge"),
813 "react-server-dom-webpack/client" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/client.node"),
815 "react-server-dom-webpack/server" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-server"),
816 "react-server-dom-webpack/server.node" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-server"),
817 "react-server-dom-webpack/static" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-static"),
818 "react-server-dom-turbopack/client" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/client.node"),
819 "react-server-dom-turbopack/server" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-server"),
820 "react-server-dom-turbopack/server.node" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-server"),
821 "react-server-dom-turbopack/static" => format!("next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-static"),
822
823 "next/dist/compiled/react" => format!("next/dist/compiled/react/index.js"),
826 })
827 } else if runtime == NextRuntime::Edge && react_condition == "client" {
828 react_alias.extend(fxindexmap! {
829 "react" => format!("next/dist/compiled/react{react_channel}"),
831 "react/compiler-runtime" => format!("next/dist/compiled/react{react_channel}/compiler-runtime"),
832 "react/jsx-dev-runtime" => format!("next/dist/compiled/react{react_channel}/jsx-dev-runtime"),
833 "react/jsx-runtime" => format!("next/dist/compiled/react{react_channel}/jsx-runtime"),
834 "react-dom" => format!("next/dist/compiled/react-dom{react_channel}"),
836 "react-dom/client" => format!("next/dist/compiled/react-dom{react_channel}/client"),
837 "react-dom/server" => format!("next/dist/compiled/react-dom{react_channel}/server.edge"),
838 "react-dom/server.browser" => format!("next/dist/compiled/react-dom{react_channel}/server.browser"),
839 "react-dom/server.edge" => format!("next/dist/compiled/react-dom{react_channel}/server.edge"),
841 "react-dom/static" => format!("next/dist/compiled/react-dom{react_channel}/static.edge"),
842 "react-dom/static.browser" => format!("next/dist/compiled/react-dom{react_channel}/static.browser"),
843 "react-dom/static.edge" => format!("next/dist/compiled/react-dom{react_channel}/static.edge"),
844 "react-server-dom-webpack/client" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/client.edge"),
846 "react-server-dom-webpack/server" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.edge"),
847 "react-server-dom-webpack/server.node" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
848 "react-server-dom-webpack/static" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/static.edge"),
849 "react-server-dom-turbopack/client" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/client.edge"),
850 "react-server-dom-turbopack/server" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.edge"),
851 "react-server-dom-turbopack/server.node" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
852 "react-server-dom-turbopack/static" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/static.edge"),
853 })
854 } else if runtime == NextRuntime::Edge && react_condition == "server" {
855 react_alias.extend(fxindexmap! {
856 "react" => format!("next/dist/compiled/react{react_channel}/react.react-server"),
858 "react/compiler-runtime" => format!("next/dist/compiled/react{react_channel}/compiler-runtime"),
859 "react/jsx-dev-runtime" => format!("next/dist/compiled/react{react_channel}/jsx-dev-runtime.react-server"),
860 "react/jsx-runtime" => format!("next/dist/compiled/react{react_channel}/jsx-runtime.react-server"),
861 "react-dom" => format!("next/dist/compiled/react-dom{react_channel}/react-dom.react-server"),
863 "react-dom/client" => format!("next/dist/compiled/react-dom{react_channel}/client"),
864 "react-dom/server" => format!("next/dist/compiled/react-dom{react_channel}/server.edge"),
865 "react-dom/server.browser" => format!("next/dist/compiled/react-dom{react_channel}/server.browser"),
866 "react-dom/server.edge" => format!("next/dist/compiled/react-dom{react_channel}/server.edge"),
868 "react-dom/static" => format!("next/dist/compiled/react-dom{react_channel}/static.edge"),
869 "react-dom/static.browser" => format!("next/dist/compiled/react-dom{react_channel}/static.browser"),
870 "react-dom/static.edge" => format!("next/dist/compiled/react-dom{react_channel}/static.edge"),
871 "react-server-dom-webpack/client" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/client.edge"),
873 "react-server-dom-webpack/server" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.edge"),
874 "react-server-dom-webpack/server.node" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
875 "react-server-dom-webpack/static" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/static.edge"),
876 "react-server-dom-turbopack/client" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/client.edge"),
877 "react-server-dom-turbopack/server" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.edge"),
878 "react-server-dom-turbopack/server.node" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/server.node"),
879 "react-server-dom-turbopack/static" => format!("next/dist/compiled/react-server-dom-turbopack{react_channel}/static.edge"),
880 });
881
882 react_alias.extend(fxindexmap! {
883 "next/dist/compiled/react" => react_alias["react"].clone(),
885 "next/dist/compiled/react-experimental" => react_alias["react"].clone(),
886 "next/dist/compiled/react/compiler-runtime" => react_alias["react/compiler-runtime"].clone(),
887 "next/dist/compiled/react-experimental/compiler-runtime" => react_alias["react/compiler-runtime"].clone(),
888 "next/dist/compiled/react/jsx-dev-runtime" => react_alias["react/jsx-dev-runtime"].clone(),
889 "next/dist/compiled/react-experimental/jsx-dev-runtime" => react_alias["react/jsx-dev-runtime"].clone(),
890 "next/dist/compiled/react/jsx-runtime" => react_alias["react/jsx-runtime"].clone(),
891 "next/dist/compiled/react-experimental/jsx-runtime" => react_alias["react/jsx-runtime"].clone(),
892 "next/dist/compiled/react-dom" => react_alias["react-dom"].clone(),
893 "next/dist/compiled/react-dom-experimental" => react_alias["react-dom"].clone(),
894 });
895 }
896
897 let react_client_package = get_react_client_package(next_config).await?;
898 react_alias.extend(fxindexmap! {
899 "react-dom/client" => format!("next/dist/compiled/react-dom{react_channel}/{react_client_package}"),
900 });
901
902 let mut alias = react_alias;
903 if react_condition == "server" {
904 alias.extend(fxindexmap! {
906 "next/navigation" => format!("next/dist/api/navigation.react-server"),
907 });
908 }
909
910 insert_exact_alias_map(import_map, project_path, alias);
911
912 Ok(())
913}
914
915async fn rsc_aliases(
916 import_map: &mut ImportMap,
917 project_path: FileSystemPath,
918 ty: ServerContextType,
919 runtime: NextRuntime,
920 next_config: Vc<NextConfig>,
921) -> Result<()> {
922 apply_vendored_react_aliases_server(
923 import_map,
924 project_path.clone(),
925 ty.clone(),
926 runtime,
927 next_config,
928 )
929 .await?;
930
931 let mut alias = FxIndexMap::default();
932 if ty.should_use_react_server_condition() {
933 alias.extend(fxindexmap! {
935 "next/navigation" => format!("next/dist/api/navigation.react-server"),
936 });
937 }
938
939 insert_exact_alias_map(import_map, project_path.clone(), alias);
940
941 Ok(())
942}
943
944pub fn mdx_import_source_file() -> RcStr {
945 format!("{VIRTUAL_PACKAGE_NAME}/mdx-import-source").into()
946}
947
948async fn insert_optimized_module_aliases(
951 import_map: &mut ImportMap,
952 project_path: FileSystemPath,
953) -> Result<()> {
954 insert_exact_alias_map(
955 import_map,
956 project_path,
957 fxindexmap! {
958 "unfetch" => "next/dist/build/polyfills/fetch/index.js".to_string(),
959 "isomorphic-unfetch" => "next/dist/build/polyfills/fetch/index.js".to_string(),
960 "whatwg-fetch" => "next/dist/build/polyfills/fetch/whatwg-fetch.js".to_string(),
961 "object-assign" => "next/dist/build/polyfills/object-assign.js".to_string(),
962 "object.assign/auto" => "next/dist/build/polyfills/object.assign/auto.js".to_string(),
963 "object.assign/implementation" => "next/dist/build/polyfills/object.assign/implementation.js".to_string(),
964 "object.assign/polyfill" => "next/dist/build/polyfills/object.assign/polyfill.js".to_string(),
965 "object.assign/shim" => "next/dist/build/polyfills/object.assign/shim.js".to_string(),
966 "url" => "next/dist/compiled/native-url".to_string(),
967 "node:url" => "next/dist/compiled/native-url".to_string(),
968 },
969 );
970 Ok(())
971}
972
973async fn insert_next_shared_aliases(
975 import_map: &mut ImportMap,
976 project_path: FileSystemPath,
977 execution_context: Vc<ExecutionContext>,
978 next_config: Vc<NextConfig>,
979 next_mode: Vc<NextMode>,
980 is_runtime_edge: bool,
981) -> Result<()> {
982 let package_root = next_js_fs().root().owned().await?;
983
984 insert_alias_to_alternatives(
985 import_map,
986 mdx_import_source_file(),
987 vec![
988 request_to_import_mapping(project_path.clone(), "./mdx-components"),
989 request_to_import_mapping(project_path.clone(), "./src/mdx-components"),
990 request_to_import_mapping(project_path.clone(), "@mdx-js/react"),
991 request_to_import_mapping(project_path.clone(), "@next/mdx/mdx-components.js"),
992 ],
993 );
994
995 insert_package_alias(
996 import_map,
997 &format!("{VIRTUAL_PACKAGE_NAME}/"),
998 package_root,
999 );
1000
1001 let next_font_google_replacer_mapping = ImportMapping::Dynamic(ResolvedVc::upcast(
1007 NextFontGoogleReplacer::new(project_path.clone())
1008 .to_resolved()
1009 .await?,
1010 ))
1011 .resolved_cell();
1012
1013 import_map.insert_alias(
1014 AliasPattern::exact("next/font/google/target.css"),
1016 next_font_google_replacer_mapping,
1017 );
1018
1019 import_map.insert_alias(
1020 AliasPattern::exact("@next/font/google/target.css"),
1022 next_font_google_replacer_mapping,
1023 );
1024
1025 import_map.insert_alias(
1026 AliasPattern::exact("@vercel/turbopack-next/internal/font/google/cssmodule.module.css"),
1027 ImportMapping::Dynamic(ResolvedVc::upcast(
1028 NextFontGoogleCssModuleReplacer::new(
1029 project_path.clone(),
1030 execution_context,
1031 next_mode,
1032 )
1033 .to_resolved()
1034 .await?,
1035 ))
1036 .resolved_cell(),
1037 );
1038
1039 import_map.insert_alias(
1040 AliasPattern::exact(GOOGLE_FONTS_INTERNAL_PREFIX),
1041 ImportMapping::Dynamic(ResolvedVc::upcast(
1042 NextFontGoogleFontFileReplacer::new(project_path.clone())
1043 .to_resolved()
1044 .await?,
1045 ))
1046 .resolved_cell(),
1047 );
1048
1049 let next_package = get_next_package(project_path.clone()).owned().await?;
1050 import_map.insert_singleton_alias("@swc/helpers", next_package.clone());
1051 import_map.insert_singleton_alias("styled-jsx", next_package.clone());
1052 import_map.insert_singleton_alias("next", project_path.clone());
1053 import_map.insert_singleton_alias("react", project_path.clone());
1054 import_map.insert_singleton_alias("react-dom", project_path.clone());
1055 let react_client_package = get_react_client_package(next_config).await?;
1056 import_map.insert_exact_alias(
1057 "react-dom/client",
1058 request_to_import_mapping(
1059 project_path.clone(),
1060 &format!("react-dom/{react_client_package}"),
1061 ),
1062 );
1063
1064 import_map.insert_alias(
1065 AliasPattern::exact("next"),
1068 ImportMapping::Empty.resolved_cell(),
1069 );
1070
1071 import_map.insert_exact_alias(
1073 "setimmediate",
1074 request_to_import_mapping(project_path.clone(), "next/dist/compiled/setimmediate"),
1075 );
1076
1077 import_map.insert_exact_alias(
1078 "private-next-rsc-server-reference",
1079 request_to_import_mapping(
1080 project_path.clone(),
1081 "next/dist/build/webpack/loaders/next-flight-loader/server-reference",
1082 ),
1083 );
1084 import_map.insert_exact_alias(
1085 "private-next-rsc-action-client-wrapper",
1086 request_to_import_mapping(
1087 project_path.clone(),
1088 "next/dist/build/webpack/loaders/next-flight-loader/action-client-wrapper",
1089 ),
1090 );
1091 import_map.insert_exact_alias(
1092 "private-next-rsc-action-validate",
1093 request_to_import_mapping(
1094 project_path.clone(),
1095 "next/dist/build/webpack/loaders/next-flight-loader/action-validate",
1096 ),
1097 );
1098 import_map.insert_exact_alias(
1099 "private-next-rsc-action-encryption",
1100 request_to_import_mapping(
1101 project_path.clone(),
1102 "next/dist/server/app-render/encryption",
1103 ),
1104 );
1105 import_map.insert_exact_alias(
1106 "private-next-rsc-cache-wrapper",
1107 request_to_import_mapping(
1108 project_path.clone(),
1109 "next/dist/build/webpack/loaders/next-flight-loader/cache-wrapper",
1110 ),
1111 );
1112 import_map.insert_exact_alias(
1113 "private-next-rsc-track-dynamic-import",
1114 request_to_import_mapping(
1115 project_path.clone(),
1116 "next/dist/build/webpack/loaders/next-flight-loader/track-dynamic-import",
1117 ),
1118 );
1119
1120 insert_turbopack_dev_alias(import_map).await?;
1121 insert_package_alias(
1122 import_map,
1123 "@vercel/turbopack-node/",
1124 turbopack_node::embed_js::embed_fs().root().owned().await?,
1125 );
1126
1127 let image_config = next_config.image_config().await?;
1128 if let Some(loader_file) = image_config.loader_file.as_deref() {
1129 import_map.insert_exact_alias(
1130 "next/dist/shared/lib/image-loader",
1131 request_to_import_mapping(project_path.clone(), loader_file),
1132 );
1133
1134 if is_runtime_edge {
1135 import_map.insert_exact_alias(
1136 "next/dist/esm/shared/lib/image-loader",
1137 request_to_import_mapping(project_path.clone(), loader_file),
1138 );
1139 }
1140 }
1141
1142 Ok(())
1143}
1144
1145#[turbo_tasks::function]
1146pub async fn get_next_package(context_directory: FileSystemPath) -> Result<Vc<FileSystemPath>> {
1147 let result = resolve(
1148 context_directory.clone(),
1149 ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined),
1150 Request::parse(Pattern::Constant(rcstr!("next/package.json"))),
1151 node_cjs_resolve_options(context_directory.root().owned().await?),
1152 );
1153 let source = result
1154 .first_source()
1155 .await?
1156 .context("Next.js package not found")?;
1157 Ok(source.ident().path().await?.parent().cell())
1158}
1159
1160pub async fn insert_alias_option<const N: usize>(
1161 import_map: &mut ImportMap,
1162 project_path: &FileSystemPath,
1163 alias_options: Vc<ResolveAliasMap>,
1164 conditions: [&'static str; N],
1165) -> Result<()> {
1166 let conditions = BTreeMap::from(conditions.map(|c| (c.into(), ConditionValue::Set)));
1167 for (alias, value) in &alias_options.await? {
1168 if let Some(mapping) = export_value_to_import_mapping(value, &conditions, project_path) {
1169 import_map.insert_alias(alias, mapping);
1170 }
1171 }
1172 Ok(())
1173}
1174
1175fn export_value_to_import_mapping(
1176 value: &SubpathValue,
1177 conditions: &BTreeMap<RcStr, ConditionValue>,
1178 project_path: &FileSystemPath,
1179) -> Option<ResolvedVc<ImportMapping>> {
1180 let mut result = Vec::new();
1181 value.add_results(
1182 conditions,
1183 &ConditionValue::Unset,
1184 &mut FxHashMap::default(),
1185 &mut result,
1186 );
1187 if result.is_empty() {
1188 None
1189 } else {
1190 Some(if result.len() == 1 {
1191 ImportMapping::PrimaryAlternative(result[0].0.into(), Some(project_path.clone()))
1192 .resolved_cell()
1193 } else {
1194 ImportMapping::Alternatives(
1195 result
1196 .iter()
1197 .map(|(m, _)| {
1198 ImportMapping::PrimaryAlternative((*m).into(), Some(project_path.clone()))
1199 .resolved_cell()
1200 })
1201 .collect(),
1202 )
1203 .resolved_cell()
1204 })
1205 }
1206}
1207
1208fn insert_exact_alias_map(
1209 import_map: &mut ImportMap,
1210 project_path: FileSystemPath,
1211 map: FxIndexMap<&'static str, String>,
1212) {
1213 for (pattern, request) in map {
1214 import_map.insert_exact_alias(
1215 pattern,
1216 request_to_import_mapping(project_path.clone(), &request),
1217 );
1218 }
1219}
1220
1221fn insert_wildcard_alias_map(
1222 import_map: &mut ImportMap,
1223 project_path: FileSystemPath,
1224 map: FxIndexMap<&'static str, String>,
1225) {
1226 for (pattern, request) in map {
1227 import_map.insert_wildcard_alias(
1228 pattern,
1229 request_to_import_mapping(project_path.clone(), &request),
1230 );
1231 }
1232}
1233
1234fn insert_alias_to_alternatives<'a>(
1236 import_map: &mut ImportMap,
1237 alias: impl Into<String> + 'a,
1238 alternatives: Vec<ResolvedVc<ImportMapping>>,
1239) {
1240 import_map.insert_exact_alias(
1241 alias.into(),
1242 ImportMapping::Alternatives(alternatives).resolved_cell(),
1243 );
1244}
1245
1246fn insert_package_alias(import_map: &mut ImportMap, prefix: &str, package_root: FileSystemPath) {
1248 import_map.insert_wildcard_alias(
1249 prefix,
1250 ImportMapping::PrimaryAlternative(rcstr!("./*"), Some(package_root)).resolved_cell(),
1251 );
1252}
1253
1254async fn insert_turbopack_dev_alias(import_map: &mut ImportMap) -> Result<()> {
1256 insert_package_alias(
1257 import_map,
1258 "@vercel/turbopack-ecmascript-runtime/",
1259 turbopack_ecmascript_runtime::embed_fs()
1260 .root()
1261 .owned()
1262 .await?,
1263 );
1264 Ok(())
1265}
1266
1267async fn insert_instrumentation_client_alias(
1269 import_map: &mut ImportMap,
1270 project_path: FileSystemPath,
1271) -> Result<()> {
1272 insert_alias_to_alternatives(
1273 import_map,
1274 "private-next-instrumentation-client",
1275 vec![
1276 request_to_import_mapping(project_path.clone(), "./src/instrumentation-client"),
1277 request_to_import_mapping(project_path.clone(), "./src/instrumentation-client.ts"),
1278 request_to_import_mapping(project_path.clone(), "./instrumentation-client"),
1279 request_to_import_mapping(project_path.clone(), "./instrumentation-client.ts"),
1280 ImportMapping::Ignore.resolved_cell(),
1281 ],
1282 );
1283
1284 Ok(())
1285}
1286
1287fn insert_exact_alias_or_js(
1289 import_map: &mut ImportMap,
1290 pattern: &str,
1291 mapping: ResolvedVc<ImportMapping>,
1292) {
1293 import_map.insert_exact_alias(pattern, mapping);
1294 import_map.insert_exact_alias(format!("{pattern}.js"), mapping);
1295}
1296
1297fn request_to_import_mapping(
1300 context_path: FileSystemPath,
1301 request: &str,
1302) -> ResolvedVc<ImportMapping> {
1303 ImportMapping::PrimaryAlternative(request.into(), Some(context_path)).resolved_cell()
1304}
1305
1306fn external_request_to_cjs_import_mapping(
1309 context_dir: FileSystemPath,
1310 request: &str,
1311) -> ResolvedVc<ImportMapping> {
1312 ImportMapping::PrimaryAlternativeExternal {
1313 name: Some(request.into()),
1314 ty: ExternalType::CommonJs,
1315 traced: ExternalTraced::Traced,
1316 lookup_dir: context_dir,
1317 }
1318 .resolved_cell()
1319}
1320
1321fn external_request_to_esm_import_mapping(
1324 context_dir: FileSystemPath,
1325 request: &str,
1326) -> ResolvedVc<ImportMapping> {
1327 ImportMapping::PrimaryAlternativeExternal {
1328 name: Some(request.into()),
1329 ty: ExternalType::EcmaScriptModule,
1330 traced: ExternalTraced::Traced,
1331 lookup_dir: context_dir,
1332 }
1333 .resolved_cell()
1334}