diff --git a/packages/next-swc/crates/next-api/src/app.rs b/packages/next-swc/crates/next-api/src/app.rs index 1fda6368d3aed..fd42d04fe7fa7 100644 --- a/packages/next-swc/crates/next-api/src/app.rs +++ b/packages/next-swc/crates/next-api/src/app.rs @@ -7,7 +7,7 @@ use next_core::{ get_entrypoints, Entrypoint as AppEntrypoint, Entrypoints as AppEntrypoints, LoaderTree, MetadataItem, }, - get_edge_resolve_options_context, + get_edge_resolve_options_context, get_next_package, next_app::{ app_client_references_chunks::get_app_server_reference_modules, get_app_client_references_chunks, get_app_client_shared_chunk_group, get_app_page_entry, @@ -45,10 +45,14 @@ use turbopack_binding::{ turbopack::{ core::{ asset::{Asset, AssetContent}, - chunk::{availability_info::AvailabilityInfo, ChunkingContextExt, EvaluatableAssets}, + chunk::{ + availability_info::AvailabilityInfo, ChunkingContext, ChunkingContextExt, + EvaluatableAssets, + }, file_source::FileSource, module::Module, output::{OutputAsset, OutputAssets}, + source::Source, virtual_output::VirtualOutputAsset, }, nodejs::EntryChunkGroupResult, @@ -894,8 +898,26 @@ impl AppEndpoint { )); server_assets.push(app_build_manifest_output); + // polyfill-nomodule.js is a pre-compiled asset distributed as part of next, + // load it as a RawModule. + let next_package = get_next_package(this.app_project.project().project_path()); + let polyfill_source = FileSource::new( + next_package.join("dist/build/polyfills/polyfill-nomodule.js".to_string()), + ); + let polyfill_output_path = + client_chunking_context.chunk_path(polyfill_source.ident(), ".js".to_string()); + let polyfill_output_asset = + VirtualOutputAsset::new(polyfill_output_path, polyfill_source.content()); + let polyfill_client_path = client_relative_path_ref + .get_path_to(&*polyfill_output_path.await?) + .context("failed to resolve client-relative path to polyfill")? + .to_string(); + let polyfill_client_paths = vec![polyfill_client_path]; + client_assets.push(Vc::upcast(polyfill_output_asset)); + let build_manifest = BuildManifest { root_main_files: client_shared_chunks_paths, + polyfill_files: polyfill_client_paths, ..Default::default() }; let build_manifest_output = Vc::upcast(VirtualOutputAsset::new( diff --git a/packages/next-swc/crates/next-core/src/lib.rs b/packages/next-swc/crates/next-core/src/lib.rs index ccf66bb91658c..6c28c7b956644 100644 --- a/packages/next-swc/crates/next-core/src/lib.rs +++ b/packages/next-swc/crates/next-core/src/lib.rs @@ -45,6 +45,7 @@ pub use next_edge::context::{ get_edge_chunking_context, get_edge_chunking_context_with_client_assets, get_edge_compile_time_info, get_edge_resolve_options_context, }; +pub use next_import_map::get_next_package; pub use page_loader::{create_page_loader_entry_module, PageLoaderAsset}; use turbopack_binding::{turbo, turbopack}; pub use util::{get_asset_path_from_pathname, pathname_for_path, PathType}; diff --git a/packages/next/src/server/dev/turbopack/manifest-loader.ts b/packages/next/src/server/dev/turbopack/manifest-loader.ts index c796aedc1e132..0b42016baf160 100644 --- a/packages/next/src/server/dev/turbopack/manifest-loader.ts +++ b/packages/next/src/server/dev/turbopack/manifest-loader.ts @@ -287,6 +287,8 @@ export class TurbopackManifestLoader { for (const m of manifests) { Object.assign(manifest.pages, m.pages) if (m.rootMainFiles.length) manifest.rootMainFiles = m.rootMainFiles + // polyfillFiles should always be the same, so we can overwrite instead of actually merging + if (m.polyfillFiles.length) manifest.polyfillFiles = m.polyfillFiles } return manifest } diff --git a/test/e2e/app-dir/app/index.test.ts b/test/e2e/app-dir/app/index.test.ts index 91b80235b82ac..8e695a09b447c 100644 --- a/test/e2e/app-dir/app/index.test.ts +++ b/test/e2e/app-dir/app/index.test.ts @@ -376,7 +376,9 @@ describe('app dir - basic', () => { it('should serve polyfills for browsers that do not support modules', async () => { const html = await next.render('/dashboard/index') expect(html).toMatch( - /