diff --git a/.eslintrc.json b/.eslintrc.json
index 8c46d8c02736f..feb49b2ecbbff 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -162,7 +162,10 @@
},
{
"files": ["packages/**"],
- "excludedFiles": ["packages/next/taskfile.js"],
+ "excludedFiles": [
+ "packages/next/taskfile*.js",
+ "packages/next/webpack.config.js"
+ ],
"rules": {
"no-shadow": ["warn", { "builtinGlobals": false }],
"import/no-extraneous-dependencies": [
diff --git a/bench/basic-app/app/api/app/route.js b/bench/basic-app/app/api/app/route.js
new file mode 100644
index 0000000000000..944ba5a8e827f
--- /dev/null
+++ b/bench/basic-app/app/api/app/route.js
@@ -0,0 +1,5 @@
+export function GET() {
+ return { name: 'John Doe' }
+}
+
+export const dynamic = 'force-dynamic'
diff --git a/bench/basic-app/app/layout.js b/bench/basic-app/app/layout.js
new file mode 100644
index 0000000000000..8ebf54889577d
--- /dev/null
+++ b/bench/basic-app/app/layout.js
@@ -0,0 +1,12 @@
+import React from 'react'
+
+export default function Layout({ children }) {
+ return (
+
+
+ My App
+
+ {children}
+
+ )
+}
diff --git a/bench/basic-app/app/page.js b/bench/basic-app/app/page.js
new file mode 100644
index 0000000000000..83dc3aa56c9a0
--- /dev/null
+++ b/bench/basic-app/app/page.js
@@ -0,0 +1,7 @@
+import React from 'react'
+
+export default function Page() {
+ return My Page
+}
+
+export const dynamic = 'force-dynamic'
diff --git a/bench/basic-app/next.config.js b/bench/basic-app/next.config.js
new file mode 100644
index 0000000000000..0957c472383fa
--- /dev/null
+++ b/bench/basic-app/next.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+ experimental: {
+ serverMinification: true,
+ },
+}
diff --git a/bench/basic-app/pages/api/index.js b/bench/basic-app/pages/api/index.js
new file mode 100644
index 0000000000000..8f603094bd288
--- /dev/null
+++ b/bench/basic-app/pages/api/index.js
@@ -0,0 +1,3 @@
+export default function handler(req, res) {
+ res.status(200).json({ name: 'John Doe' })
+}
diff --git a/bench/basic-app/pages/pages/index.js b/bench/basic-app/pages/pages/index.js
new file mode 100644
index 0000000000000..e06229eee0637
--- /dev/null
+++ b/bench/basic-app/pages/pages/index.js
@@ -0,0 +1,7 @@
+export default () => 'Hello World'
+
+export function getServerSideProps() {
+ return {
+ props: {},
+ }
+}
diff --git a/packages/next-swc/crates/next-core/js/src/entry/app-edge-renderer.tsx b/packages/next-swc/crates/next-core/js/src/entry/app-edge-renderer.tsx
index fdec9ffc360fe..38f27b3c1c7a3 100644
--- a/packages/next-swc/crates/next-core/js/src/entry/app-edge-renderer.tsx
+++ b/packages/next-swc/crates/next-core/js/src/entry/app-edge-renderer.tsx
@@ -2,6 +2,8 @@
// the other imports
import startOperationStreamHandler from '../internal/operation-stream'
+import 'next/dist/server/node-polyfill-fetch'
+
import { join } from 'path'
import { parse as parseUrl } from 'node:url'
diff --git a/packages/next-swc/crates/next-core/js/src/entry/app-renderer.tsx b/packages/next-swc/crates/next-core/js/src/entry/app-renderer.tsx
index 951f91570d92d..25437fec08ef4 100644
--- a/packages/next-swc/crates/next-core/js/src/entry/app-renderer.tsx
+++ b/packages/next-swc/crates/next-core/js/src/entry/app-renderer.tsx
@@ -3,13 +3,15 @@
import startOperationStreamHandler from '../internal/operation-stream'
import '../polyfill/app-polyfills.ts'
+// TODO: when actions are supported, this should be removed/changed
+process.env.__NEXT_PRIVATE_PREBUNDLED_REACT = 'next'
+import 'next/dist/server/require-hook'
import type { IncomingMessage } from 'node:http'
import type { RenderData } from 'types/turbopack'
import type { RenderOpts } from 'next/dist/server/app-render/types'
-import { renderToHTMLOrFlight } from 'next/dist/server/app-render/app-render'
import { RSC_VARY_HEADER } from 'next/dist/client/components/app-router-headers'
import { headersFromEntries, initProxiedHeaders } from '../internal/headers'
import { parse, ParsedUrlQuery } from 'node:querystring'
@@ -23,6 +25,10 @@ import { join } from 'node:path'
import { nodeFs } from 'next/dist/server/lib/node-fs-methods'
import { IncrementalCache } from 'next/dist/server/lib/incremental-cache'
+const {
+ renderToHTMLOrFlight,
+} = require('next/dist/compiled/next-server/app-page.runtime.dev')
+
installRequireAndChunkLoad()
const MIME_TEXT_HTML_UTF8 = 'text/html; charset=utf-8'
diff --git a/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx b/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx
index abdf23d0fd7d3..c4e1bce96aa5e 100644
--- a/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx
+++ b/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx
@@ -6,7 +6,7 @@ import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-we
import { callServer } from 'next/dist/client/app-call-server'
import { linkGc } from 'next/dist/client/app-link-gc'
-import { HeadManagerContext } from 'next/dist/shared/lib/head-manager-context'
+import { HeadManagerContext } from 'next/dist/shared/lib/head-manager-context.shared-runtime'
import { initializeHMR } from '@vercel/turbopack-next/dev/client'
diff --git a/packages/next-swc/crates/next-core/js/src/internal/page-server-handler.tsx b/packages/next-swc/crates/next-core/js/src/internal/page-server-handler.tsx
index 6182b2d7d4539..cecafb35f77a7 100644
--- a/packages/next-swc/crates/next-core/js/src/internal/page-server-handler.tsx
+++ b/packages/next-swc/crates/next-core/js/src/internal/page-server-handler.tsx
@@ -3,11 +3,12 @@
import { IPC } from '@vercel/turbopack-node/ipc/index'
import 'next/dist/server/node-polyfill-fetch.js'
+import 'next/dist/server/require-hook'
import './shims'
import type { IncomingMessage, ServerResponse } from 'node:http'
-import { renderToHTML, RenderOpts } from 'next/dist/server/render'
+import type { RenderOpts } from 'next/dist/server/render'
import { getRedirectStatus } from 'next/dist/lib/redirect-status'
import { PERMANENT_REDIRECT_STATUS } from 'next/dist/shared/lib/constants'
import { buildStaticPaths } from 'next/dist/build/utils'
@@ -21,6 +22,9 @@ import type { RenderData } from 'types/turbopack'
import type { ChunkGroup } from 'types/next'
import type { NextComponentType } from 'next/types'
import { parse } from 'node:querystring'
+const {
+ renderToHTML,
+} = require('next/dist/compiled/next-server/pages.runtime.dev')
const ipc = IPC as Ipc
diff --git a/packages/next-swc/crates/next-core/src/app_source.rs b/packages/next-swc/crates/next-core/src/app_source.rs
index e5af263c3d6bd..738f5a4bf938f 100644
--- a/packages/next-swc/crates/next-core/src/app_source.rs
+++ b/packages/next-swc/crates/next-core/src/app_source.rs
@@ -2,7 +2,7 @@ use std::{collections::HashMap, io::Write as _, iter::once};
use anyhow::{bail, Result};
use indexmap::indexmap;
-use indoc::indoc;
+use indoc::formatdoc;
use serde_json::Value as JsonValue;
use turbo_tasks::Vc;
use turbopack_binding::{
@@ -968,13 +968,18 @@ impl AppRenderer {
.emit();
}
- let mut result = RopeBuilder::from(indoc! {"
- \"TURBOPACK { chunking-type: isolatedParallel; transition: next-edge-server-component }\";
+ let mut result = RopeBuilder::from(
+ formatdoc!(
+ "
+ \"TURBOPACK {{ chunking-type: isolatedParallel; transition: {rsc_transition} }}\";
import GlobalErrorMod from \"next/dist/client/components/error-boundary\"
- const { GlobalError } = GlobalErrorMod;
- \"TURBOPACK { chunking-type: isolatedParallel; transition: next-edge-server-component }\";
+ const {{ GlobalError }} = GlobalErrorMod;
+ \"TURBOPACK {{ chunking-type: isolatedParallel; transition: {rsc_transition} }}\";
import base from \"next/dist/server/app-render/entry-base\"\n
- "});
+ "
+ )
+ .into_bytes(),
+ );
for import in loader_tree_module.imports {
writeln!(result, "{import}")?;
diff --git a/packages/next-swc/crates/next-core/src/next_edge/context.rs b/packages/next-swc/crates/next-core/src/next_edge/context.rs
index 54c7dd3331a63..cfe9eebf19f94 100644
--- a/packages/next-swc/crates/next-core/src/next_edge/context.rs
+++ b/packages/next-swc/crates/next-core/src/next_edge/context.rs
@@ -96,10 +96,9 @@ pub async fn get_edge_resolve_options_context(
];
match ty {
- ServerContextType::AppRSC { .. } | ServerContextType::AppRoute { .. } => {
- custom_conditions.push("react-server".to_string())
- }
- ServerContextType::Pages { .. }
+ ServerContextType::AppRSC { .. } => custom_conditions.push("react-server".to_string()),
+ ServerContextType::AppRoute { .. }
+ | ServerContextType::Pages { .. }
| ServerContextType::PagesData { .. }
| ServerContextType::AppSSR { .. }
| ServerContextType::Middleware { .. } => {}
diff --git a/packages/next-swc/crates/next-core/src/next_edge/route_transition.rs b/packages/next-swc/crates/next-core/src/next_edge/route_transition.rs
index de0bd2f2e7bf7..05326de255203 100644
--- a/packages/next-swc/crates/next-core/src/next_edge/route_transition.rs
+++ b/packages/next-swc/crates/next-core/src/next_edge/route_transition.rs
@@ -58,24 +58,26 @@ impl Transition for NextEdgeRouteTransition {
#[turbo_tasks::function]
async fn process_module(
- &self,
+ self: Vc,
asset: Vc>,
context: Vc,
) -> Result>> {
+ let new_context = self.process_context(context);
+ let this = self.await?;
let new_asset = route_bootstrap(
asset,
- Vc::upcast(context),
- self.base_path,
- self.bootstrap_asset,
+ Vc::upcast(new_context),
+ this.base_path,
+ this.bootstrap_asset,
Vc::cell(indexmap! {
- "NAME".to_string() => self.entry_name.clone(),
+ "NAME".to_string() => this.entry_name.clone(),
}),
);
let asset = ChunkGroupFilesAsset {
module: Vc::upcast(new_asset),
- client_root: self.output_path,
- chunking_context: self.edge_chunking_context,
+ client_root: this.output_path,
+ chunking_context: this.edge_chunking_context,
runtime_entries: None,
};
diff --git a/packages/next-swc/crates/next-core/src/next_import_map.rs b/packages/next-swc/crates/next-core/src/next_import_map.rs
index e05ac926c139f..c530f3bcb9290 100644
--- a/packages/next-swc/crates/next-core/src/next_import_map.rs
+++ b/packages/next-swc/crates/next-core/src/next_import_map.rs
@@ -216,25 +216,26 @@ pub async fn get_next_server_import_map(
let ty = ty.into_value();
insert_next_server_special_aliases(&mut import_map, ty, mode, NextRuntime::NodeJs).await?;
- let external = ImportMapping::External(None).cell();
+ let external: Vc = ImportMapping::External(None).cell();
+ import_map.insert_exact_alias("next/dist/server/require-hook", external);
match ty {
ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => {
- import_map.insert_exact_alias("next", external);
- import_map.insert_wildcard_alias("next/", external);
import_map.insert_exact_alias("react", external);
import_map.insert_wildcard_alias("react/", external);
import_map.insert_exact_alias("react-dom", external);
import_map.insert_wildcard_alias("react-dom/", external);
import_map.insert_exact_alias("styled-jsx", external);
import_map.insert_wildcard_alias("styled-jsx/", external);
- import_map.insert_exact_alias("react-server-dom-webpack/", external);
+ import_map.insert_wildcard_alias("react-server-dom-webpack/", external);
+ // TODO: we should not bundle next/dist/build/utils in the pages renderer at all
+ import_map.insert_wildcard_alias("next/dist/build/utils", external);
}
ServerContextType::AppSSR { .. }
| ServerContextType::AppRSC { .. }
| ServerContextType::AppRoute { .. } => {
match mode {
- NextMode::Development | NextMode::Build => {
+ NextMode::Build => {
import_map.insert_wildcard_alias("next/dist/server/", external);
import_map.insert_wildcard_alias("next/dist/shared/", external);
}
@@ -242,6 +243,7 @@ pub async fn get_next_server_import_map(
// The sandbox can't be bundled and needs to be external
import_map.insert_exact_alias("next/dist/server/web/sandbox", external);
}
+ NextMode::Development => {}
}
import_map.insert_exact_alias(
"next/head",
@@ -377,6 +379,11 @@ async fn insert_next_server_special_aliases(
NextRuntime::Edge => request_to_import_mapping(context_dir, request),
NextRuntime::NodeJs => external_request_to_import_mapping(request),
};
+ let passthrough_external_if_node =
+ move |context_dir: Vc, request: &str| match runtime {
+ NextRuntime::Edge => request_to_import_mapping(context_dir, request),
+ NextRuntime::NodeJs => ImportMapping::External(None).cell(),
+ };
match (mode, ty) {
(_, ServerContextType::Pages { pages_dir }) => {
import_map.insert_exact_alias(
@@ -413,12 +420,7 @@ async fn insert_next_server_special_aliases(
(_, ServerContextType::PagesData { .. }) => {}
// In development, we *always* use the bundled version of React, even in
// SSR, since we're bundling Next.js alongside it.
- (
- NextMode::DevServer,
- ServerContextType::AppSSR { app_dir }
- | ServerContextType::AppRSC { app_dir, .. }
- | ServerContextType::AppRoute { app_dir },
- ) => {
+ (NextMode::DevServer, ServerContextType::AppSSR { app_dir }) => {
import_map.insert_exact_alias(
"@opentelemetry/api",
// TODO(WEB-625) this actually need to prefer the local version of
@@ -427,28 +429,40 @@ async fn insert_next_server_special_aliases(
);
import_map.insert_exact_alias(
"react",
- request_to_import_mapping(app_dir, "next/dist/compiled/react"),
+ passthrough_external_if_node(app_dir, "next/dist/compiled/react"),
);
import_map.insert_wildcard_alias(
"react/",
- request_to_import_mapping(app_dir, "next/dist/compiled/react/*"),
+ passthrough_external_if_node(app_dir, "next/dist/compiled/react/*"),
);
import_map.insert_exact_alias(
"react-dom",
- request_to_import_mapping(
+ passthrough_external_if_node(
app_dir,
"next/dist/compiled/react-dom/server-rendering-stub.js",
),
);
import_map.insert_wildcard_alias(
"react-dom/",
- request_to_import_mapping(app_dir, "next/dist/compiled/react-dom/*"),
+ passthrough_external_if_node(app_dir, "next/dist/compiled/react-dom/*"),
+ );
+ import_map.insert_exact_alias(
+ "styled-jsx",
+ passthrough_external_if_node(app_dir, "next/dist/compiled/styled-jsx"),
+ );
+ import_map.insert_wildcard_alias(
+ "styled-jsx/",
+ passthrough_external_if_node(app_dir, "next/dist/compiled/styled-jsx/*"),
);
import_map.insert_wildcard_alias(
"react-server-dom-webpack/",
- request_to_import_mapping(app_dir, "next/dist/compiled/react-server-dom-webpack/*"),
+ passthrough_external_if_node(
+ app_dir,
+ "next/dist/compiled/react-server-dom-webpack/*",
+ ),
);
}
+
// NOTE(alexkirsz) This logic maps loosely to
// `next.js/packages/next/src/build/webpack-config.ts`, where:
//
@@ -460,7 +474,7 @@ async fn insert_next_server_special_aliases(
// * passes through (react|react-dom|react-server-dom-webpack)/(.*) to
// next/dist/compiled/$1/$2
(
- NextMode::Build | NextMode::Development,
+ NextMode::Build | NextMode::Development | NextMode::DevServer,
ServerContextType::AppRSC { app_dir, .. } | ServerContextType::AppRoute { app_dir },
) => {
import_map.insert_exact_alias(
@@ -469,10 +483,20 @@ async fn insert_next_server_special_aliases(
// @opentelemetry/api
request_to_import_mapping(app_dir, "next/dist/compiled/@opentelemetry/api"),
);
- import_map.insert_exact_alias(
- "react",
- request_to_import_mapping(app_dir, "next/dist/compiled/react/react.shared-subset"),
- );
+ if matches!(ty, ServerContextType::AppRSC { .. }) {
+ import_map.insert_exact_alias(
+ "react",
+ request_to_import_mapping(
+ app_dir,
+ "next/dist/compiled/react/react.shared-subset",
+ ),
+ );
+ } else {
+ import_map.insert_exact_alias(
+ "react",
+ request_to_import_mapping(app_dir, "next/dist/compiled/react"),
+ );
+ }
import_map.insert_exact_alias(
"react-dom",
request_to_import_mapping(
diff --git a/packages/next-swc/crates/next-core/src/next_server/context.rs b/packages/next-swc/crates/next-core/src/next_server/context.rs
index e7485ff100ade..1d242498b36df 100644
--- a/packages/next-swc/crates/next-core/src/next_server/context.rs
+++ b/packages/next-swc/crates/next-core/src/next_server/context.rs
@@ -46,7 +46,10 @@ use crate::{
next_import_map::{get_next_server_import_map, mdx_import_source_file},
next_server::resolve::ExternalPredicate,
next_shared::{
- resolve::{ModuleFeatureReportResolvePlugin, UnsupportedModulesResolvePlugin},
+ resolve::{
+ ModuleFeatureReportResolvePlugin, NextExternalResolvePlugin,
+ UnsupportedModulesResolvePlugin,
+ },
transforms::{
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
styled_components::get_styled_components_transform_plugin,
@@ -108,10 +111,9 @@ pub async fn get_server_resolve_options_context(
let mut custom_conditions = vec![mode.node_env().to_string(), "node".to_string()];
match ty {
- ServerContextType::AppRSC { .. } | ServerContextType::AppRoute { .. } => {
- custom_conditions.push("react-server".to_string())
- }
- ServerContextType::Pages { .. }
+ ServerContextType::AppRSC { .. } => custom_conditions.push("react-server".to_string()),
+ ServerContextType::AppRoute { .. }
+ | ServerContextType::Pages { .. }
| ServerContextType::PagesData { .. }
| ServerContextType::AppSSR { .. }
| ServerContextType::Middleware { .. } => {}
@@ -121,12 +123,15 @@ pub async fn get_server_resolve_options_context(
ExternalPredicate::AllExcept(next_config.transpile_packages()).cell(),
);
+ let next_external_plugin = NextExternalResolvePlugin::new(project_path);
+
let plugins = match ty {
ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => {
vec![
Vc::upcast(module_feature_report_resolve_plugin),
Vc::upcast(external_cjs_modules_plugin),
Vc::upcast(unsupported_modules_resolve_plugin),
+ Vc::upcast(next_external_plugin),
]
}
ServerContextType::AppSSR { .. }
@@ -137,6 +142,7 @@ pub async fn get_server_resolve_options_context(
Vc::upcast(module_feature_report_resolve_plugin),
Vc::upcast(server_component_externals_plugin),
Vc::upcast(unsupported_modules_resolve_plugin),
+ Vc::upcast(next_external_plugin),
]
}
};
diff --git a/packages/next-swc/crates/next-core/src/next_shared/resolve.rs b/packages/next-swc/crates/next-core/src/next_shared/resolve.rs
index 013f87f9fd5b6..ea7f044c12cc8 100644
--- a/packages/next-swc/crates/next-core/src/next_shared/resolve.rs
+++ b/packages/next-swc/crates/next-core/src/next_shared/resolve.rs
@@ -13,7 +13,7 @@ use turbopack_binding::{
parse::Request,
pattern::Pattern,
plugin::{ResolvePlugin, ResolvePluginCondition},
- ResolveResultOption,
+ ResolveResult, ResolveResultItem, ResolveResultOption,
},
},
};
@@ -102,6 +102,55 @@ impl ResolvePlugin for UnsupportedModulesResolvePlugin {
}
}
+#[turbo_tasks::value]
+pub(crate) struct NextExternalResolvePlugin {
+ root: Vc,
+}
+
+#[turbo_tasks::value_impl]
+impl NextExternalResolvePlugin {
+ #[turbo_tasks::function]
+ pub fn new(root: Vc) -> Vc {
+ NextExternalResolvePlugin { root }.cell()
+ }
+}
+
+#[turbo_tasks::value_impl]
+impl ResolvePlugin for NextExternalResolvePlugin {
+ #[turbo_tasks::function]
+ fn after_resolve_condition(&self) -> Vc {
+ ResolvePluginCondition::new(
+ self.root.root(),
+ Glob::new(
+ "**/next/dist/**/*.{external,shared-runtime,runtime.dev,runtime.prod}.js"
+ .to_string(),
+ ),
+ )
+ }
+
+ #[turbo_tasks::function]
+ async fn after_resolve(
+ &self,
+ fs_path: Vc,
+ _context: Vc,
+ _request: Vc,
+ ) -> Result> {
+ let raw_fs_path = &*fs_path.await?;
+ let path = raw_fs_path.path.to_string();
+ // Find the starting index of 'next/dist' and slice from that point. It should
+ // always be found since the glob pattern above is specific enough.
+ let starting_index = path.find("next/dist").unwrap();
+ // Replace '/esm/' with '/' to match the CJS version of the file.
+ let modified_path = &path[starting_index..].replace("/esm/", "/");
+ Ok(Vc::cell(Some(
+ ResolveResult::primary(ResolveResultItem::OriginalReferenceTypeExternal(
+ modified_path.to_string(),
+ ))
+ .into(),
+ )))
+ }
+}
+
/// A resolver plugin tracks the usage of certain import paths, emit
/// telemetry events if there is a match.
#[turbo_tasks::value]
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/api/basic/issues/lint TP1004 fs.readFile(__q____q____q____star__0__-3e4dd8.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/api/basic/issues/lint TP1004 fs.readFile(__q____q____q____star__0__-3e4dd8.txt
new file mode 100644
index 0000000000000..a5ad94c85fb0a
--- /dev/null
+++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/api/basic/issues/lint TP1004 fs.readFile(__q____q____q____star__0__-3e4dd8.txt
@@ -0,0 +1,17 @@
+warning - [parse] [project]/packages/next/dist/server/web/sandbox/context.js /packages/next/dist/server/web/sandbox/context.js:64:56 lint TP1004 fs.readFile(???*0*) is very dynamic
+ 60 | }
+ 61 | async function loadWasm(wasm) {
+ 62 | const modules = {};
+ 63 | await Promise.all(wasm.map(async (binding)=>{
+ + v
+ 64 + const module1 = await WebAssembly.compile(await _fs.promises.readFile(binding.filePath));
+ + ^
+ 65 | modules[binding.name] = module1;
+ 66 | }));
+ 67 | return modules;
+ 68 | }
+
+ - *0* ???*1*["filePath"]
+ ⚠️ unknown object
+ - *1* binding
+ ⚠️ pattern without value
\ No newline at end of file
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/api/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star_-e11df4.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/api/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star_-e11df4.txt
new file mode 100644
index 0000000000000..c80db085946c2
--- /dev/null
+++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/api/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star_-e11df4.txt
@@ -0,0 +1,15 @@
+warning - [parse] [project]/packages/next/dist/server/web/sandbox/context.js /packages/next/dist/server/web/sandbox/context.js:355:28 lint TP1004 fs.readFileSync(???*0*, "utf-8") is very dynamic
+ 351 | }
+ 352 | const moduleContext = lazyModuleContext;
+ 353 | const evaluateInContext = (filepath)=>{
+ 354 | if (!moduleContext.paths.has(filepath)) {
+ + v
+ 355 + const content = (0, _fs.readFileSync)(filepath, "utf-8");
+ + ^
+ 356 | try {
+ 357 | (0, _vm.runInContext)(content, moduleContext.runtime.context, {
+ 358 | filename: filepath
+ 359 | });
+
+ - *0* filepath
+ ⚠️ pattern without value
\ No newline at end of file
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/remotepattern/issues/Error during SSR Rendering-8ad1c9.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/remotepattern/issues/Error during SSR Rendering-8ad1c9.txt
new file mode 100644
index 0000000000000..39e97b4ccc85e
--- /dev/null
+++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/remotepattern/issues/Error during SSR Rendering-8ad1c9.txt
@@ -0,0 +1,47 @@
+error - [rendering] [root of the server]/invalid Error during SSR Rendering
+ Error: Invalid src prop (https://image-optimization-test.vercel.app/test.webp) on `next/image`, hostname "image-optimization-test.vercel.app" is not configured under images in your `next.config.js`
+
+ Debug info:
+ - Error: Invalid src prop (https://image-optimization-test.vercel.app/test.webp) on `next/image`, hostname "image-optimization-test.vercel.app" is not configured under images in your `next.config.js`
+ See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
+ at defaultLoader (packages/next/dist/shared/lib/image-loader.js:41:27)
+ 37 | process.env.NEXT_RUNTIME !== "edge") {
+ 38 | // We use dynamic require because this should only error in development
+ 39 | const { hasMatch } = require("./match-remote-pattern");
+ 40 | if (!hasMatch(config.domains, config.remotePatterns, parsedSrc)) {
+ | v
+ 41 + throw new Error("Invalid src prop (" + src + ') on `next/image`, hostname "' + parsedSrc.hostname + '" i...xt.config.js`\n' + "See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host");
+ | ^
+ 42 | }
+ 43 | }
+ 44 | }
+ 45 | }
+
+ at (packages/next/dist/shared/lib/get-img-props.js:101:36)
+ 97 | const { widths , kind } = getWidths(config, width, sizes);
+ 98 | const last = widths.length - 1;
+ 99 | return {
+ 100 | sizes: !sizes && kind === "w" ? "100vw" : sizes,
+ | v
+ 101 + srcSet: widths.map((w, i)=>loader({
+ | ^
+ 102 | config,
+ 103 | src,
+ 104 | quality,
+ 105 | width: w
+
+ at generateImgAttrs (packages/next/dist/shared/lib/get-img-props.js:101:24)
+ 97 | const { widths , kind } = getWidths(config, width, sizes);
+ 98 | const last = widths.length - 1;
+ 99 | return {
+ 100 | sizes: !sizes && kind === "w" ? "100vw" : sizes,
+ | v
+ 101 + srcSet: widths.map((w, i)=>loader({
+ | ^
+ 102 | config,
+ 103 | src,
+ 104 | quality,
+ 105 | width: w
+
+ at getImgProps (packages/next/dist/shared/lib/get-img-props.js:392:27)
+ at (packages/next/dist/client/image-component.js:275:82)
\ No newline at end of file
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/remotepattern/issues/Error during SSR Rendering-d9114a.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/remotepattern/issues/Error during SSR Rendering-d9114a.txt
deleted file mode 100644
index ce775cb8df7e8..0000000000000
--- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/remotepattern/issues/Error during SSR Rendering-d9114a.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-error - [rendering] [root of the server]/invalid Error during SSR Rendering
- Error: Invalid src prop (https://image-optimization-test.vercel.app/test.webp) on `next/image`, hostname "image-optimization-test.vercel.app" is not configured under images in your `next.config.js`
-
- Debug info:
- - Error: Invalid src prop (https://image-optimization-test.vercel.app/test.webp) on `next/image`, hostname "image-optimization-test.vercel.app" is not configured under images in your `next.config.js`
- See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
\ No newline at end of file
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/input/app/test.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/input/app/test.js
index e2c2f40a06dd7..108b763da879c 100644
--- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/input/app/test.js
+++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/input/app/test.js
@@ -120,7 +120,7 @@ function runTests() {
expect(json).toMatchObject({
edgeThenNode: 'node',
nodeThenEdge: 'node',
- reactServer: 'react-server',
+ reactServer: 'default',
})
})
@@ -129,7 +129,7 @@ function runTests() {
expect(json).toMatchObject({
edgeThenNode: 'edge',
nodeThenEdge: 'edge',
- reactServer: 'react-server',
+ reactServer: 'default',
})
})
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/Error resolving commonjs request-b2593b.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/Error resolving commonjs request-b2593b.txt
deleted file mode 100644
index 72c048d7b6481..0000000000000
--- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/Error resolving commonjs request-b2593b.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-error - [resolve] [project]/packages/next/dist/compiled/nanoid/index.cjs /packages/next/dist/compiled/nanoid/index.cjs:1:45 Error resolving commonjs request
- + v---------------v
- 1 + (()=>{var e={113:e=>{"use strict";e.exports=require("crypto")},660:(e,r,t)=>{let l=t(113);let{urlAlphabet:a}=t(591);const n=128;let _,u;let fillPool=e=>{if(!_||...ndefined")__nccwpck_require__.ab=__dirname+"/";var t=__nccwpck_require__(660);module.exports=t})();
- + ^---------------^
-
- unable to resolve module "crypto"
-
- | It was not possible to find the requested file.
- | Parsed request as written in source code: module "crypto"
- | Path where resolving has started: [project]/packages/next/dist/compiled/nanoid/index.cjs
- | Type of request: commonjs request
- | Import map: No import map entry
- |
\ No newline at end of file
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/Error resolving commonjs request-dd84e7.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/Error resolving commonjs request-dd84e7.txt
deleted file mode 100644
index 72c048d7b6481..0000000000000
--- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/Error resolving commonjs request-dd84e7.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-error - [resolve] [project]/packages/next/dist/compiled/nanoid/index.cjs /packages/next/dist/compiled/nanoid/index.cjs:1:45 Error resolving commonjs request
- + v---------------v
- 1 + (()=>{var e={113:e=>{"use strict";e.exports=require("crypto")},660:(e,r,t)=>{let l=t(113);let{urlAlphabet:a}=t(591);const n=128;let _,u;let fillPool=e=>{if(!_||...ndefined")__nccwpck_require__.ab=__dirname+"/";var t=__nccwpck_require__(660);module.exports=t})();
- + ^---------------^
-
- unable to resolve module "crypto"
-
- | It was not possible to find the requested file.
- | Parsed request as written in source code: module "crypto"
- | Path where resolving has started: [project]/packages/next/dist/compiled/nanoid/index.cjs
- | Type of request: commonjs request
- | Import map: No import map entry
- |
\ No newline at end of file
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/lint TP1004 fs.readFile(__q____q____q____star__0__-76c34b.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/lint TP1004 fs.readFile(__q____q____q____star__0__-76c34b.txt
new file mode 100644
index 0000000000000..a5ad94c85fb0a
--- /dev/null
+++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/lint TP1004 fs.readFile(__q____q____q____star__0__-76c34b.txt
@@ -0,0 +1,17 @@
+warning - [parse] [project]/packages/next/dist/server/web/sandbox/context.js /packages/next/dist/server/web/sandbox/context.js:64:56 lint TP1004 fs.readFile(???*0*) is very dynamic
+ 60 | }
+ 61 | async function loadWasm(wasm) {
+ 62 | const modules = {};
+ 63 | await Promise.all(wasm.map(async (binding)=>{
+ + v
+ 64 + const module1 = await WebAssembly.compile(await _fs.promises.readFile(binding.filePath));
+ + ^
+ 65 | modules[binding.name] = module1;
+ 66 | }));
+ 67 | return modules;
+ 68 | }
+
+ - *0* ???*1*["filePath"]
+ ⚠️ unknown object
+ - *1* binding
+ ⚠️ pattern without value
\ No newline at end of file
diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/lint TP1004 fs.readFileSync(__q____q____q____star_-f7e52c.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/lint TP1004 fs.readFileSync(__q____q____q____star_-f7e52c.txt
new file mode 100644
index 0000000000000..c80db085946c2
--- /dev/null
+++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/import/conditions/issues/lint TP1004 fs.readFileSync(__q____q____q____star_-f7e52c.txt
@@ -0,0 +1,15 @@
+warning - [parse] [project]/packages/next/dist/server/web/sandbox/context.js /packages/next/dist/server/web/sandbox/context.js:355:28 lint TP1004 fs.readFileSync(???*0*, "utf-8") is very dynamic
+ 351 | }
+ 352 | const moduleContext = lazyModuleContext;
+ 353 | const evaluateInContext = (filepath)=>{
+ 354 | if (!moduleContext.paths.has(filepath)) {
+ + v
+ 355 + const content = (0, _fs.readFileSync)(filepath, "utf-8");
+ + ^
+ 356 | try {
+ 357 | (0, _vm.runInContext)(content, moduleContext.runtime.context, {
+ 358 | filename: filepath
+ 359 | });
+
+ - *0* filepath
+ ⚠️ pattern without value
\ No newline at end of file
diff --git a/packages/next/config.d.ts b/packages/next/config.d.ts
index 78fe148a8dc9b..2da1ee3c4029c 100644
--- a/packages/next/config.d.ts
+++ b/packages/next/config.d.ts
@@ -1,3 +1,3 @@
-import getConfig from './dist/shared/lib/runtime-config'
-export * from './dist/shared/lib/runtime-config'
+import getConfig from './dist/shared/lib/runtime-config.shared-runtime'
+export * from './dist/shared/lib/runtime-config.shared-runtime'
export default getConfig
diff --git a/packages/next/config.js b/packages/next/config.js
index 2da980d8b0065..6510748638097 100644
--- a/packages/next/config.js
+++ b/packages/next/config.js
@@ -1 +1 @@
-module.exports = require('./dist/shared/lib/runtime-config')
+module.exports = require('./dist/shared/lib/runtime-config.shared-runtime')
diff --git a/packages/next/package.json b/packages/next/package.json
index bebc8aa2b209b..75b2e78962ffc 100644
--- a/packages/next/package.json
+++ b/packages/next/package.json
@@ -83,6 +83,7 @@
},
"taskr": {
"requires": [
+ "./taskfile-webpack.js",
"./taskfile-ncc.js",
"./taskfile-swc.js",
"./taskfile-watch.js"
@@ -299,6 +300,7 @@
"tar": "6.1.15",
"taskr": "1.1.0",
"terser": "5.14.1",
+ "terser-webpack-plugin": "5.3.9",
"text-table": "0.2.0",
"timers-browserify": "2.0.12",
"tty-browserify": "0.0.1",
diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts
index 8ad7407b4be45..b0e0870ca1392 100644
--- a/packages/next/src/build/index.ts
+++ b/packages/next/src/build/index.ts
@@ -143,8 +143,13 @@ import { createClientRouterFilter } from '../lib/create-client-router-filter'
import { createValidFileMatcher } from '../server/lib/find-page-file'
import { startTypeChecking } from './type-check'
import { generateInterceptionRoutesRewrites } from '../lib/generate-interception-routes-rewrites'
+
import { buildDataRoute } from '../server/lib/router-utils/build-data-route'
-import { baseOverrides, experimentalOverrides } from '../server/require-hook'
+import {
+ baseOverrides,
+ defaultOverrides,
+ experimentalOverrides,
+} from '../server/require-hook'
import { initialize } from '../server/lib/incremental-cache-server'
import { nodeFs } from '../server/lib/node-fs-methods'
@@ -1243,6 +1248,7 @@ export default async function build(
forkOptions: {
env: {
...process.env,
+ __NEXT_PRIVATE_RENDER_RUNTIME: type,
__NEXT_INCREMENTAL_CACHE_IPC_PORT: ipcPort + '',
__NEXT_INCREMENTAL_CACHE_IPC_KEY: ipcValidationKey,
__NEXT_PRIVATE_PREBUNDLED_REACT:
@@ -2084,6 +2090,25 @@ export default async function build(
...Object.values(experimentalOverrides).map((override) =>
require.resolve(override)
),
+ ...(config.experimental.turbotrace
+ ? []
+ : Object.keys(defaultOverrides).map((value) =>
+ require.resolve(value, {
+ paths: [require.resolve('next/dist/server/require-hook')],
+ })
+ )),
+ require.resolve(
+ 'next/dist/compiled/next-server/app-page.runtime.prod'
+ ),
+ require.resolve(
+ 'next/dist/compiled/next-server/app-route.runtime.prod'
+ ),
+ require.resolve(
+ 'next/dist/compiled/next-server/pages.runtime.prod'
+ ),
+ require.resolve(
+ 'next/dist/compiled/next-server/pages-api.runtime.prod'
+ ),
]
// ensure we trace any dependencies needed for custom
@@ -2109,10 +2134,7 @@ export default async function build(
const minimalServerEntries = [
...sharedEntriesSet,
require.resolve(
- 'next/dist/compiled/minimal-next-server/next-server-cached.js'
- ),
- require.resolve(
- 'next/dist/compiled/minimal-next-server/next-server.js'
+ 'next/dist/compiled/next-server/server.runtime.prod'
),
].filter(Boolean)
diff --git a/packages/next/src/build/templates/app-page.ts b/packages/next/src/build/templates/app-page.ts
index c75509904c3a8..f0d2ab692e2aa 100644
--- a/packages/next/src/build/templates/app-page.ts
+++ b/packages/next/src/build/templates/app-page.ts
@@ -1,7 +1,7 @@
import type { LoaderTree } from '../../server/lib/app-dir-module'
// @ts-ignore this need to be imported from next/dist to be external
-import * as module from 'next/dist/server/future/route-modules/app-page/module'
+import * as module from 'next/dist/server/future/route-modules/app-page/module.compiled'
import { RouteKind } from '../../server/future/route-kind'
const AppPageRouteModule =
diff --git a/packages/next/src/build/templates/app-route.ts b/packages/next/src/build/templates/app-route.ts
index 50a8b6165a747..b4b8e5b0fe6cd 100644
--- a/packages/next/src/build/templates/app-route.ts
+++ b/packages/next/src/build/templates/app-route.ts
@@ -1,7 +1,8 @@
import '../../server/node-polyfill-headers'
// @ts-ignore this need to be imported from next/dist to be external
-import * as module from 'next/dist/server/future/route-modules/app-route/module'
+import * as module from 'next/dist/server/future/route-modules/app-route/module.compiled'
+
import type { AppRouteRouteModuleOptions } from '../../server/future/route-modules/app-route/module'
import { RouteKind } from '../../server/future/route-kind'
diff --git a/packages/next/src/build/templates/pages-api.ts b/packages/next/src/build/templates/pages-api.ts
index a48822f9ed75a..eaeec836cb61e 100644
--- a/packages/next/src/build/templates/pages-api.ts
+++ b/packages/next/src/build/templates/pages-api.ts
@@ -1,5 +1,6 @@
// @ts-ignore this need to be imported from next/dist to be external
-import * as module from 'next/dist/server/future/route-modules/pages-api/module'
+import * as module from 'next/dist/server/future/route-modules/pages-api/module.compiled'
+
import { RouteKind } from '../../server/future/route-kind'
import { hoist } from './helpers'
diff --git a/packages/next/src/build/templates/pages.ts b/packages/next/src/build/templates/pages.ts
index 3f3527e6650d6..b5def5d13c552 100644
--- a/packages/next/src/build/templates/pages.ts
+++ b/packages/next/src/build/templates/pages.ts
@@ -1,5 +1,5 @@
// @ts-ignore this need to be imported from next/dist to be external
-import * as module from 'next/dist/server/future/route-modules/pages/module'
+import * as module from 'next/dist/server/future/route-modules/pages/module.compiled'
import { RouteKind } from '../../server/future/route-kind'
import { hoist } from './helpers'
diff --git a/packages/next/src/build/utils.ts b/packages/next/src/build/utils.ts
index 867429c2ba901..423beb27f6dca 100644
--- a/packages/next/src/build/utils.ts
+++ b/packages/next/src/build/utils.ts
@@ -14,7 +14,7 @@ import type {
EdgeFunctionDefinition,
MiddlewareManifest,
} from './webpack/plugins/middleware-plugin'
-import type { StaticGenerationAsyncStorage } from '../client/components/static-generation-async-storage'
+import type { StaticGenerationAsyncStorage } from '../client/components/static-generation-async-storage.external'
import '../server/require-hook'
import '../server/node-polyfill-fetch'
@@ -65,7 +65,9 @@ import { nodeFs } from '../server/lib/node-fs-methods'
import * as ciEnvironment from '../telemetry/ci-info'
import { normalizeAppPath } from '../shared/lib/router/utils/app-paths'
import { denormalizeAppPagePath } from '../shared/lib/page-path/denormalize-app-path'
-import { AppRouteRouteModule } from '../server/future/route-modules/app-route/module'
+// import { AppRouteRouteModule } from '../server/future/route-modules/app-route/module'
+const { AppRouteRouteModule } =
+ require('../server/future/route-modules/app-route/module.compiled') as typeof import('../server/future/route-modules/app-route/module')
export type ROUTER_TYPE = 'pages' | 'app'
@@ -1389,7 +1391,9 @@ export async function isPageStatic({
const isPageStaticSpan = trace('is-page-static-utils', parentId)
return isPageStaticSpan
.traceAsyncFn(async () => {
- require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig)
+ require('../shared/lib/runtime-config.shared-runtime').setConfig(
+ runtimeEnvConfig
+ )
setHttpClientAndAgentOptions({
httpAgentOptions,
})
@@ -1673,7 +1677,9 @@ export async function hasCustomGetInitialProps(
runtimeEnvConfig: any,
checkingApp: boolean
): Promise {
- require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig)
+ require('../shared/lib/runtime-config.shared-runtime').setConfig(
+ runtimeEnvConfig
+ )
const components = await loadComponents({
distDir,
@@ -1696,7 +1702,9 @@ export async function getDefinedNamedExports(
distDir: string,
runtimeEnvConfig: any
): Promise> {
- require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig)
+ require('../shared/lib/runtime-config.shared-runtime').setConfig(
+ runtimeEnvConfig
+ )
const components = await loadComponents({
distDir,
pathname: page,
diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts
index f1f053d05eb9b..d1b7487618fe2 100644
--- a/packages/next/src/build/webpack-config.ts
+++ b/packages/next/src/build/webpack-config.ts
@@ -103,6 +103,19 @@ const reactPackagesRegex = /^(react|react-dom|react-server-dom-webpack)($|\/)/
const asyncStoragesRegex =
/next[\\/]dist[\\/](esm[\\/])?client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/
+const pathSeparators = '[/\\\\]'
+const optionalEsmPart = `((${pathSeparators}esm)?${pathSeparators})`
+const sharedRuntimeFileEnd = '(\\.shared-runtime(\\.js)?)$'
+const externalFileEnd = '(\\.external(\\.js)?)$'
+const nextDist = `next${pathSeparators}dist`
+
+const sharedRuntimePattern = new RegExp(
+ `${nextDist}${optionalEsmPart}.*${sharedRuntimeFileEnd}`
+)
+const externalPattern = new RegExp(
+ `${nextDist}${optionalEsmPart}.*${externalFileEnd}`
+)
+
// exports.
const edgeConditionNames = [
'edge-light',
@@ -1011,7 +1024,7 @@ export default async function getBaseWebpackConfig(
const customRootAliases: { [key: string]: string[] } = {}
if (dev) {
- const nextDist = 'next/dist/' + (isEdgeServer ? 'esm/' : '')
+ const nextDistPath = 'next/dist/' + (isEdgeServer ? 'esm/' : '')
customAppAliases[`${PAGES_DIR_ALIAS}/_app`] = [
...(pagesDir
? pageExtensions.reduce((prev, ext) => {
@@ -1019,7 +1032,7 @@ export default async function getBaseWebpackConfig(
return prev
}, [] as string[])
: []),
- `${nextDist}pages/_app.js`,
+ `${nextDistPath}pages/_app.js`,
]
customAppAliases[`${PAGES_DIR_ALIAS}/_error`] = [
...(pagesDir
@@ -1028,7 +1041,7 @@ export default async function getBaseWebpackConfig(
return prev
}, [] as string[])
: []),
- `${nextDist}pages/_error.js`,
+ `${nextDistPath}pages/_error.js`,
]
customDocumentAliases[`${PAGES_DIR_ALIAS}/_document`] = [
...(pagesDir
@@ -1037,7 +1050,7 @@ export default async function getBaseWebpackConfig(
return prev
}, [] as string[])
: []),
- `${nextDist}pages/_document.js`,
+ `${nextDistPath}pages/_document.js`,
]
}
@@ -1311,6 +1324,7 @@ export default async function getBaseWebpackConfig(
WEBPACK_LAYERS.serverSideRendering,
WEBPACK_LAYERS.appPagesBrowser,
WEBPACK_LAYERS.actionBrowser,
+ WEBPACK_LAYERS.appRouteHandler,
].includes(layer!)
if (
@@ -1367,7 +1381,7 @@ export default async function getBaseWebpackConfig(
}
const notExternalModules =
- /^(?:private-next-pages\/|next\/(?:dist\/pages\/|(?:app|document|link|image|legacy\/image|constants|dynamic|script|navigation|headers)$)|string-hash|private-next-rsc-action-validate|private-next-rsc-action-client-wrapper|private-next-rsc-action-proxy$)/
+ /^(?:private-next-pages\/|next\/(?:dist\/pages\/|(?:app|document|link|image|legacy\/image|constants|dynamic|script|navigation|headers|router)$)|string-hash|private-next-rsc-action-validate|private-next-rsc-action-client-wrapper|private-next-rsc-action-proxy$)/
if (notExternalModules.test(request)) {
return
}
@@ -1390,41 +1404,59 @@ export default async function getBaseWebpackConfig(
// Also disable esm request when appDir is enabled
const isEsmRequested = dependencyType === 'esm'
+ /**
+ * @param localRes the full path to the file
+ * @returns the externalized path
+ * @description returns an externalized path if the file is a Next.js file and ends with either `.shared-runtime.js` or `.external.js`
+ * This is used to ensure that files used across the rendering runtime(s) and the user code are one and the same. The logic in this function
+ * will rewrite the require to the correct bundle location depending on the layer at which the file is being used.
+ */
const isLocalCallback = (localRes: string) => {
- // Makes sure dist/shared and dist/server are not bundled
- // we need to process shared `router/router`, `head` and `dynamic`,
- // so that the DefinePlugin can inject process.env values.
-
- // Treat next internals as non-external for server layer
- if (isWebpackServerLayer(layer)) {
- return
+ const isSharedRuntime = sharedRuntimePattern.test(localRes)
+ const isExternal = externalPattern.test(localRes)
+
+ // if the file ends with .external, we need to make it a commonjs require in all cases
+ // this is used mainly to share the async local storage across the routing, rendering and user layers.
+ if (isExternal) {
+ // it's important we return the path that starts with `next/dist/` here instead of the absolute path
+ // otherwise NFT will get tripped up
+ return `commonjs ${localRes.replace(/.*?next[/\\]dist/, 'next/dist')}`
}
+ // if the file ends with .shared-runtime, we need to make it point to the correct bundle depending on the layer
+ // this is because each shared-runtime files are unique per bundle, so if you use app-router context in pages,
+ // it'll be a different instance than the one used in the app-router runtime.
+ if (isSharedRuntime) {
+ if (dev) {
+ return `commonjs ${localRes}`
+ }
- const isNextExternal =
- /next[/\\]dist[/\\](esm[\\/])?(shared|server)[/\\](?!lib[/\\](router[/\\]router|dynamic|app-dynamic|image-external|lazy-dynamic|head[^-]))/.test(
- localRes
- ) ||
- // There's no need to bundle the dev overlay
- (process.env.NODE_ENV === 'development' &&
- /next[/\\]dist[/\\](esm[/\\])?client[/\\]components[/\\]react-dev-overlay[/\\]/.test(
- localRes
- ))
-
- if (isNextExternal) {
- // Generate Next.js external import
- const externalRequest = path.posix.join(
- 'next',
- 'dist',
- path
- .relative(
- // Root of Next.js package:
- path.join(__dirname, '..'),
- localRes
- )
- // Windows path normalization
- .replace(/\\/g, '/')
+ const name = path.parse(localRes).name.replace('.shared-runtime', '')
+
+ const camelCaseName = name.replace(/-([a-z])/g, (_, w) =>
+ w.toUpperCase()
)
- return `commonjs ${externalRequest}`
+
+ // there's no externals for API routes but if need be, they'll need to be added here and have
+ // their own layer
+ const runtime =
+ layer === 'app-route-handler'
+ ? 'app-route'
+ : isAppLayer
+ ? 'app-page'
+ : 'pages'
+ return [
+ 'commonjs ' +
+ path.posix.join(
+ 'next',
+ 'dist',
+ 'compiled',
+ 'next-server',
+ `${runtime}.runtime.${dev ? 'dev' : 'prod'}`
+ ),
+ 'default',
+ 'sharedModules',
+ camelCaseName,
+ ]
}
}
@@ -1445,6 +1477,10 @@ export default async function getBaseWebpackConfig(
return
}
+ if (/^next\/dist\/compiled\/next-server/.test(request)) {
+ return `commonjs ${request}`
+ }
+
if (
/^next\/dist\/shared\/(?!lib\/router\/router)/.test(request) ||
/^next\/dist\/compiled\/.*\.c?js$/.test(request)
@@ -2031,6 +2067,14 @@ export default async function getBaseWebpackConfig(
},
...(hasAppDir
? [
+ {
+ layer: WEBPACK_LAYERS.appRouteHandler,
+ test: new RegExp(
+ `private-next-app-dir\\/.*\\/route\\.(${pageExtensions.join(
+ '|'
+ )})$`
+ ),
+ },
{
// Make sure that AsyncLocalStorage module instance is shared between server and client
// layers.
@@ -2239,7 +2283,7 @@ export default async function getBaseWebpackConfig(
WEBPACK_LAYERS.appPagesBrowser,
],
},
- exclude: [asyncStoragesRegex, codeCondition.exclude],
+ exclude: [codeCondition.exclude],
use: [
...(dev && isClient
? [
diff --git a/packages/next/src/build/webpack/plugins/next-types-plugin/index.ts b/packages/next/src/build/webpack/plugins/next-types-plugin/index.ts
index 2be12daecdbc6..c2b1089df5b3f 100644
--- a/packages/next/src/build/webpack/plugins/next-types-plugin/index.ts
+++ b/packages/next/src/build/webpack/plugins/next-types-plugin/index.ts
@@ -442,7 +442,7 @@ declare module 'next/link' {
declare module 'next/navigation' {
export * from 'next/dist/client/components/navigation.js'
- import type { NavigateOptions, AppRouterInstance as OriginalAppRouterInstance } from 'next/dist/shared/lib/app-router-context.js'
+ import type { NavigateOptions, AppRouterInstance as OriginalAppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime.js'
interface AppRouterInstance extends OriginalAppRouterInstance {
/**
* Navigate to the provided href.
@@ -575,8 +575,11 @@ export class NextTypesPlugin {
}
return
}
-
- if (mod.layer !== WEBPACK_LAYERS.reactServerComponents) return
+ if (
+ mod.layer !== WEBPACK_LAYERS.reactServerComponents &&
+ mod.layer !== WEBPACK_LAYERS.appRouteHandler
+ )
+ return
const IS_LAYOUT = /[/\\]layout\.[^./\\]+$/.test(mod.resource)
const IS_PAGE = !IS_LAYOUT && /[/\\]page\.[^.]+$/.test(mod.resource)
diff --git a/packages/next/src/client/app-index.tsx b/packages/next/src/client/app-index.tsx
index 8f82d244837e6..47c0bd13f369e 100644
--- a/packages/next/src/client/app-index.tsx
+++ b/packages/next/src/client/app-index.tsx
@@ -7,8 +7,8 @@ import React, { use } from 'react'
// eslint-disable-next-line import/no-extraneous-dependencies
import { createFromReadableStream } from 'react-server-dom-webpack/client'
-import { HeadManagerContext } from '../shared/lib/head-manager-context'
-import { GlobalLayoutRouterContext } from '../shared/lib/app-router-context'
+import { HeadManagerContext } from '../shared/lib/head-manager-context.shared-runtime'
+import { GlobalLayoutRouterContext } from '../shared/lib/app-router-context.shared-runtime'
import onRecoverableError from './on-recoverable-error'
import { callServer } from './app-call-server'
import { isNextRouterError } from './components/is-next-router-error'
diff --git a/packages/next/src/client/compat/router.ts b/packages/next/src/client/compat/router.ts
index 58b1b9f02ed05..e9143c4117bd7 100644
--- a/packages/next/src/client/compat/router.ts
+++ b/packages/next/src/client/compat/router.ts
@@ -1,5 +1,5 @@
import { useContext } from 'react'
-import { RouterContext } from '../../shared/lib/router-context'
+import { RouterContext } from '../../shared/lib/router-context.shared-runtime'
import { NextRouter } from '../router'
/**
diff --git a/packages/next/src/client/components/action-async-storage.ts b/packages/next/src/client/components/action-async-storage.external.ts
similarity index 100%
rename from packages/next/src/client/components/action-async-storage.ts
rename to packages/next/src/client/components/action-async-storage.external.ts
diff --git a/packages/next/src/client/components/app-router.tsx b/packages/next/src/client/components/app-router.tsx
index 2382d6a83925e..2c3c541e02b8e 100644
--- a/packages/next/src/client/components/app-router.tsx
+++ b/packages/next/src/client/components/app-router.tsx
@@ -14,11 +14,11 @@ import {
LayoutRouterContext,
GlobalLayoutRouterContext,
CacheStates,
-} from '../../shared/lib/app-router-context'
+} from '../../shared/lib/app-router-context.shared-runtime'
import type {
CacheNode,
AppRouterInstance,
-} from '../../shared/lib/app-router-context'
+} from '../../shared/lib/app-router-context.shared-runtime'
import type {
FlightRouterState,
FlightData,
@@ -44,7 +44,7 @@ import { createHrefFromUrl } from './router-reducer/create-href-from-url'
import {
SearchParamsContext,
PathnameContext,
-} from '../../shared/lib/hooks-client-context'
+} from '../../shared/lib/hooks-client-context.shared-runtime'
import { useReducerWithReduxDevtools } from './use-reducer-with-devtools'
import { ErrorBoundary } from './error-boundary'
import {
diff --git a/packages/next/src/client/components/bailout-to-client-rendering.ts b/packages/next/src/client/components/bailout-to-client-rendering.ts
index 76356e05304a8..799398b5f300c 100644
--- a/packages/next/src/client/components/bailout-to-client-rendering.ts
+++ b/packages/next/src/client/components/bailout-to-client-rendering.ts
@@ -1,5 +1,5 @@
import { suspense } from '../../shared/lib/lazy-dynamic/dynamic-no-ssr'
-import { staticGenerationAsyncStorage } from './static-generation-async-storage'
+import { staticGenerationAsyncStorage } from './static-generation-async-storage.external'
export function bailoutToClientRendering(): boolean | never {
const staticGenerationStore = staticGenerationAsyncStorage.getStore()
diff --git a/packages/next/src/client/components/headers.ts b/packages/next/src/client/components/headers.ts
index d090264391e7c..a0a27a184cbfe 100644
--- a/packages/next/src/client/components/headers.ts
+++ b/packages/next/src/client/components/headers.ts
@@ -4,8 +4,8 @@ import {
} from '../../server/web/spec-extension/adapters/request-cookies'
import { HeadersAdapter } from '../../server/web/spec-extension/adapters/headers'
import { RequestCookies } from '../../server/web/spec-extension/cookies'
-import { requestAsyncStorage } from './request-async-storage'
-import { actionAsyncStorage } from './action-async-storage'
+import { requestAsyncStorage } from './request-async-storage.external'
+import { actionAsyncStorage } from './action-async-storage.external'
import { staticGenerationBailout } from './static-generation-bailout'
import { DraftMode } from './draft-mode'
@@ -17,7 +17,6 @@ export function headers() {
) {
return HeadersAdapter.seal(new Headers({}))
}
-
const requestStore = requestAsyncStorage.getStore()
if (!requestStore) {
throw new Error(
diff --git a/packages/next/src/client/components/layout-router.tsx b/packages/next/src/client/components/layout-router.tsx
index 3e410a93fb0ca..1f0ffff7e2de8 100644
--- a/packages/next/src/client/components/layout-router.tsx
+++ b/packages/next/src/client/components/layout-router.tsx
@@ -1,6 +1,6 @@
'use client'
-import type { ChildSegmentMap } from '../../shared/lib/app-router-context'
+import type { ChildSegmentMap } from '../../shared/lib/app-router-context.shared-runtime'
import type {
FlightRouterState,
FlightSegmentPath,
@@ -17,7 +17,7 @@ import {
LayoutRouterContext,
GlobalLayoutRouterContext,
TemplateContext,
-} from '../../shared/lib/app-router-context'
+} from '../../shared/lib/app-router-context.shared-runtime'
import { fetchServerResponse } from './router-reducer/fetch-server-response'
import { createInfinitePromise } from './infinite-promise'
import { ErrorBoundary } from './error-boundary'
diff --git a/packages/next/src/client/components/navigation.ts b/packages/next/src/client/components/navigation.ts
index bf6a56100080d..b3d69dcb065e8 100644
--- a/packages/next/src/client/components/navigation.ts
+++ b/packages/next/src/client/components/navigation.ts
@@ -4,11 +4,11 @@ import {
AppRouterContext,
GlobalLayoutRouterContext,
LayoutRouterContext,
-} from '../../shared/lib/app-router-context'
+} from '../../shared/lib/app-router-context.shared-runtime'
import {
SearchParamsContext,
PathnameContext,
-} from '../../shared/lib/hooks-client-context'
+} from '../../shared/lib/hooks-client-context.shared-runtime'
import { clientHookInServerComponentError } from './client-hook-in-server-component-error'
import { getSegmentValue } from './router-reducer/reducers/get-segment-value'
@@ -111,12 +111,12 @@ export function usePathname(): string {
export {
ServerInsertedHTMLContext,
useServerInsertedHTML,
-} from '../../shared/lib/server-inserted-html'
+} from '../../shared/lib/server-inserted-html.shared-runtime'
/**
* Get the router methods. For example router.push('/dashboard')
*/
-export function useRouter(): import('../../shared/lib/app-router-context').AppRouterInstance {
+export function useRouter(): import('../../shared/lib/app-router-context.shared-runtime').AppRouterInstance {
clientHookInServerComponentError('useRouter')
const router = useContext(AppRouterContext)
if (router === null) {
diff --git a/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-websocket.ts b/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-websocket.ts
index 4d92a279c3ed5..d37fce9851e91 100644
--- a/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-websocket.ts
+++ b/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-websocket.ts
@@ -1,5 +1,5 @@
import { useCallback, useContext, useEffect, useRef } from 'react'
-import { GlobalLayoutRouterContext } from '../../../../../shared/lib/app-router-context'
+import { GlobalLayoutRouterContext } from '../../../../../shared/lib/app-router-context.shared-runtime'
import { getSocketUrl } from './get-socket-url'
export function useWebsocket(assetPrefix: string) {
diff --git a/packages/next/src/client/components/redirect-boundary.tsx b/packages/next/src/client/components/redirect-boundary.tsx
index 23e5493ae83fb..8d407fd6e9d6e 100644
--- a/packages/next/src/client/components/redirect-boundary.tsx
+++ b/packages/next/src/client/components/redirect-boundary.tsx
@@ -1,6 +1,6 @@
'use client'
import React, { useEffect } from 'react'
-import { AppRouterInstance } from '../../shared/lib/app-router-context'
+import { AppRouterInstance } from '../../shared/lib/app-router-context.shared-runtime'
import { useRouter } from './navigation'
import {
RedirectType,
diff --git a/packages/next/src/client/components/redirect.ts b/packages/next/src/client/components/redirect.ts
index 10e72bc1ccbef..b9a2cfebd883f 100644
--- a/packages/next/src/client/components/redirect.ts
+++ b/packages/next/src/client/components/redirect.ts
@@ -1,4 +1,4 @@
-import { requestAsyncStorage } from './request-async-storage'
+import { requestAsyncStorage } from './request-async-storage.external'
import type { ResponseCookies } from '../../server/web/spec-extension/cookies'
const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT'
diff --git a/packages/next/src/client/components/render-from-template-context.tsx b/packages/next/src/client/components/render-from-template-context.tsx
index be486842c4f33..c1755cc5056bf 100644
--- a/packages/next/src/client/components/render-from-template-context.tsx
+++ b/packages/next/src/client/components/render-from-template-context.tsx
@@ -1,7 +1,7 @@
'use client'
import React, { useContext } from 'react'
-import { TemplateContext } from '../../shared/lib/app-router-context'
+import { TemplateContext } from '../../shared/lib/app-router-context.shared-runtime'
export default function RenderFromTemplateContext(): JSX.Element {
const children = useContext(TemplateContext)
diff --git a/packages/next/src/client/components/request-async-storage.ts b/packages/next/src/client/components/request-async-storage.external.ts
similarity index 100%
rename from packages/next/src/client/components/request-async-storage.ts
rename to packages/next/src/client/components/request-async-storage.external.ts
diff --git a/packages/next/src/client/components/router-reducer/apply-flight-data.ts b/packages/next/src/client/components/router-reducer/apply-flight-data.ts
index e7a2f11a84f48..003d0a5cde9e4 100644
--- a/packages/next/src/client/components/router-reducer/apply-flight-data.ts
+++ b/packages/next/src/client/components/router-reducer/apply-flight-data.ts
@@ -1,4 +1,7 @@
-import { CacheNode, CacheStates } from '../../../shared/lib/app-router-context'
+import {
+ CacheNode,
+ CacheStates,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import { FlightDataPath } from '../../../server/app-render/types'
import { fillLazyItemsTillLeafWithHead } from './fill-lazy-items-till-leaf-with-head'
import { fillCacheWithNewSubTreeData } from './fill-cache-with-new-subtree-data'
diff --git a/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx b/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx
index a6052636ef256..414b553c63249 100644
--- a/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx
+++ b/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx
@@ -1,6 +1,9 @@
import React from 'react'
import type { FlightRouterState } from '../../../server/app-render/types'
-import { CacheNode, CacheStates } from '../../../shared/lib/app-router-context'
+import {
+ CacheNode,
+ CacheStates,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import { createInitialRouterState } from './create-initial-router-state'
const buildId = 'development'
diff --git a/packages/next/src/client/components/router-reducer/create-initial-router-state.ts b/packages/next/src/client/components/router-reducer/create-initial-router-state.ts
index 7f7cca2003b0b..94fdabb9b577a 100644
--- a/packages/next/src/client/components/router-reducer/create-initial-router-state.ts
+++ b/packages/next/src/client/components/router-reducer/create-initial-router-state.ts
@@ -1,8 +1,8 @@
import type { ReactNode } from 'react'
-import type { CacheNode } from '../../../shared/lib/app-router-context'
+import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightRouterState } from '../../../server/app-render/types'
-import { CacheStates } from '../../../shared/lib/app-router-context'
+import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime'
import { createHrefFromUrl } from './create-href-from-url'
import { fillLazyItemsTillLeafWithHead } from './fill-lazy-items-till-leaf-with-head'
import { extractPathFromFlightRouterState } from './compute-changed-path'
diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx
index 28f8c3412ab3a..648069ea76986 100644
--- a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx
+++ b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx
@@ -1,7 +1,10 @@
import React from 'react'
import { fetchServerResponse } from './fetch-server-response'
import { fillCacheWithDataProperty } from './fill-cache-with-data-property'
-import { CacheStates, CacheNode } from '../../../shared/lib/app-router-context'
+import {
+ CacheStates,
+ CacheNode,
+} from '../../../shared/lib/app-router-context.shared-runtime'
describe('fillCacheWithDataProperty', () => {
it('should add data property', () => {
const fetchServerResponseMock: jest.Mock<
diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts
index 81df295dba302..42df61a952af5 100644
--- a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts
+++ b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts
@@ -1,5 +1,8 @@
import { FlightSegmentPath } from '../../../server/app-render/types'
-import { CacheNode, CacheStates } from '../../../shared/lib/app-router-context'
+import {
+ CacheNode,
+ CacheStates,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import { createRouterCacheKey } from './create-router-cache-key'
import { fetchServerResponse } from './fetch-server-response'
diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx
index 187f86a478751..ac888a3ede0ff 100644
--- a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx
+++ b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx
@@ -1,6 +1,9 @@
import React from 'react'
import { fillCacheWithNewSubTreeData } from './fill-cache-with-new-subtree-data'
-import { CacheStates, CacheNode } from '../../../shared/lib/app-router-context'
+import {
+ CacheStates,
+ CacheNode,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightData } from '../../../server/app-render/types'
const getFlightData = (): FlightData => {
diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts
index 5d48eaee9ef9f..7e9a93699fb65 100644
--- a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts
+++ b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts
@@ -1,4 +1,7 @@
-import { CacheNode, CacheStates } from '../../../shared/lib/app-router-context'
+import {
+ CacheNode,
+ CacheStates,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightDataPath } from '../../../server/app-render/types'
import { invalidateCacheByRouterState } from './invalidate-cache-by-router-state'
import { fillLazyItemsTillLeafWithHead } from './fill-lazy-items-till-leaf-with-head'
diff --git a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx
index 606440a96f9c9..1edbeffd7b3e9 100644
--- a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx
+++ b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx
@@ -1,6 +1,9 @@
import React from 'react'
import { fillLazyItemsTillLeafWithHead } from './fill-lazy-items-till-leaf-with-head'
-import { CacheStates, CacheNode } from '../../../shared/lib/app-router-context'
+import {
+ CacheStates,
+ CacheNode,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightData } from '../../../server/app-render/types'
const getFlightData = (): FlightData => {
diff --git a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts
index c5ddedd52351e..f558edfab2f1e 100644
--- a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts
+++ b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts
@@ -1,4 +1,7 @@
-import { CacheNode, CacheStates } from '../../../shared/lib/app-router-context'
+import {
+ CacheNode,
+ CacheStates,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightRouterState } from '../../../server/app-render/types'
import { createRouterCacheKey } from './create-router-cache-key'
diff --git a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx
index 915f09cae0cae..8c23c47d42d74 100644
--- a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx
+++ b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx
@@ -1,7 +1,10 @@
import React from 'react'
import type { FlightData } from '../../../server/app-render/types'
import { invalidateCacheBelowFlightSegmentPath } from './invalidate-cache-below-flight-segmentpath'
-import { CacheStates, CacheNode } from '../../../shared/lib/app-router-context'
+import {
+ CacheStates,
+ CacheNode,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import { fillCacheWithNewSubTreeData } from './fill-cache-with-new-subtree-data'
const getFlightData = (): FlightData => {
diff --git a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts
index ac343f8d79679..d637d850b145a 100644
--- a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts
+++ b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts
@@ -1,4 +1,4 @@
-import type { CacheNode } from '../../../shared/lib/app-router-context'
+import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightSegmentPath } from '../../../server/app-render/types'
import { createRouterCacheKey } from './create-router-cache-key'
diff --git a/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx b/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx
index 65ce9e42c05ee..bdd819b0614d9 100644
--- a/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx
+++ b/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx
@@ -1,6 +1,9 @@
import React from 'react'
import { invalidateCacheByRouterState } from './invalidate-cache-by-router-state'
-import { CacheStates, CacheNode } from '../../../shared/lib/app-router-context'
+import {
+ CacheStates,
+ CacheNode,
+} from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightRouterState } from '../../../server/app-render/types'
describe('invalidateCacheByRouterState', () => {
diff --git a/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.ts b/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.ts
index 820e5909bf031..1ec39ae9e35fd 100644
--- a/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.ts
+++ b/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.ts
@@ -1,4 +1,4 @@
-import type { CacheNode } from '../../../shared/lib/app-router-context'
+import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime'
import type { FlightRouterState } from '../../../server/app-render/types'
import { createRouterCacheKey } from './create-router-cache-key'
diff --git a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx
index 807374c855577..2d4cdef348b1e 100644
--- a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx
+++ b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx
@@ -3,7 +3,7 @@ import type { FlightRouterState } from '../../../../server/app-render/types'
import {
CacheNode,
CacheStates,
-} from '../../../../shared/lib/app-router-context'
+} from '../../../../shared/lib/app-router-context.shared-runtime'
import { findHeadInCache } from './find-head-in-cache'
describe('findHeadInCache', () => {
diff --git a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts
index f4d5e768b9808..08dcefc65f2ce 100644
--- a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts
+++ b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts
@@ -1,5 +1,5 @@
import type { FlightRouterState } from '../../../../server/app-render/types'
-import type { CacheNode } from '../../../../shared/lib/app-router-context'
+import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime'
import { createRouterCacheKey } from '../create-router-cache-key'
export function findHeadInCache(
diff --git a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx
index 6ff039d14cf54..4ed01fed08c83 100644
--- a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx
+++ b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx
@@ -79,7 +79,7 @@ import { FlightRouterState } from '../../../../server/app-render/types'
import {
CacheNode,
CacheStates,
-} from '../../../../shared/lib/app-router-context'
+} from '../../../../shared/lib/app-router-context.shared-runtime'
import { createInitialRouterState } from '../create-initial-router-state'
import {
NavigateAction,
diff --git a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts
index fe8a4a24c4b8b..e47c42b2aa60a 100644
--- a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts
+++ b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts
@@ -1,7 +1,7 @@
import {
CacheNode,
CacheStates,
-} from '../../../../shared/lib/app-router-context'
+} from '../../../../shared/lib/app-router-context.shared-runtime'
import type {
FlightRouterState,
FlightSegmentPath,
diff --git a/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx
index 8055123367a94..bbbee6ff5f2a4 100644
--- a/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx
+++ b/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx
@@ -36,7 +36,7 @@ import { FlightRouterState } from '../../../../server/app-render/types'
import {
CacheNode,
CacheStates,
-} from '../../../../shared/lib/app-router-context'
+} from '../../../../shared/lib/app-router-context.shared-runtime'
import { createInitialRouterState } from '../create-initial-router-state'
import {
PrefetchAction,
diff --git a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx
index 1ffbb376e2f96..9ed54e8994d2e 100644
--- a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx
+++ b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx
@@ -46,7 +46,7 @@ import { FlightRouterState } from '../../../../server/app-render/types'
import {
CacheNode,
CacheStates,
-} from '../../../../shared/lib/app-router-context'
+} from '../../../../shared/lib/app-router-context.shared-runtime'
import { createInitialRouterState } from '../create-initial-router-state'
import { RefreshAction, ACTION_REFRESH } from '../router-reducer-types'
import { refreshReducer } from './refresh-reducer'
diff --git a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts
index cd87ef3802b00..bd6dfc4ef9047 100644
--- a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts
+++ b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts
@@ -11,7 +11,7 @@ import {
} from '../router-reducer-types'
import { handleExternalUrl } from './navigate-reducer'
import { handleMutable } from '../handle-mutable'
-import { CacheStates } from '../../../../shared/lib/app-router-context'
+import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime'
import { fillLazyItemsTillLeafWithHead } from '../fill-lazy-items-till-leaf-with-head'
export function refreshReducer(
diff --git a/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx
index b11f39b141ccf..36c978926517f 100644
--- a/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx
+++ b/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx
@@ -3,7 +3,7 @@ import type { FlightRouterState } from '../../../../server/app-render/types'
import {
CacheNode,
CacheStates,
-} from '../../../../shared/lib/app-router-context'
+} from '../../../../shared/lib/app-router-context.shared-runtime'
import { createInitialRouterState } from '../create-initial-router-state'
import { RestoreAction, ACTION_RESTORE } from '../router-reducer-types'
import { restoreReducer } from './restore-reducer'
diff --git a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts
index 3b8fa6acb4013..0c6caaba746ca 100644
--- a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts
+++ b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts
@@ -27,7 +27,7 @@ import { createHrefFromUrl } from '../create-href-from-url'
import { handleExternalUrl } from './navigate-reducer'
import { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree'
import { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout'
-import { CacheStates } from '../../../../shared/lib/app-router-context'
+import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime'
import { handleMutable } from '../handle-mutable'
import { fillLazyItemsTillLeafWithHead } from '../fill-lazy-items-till-leaf-with-head'
diff --git a/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx
index 37ef29296c891..0540c02079cb1 100644
--- a/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx
+++ b/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx
@@ -41,7 +41,7 @@ jest.mock('../fetch-server-response', () => {
import {
CacheNode,
CacheStates,
-} from '../../../../shared/lib/app-router-context'
+} from '../../../../shared/lib/app-router-context.shared-runtime'
import { createInitialRouterState } from '../create-initial-router-state'
import {
ServerPatchAction,
diff --git a/packages/next/src/client/components/router-reducer/router-reducer-types.ts b/packages/next/src/client/components/router-reducer/router-reducer-types.ts
index 48840a29db6db..defbb657c7c42 100644
--- a/packages/next/src/client/components/router-reducer/router-reducer-types.ts
+++ b/packages/next/src/client/components/router-reducer/router-reducer-types.ts
@@ -1,4 +1,4 @@
-import type { CacheNode } from '../../../shared/lib/app-router-context'
+import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime'
import type {
FlightRouterState,
FlightData,
diff --git a/packages/next/src/client/components/static-generation-async-storage.ts b/packages/next/src/client/components/static-generation-async-storage.external.ts
similarity index 100%
rename from packages/next/src/client/components/static-generation-async-storage.ts
rename to packages/next/src/client/components/static-generation-async-storage.external.ts
diff --git a/packages/next/src/client/components/static-generation-bailout.ts b/packages/next/src/client/components/static-generation-bailout.ts
index c5072218f035c..4d35150664251 100644
--- a/packages/next/src/client/components/static-generation-bailout.ts
+++ b/packages/next/src/client/components/static-generation-bailout.ts
@@ -1,5 +1,5 @@
import { DynamicServerError } from './hooks-server-context'
-import { staticGenerationAsyncStorage } from './static-generation-async-storage'
+import { staticGenerationAsyncStorage } from './static-generation-async-storage.external'
class StaticGenBailoutError extends Error {
code = 'NEXT_STATIC_GEN_BAILOUT'
diff --git a/packages/next/src/client/image-component.tsx b/packages/next/src/client/image-component.tsx
index 3f2183c004b10..321b07ecd0a5f 100644
--- a/packages/next/src/client/image-component.tsx
+++ b/packages/next/src/client/image-component.tsx
@@ -25,9 +25,9 @@ import type {
ImageLoaderProps,
} from '../shared/lib/image-config'
import { imageConfigDefault } from '../shared/lib/image-config'
-import { ImageConfigContext } from '../shared/lib/image-config-context'
+import { ImageConfigContext } from '../shared/lib/image-config-context.shared-runtime'
import { warnOnce } from '../shared/lib/utils/warn-once'
-import { RouterContext } from '../shared/lib/router-context'
+import { RouterContext } from '../shared/lib/router-context.shared-runtime'
// @ts-ignore - This is replaced by webpack alias
import defaultLoader from 'next/dist/shared/lib/image-loader'
diff --git a/packages/next/src/client/index.tsx b/packages/next/src/client/index.tsx
index f7c163f020d31..0f8a95c93746e 100644
--- a/packages/next/src/client/index.tsx
+++ b/packages/next/src/client/index.tsx
@@ -10,16 +10,16 @@ import type {
import React from 'react'
import ReactDOM from 'react-dom/client'
-import { HeadManagerContext } from '../shared/lib/head-manager-context'
+import { HeadManagerContext } from '../shared/lib/head-manager-context.shared-runtime'
import mitt, { MittEmitter } from '../shared/lib/mitt'
-import { RouterContext } from '../shared/lib/router-context'
+import { RouterContext } from '../shared/lib/router-context.shared-runtime'
import { handleSmoothScroll } from '../shared/lib/router/utils/handle-smooth-scroll'
import { isDynamicRoute } from '../shared/lib/router/utils/is-dynamic'
import {
urlQueryToSearchParams,
assign,
} from '../shared/lib/router/utils/querystring'
-import { setConfig } from '../shared/lib/runtime-config'
+import { setConfig } from '../shared/lib/runtime-config.shared-runtime'
import {
getURL,
loadGetInitialProps,
@@ -34,17 +34,17 @@ import measureWebVitals from './performance-relayer'
import { RouteAnnouncer } from './route-announcer'
import { createRouter, makePublicRouterInstance } from './router'
import { getProperError } from '../lib/is-error'
-import { ImageConfigContext } from '../shared/lib/image-config-context'
+import { ImageConfigContext } from '../shared/lib/image-config-context.shared-runtime'
import { ImageConfigComplete } from '../shared/lib/image-config'
import { removeBasePath } from './remove-base-path'
import { hasBasePath } from './has-base-path'
-import { AppRouterContext } from '../shared/lib/app-router-context'
+import { AppRouterContext } from '../shared/lib/app-router-context.shared-runtime'
import {
adaptForAppRouterInstance,
adaptForSearchParams,
PathnameContextProviderAdapter,
-} from '../shared/lib/router/adapters'
-import { SearchParamsContext } from '../shared/lib/hooks-client-context'
+} from '../shared/lib/router/adapters.shared-runtime'
+import { SearchParamsContext } from '../shared/lib/hooks-client-context.shared-runtime'
import onRecoverableError from './on-recoverable-error'
import tracer from './tracing/tracer'
import reportToSocket from './tracing/report-to-socket'
diff --git a/packages/next/src/client/legacy/image.tsx b/packages/next/src/client/legacy/image.tsx
index d1456477bacf6..07ec2e217c200 100644
--- a/packages/next/src/client/legacy/image.tsx
+++ b/packages/next/src/client/legacy/image.tsx
@@ -16,7 +16,7 @@ import {
VALID_LOADERS,
} from '../../shared/lib/image-config'
import { useIntersection } from '../use-intersection'
-import { ImageConfigContext } from '../../shared/lib/image-config-context'
+import { ImageConfigContext } from '../../shared/lib/image-config-context.shared-runtime'
import { warnOnce } from '../../shared/lib/utils/warn-once'
import { normalizePathTrailingSlash } from '../normalize-trailing-slash'
diff --git a/packages/next/src/client/link.tsx b/packages/next/src/client/link.tsx
index 94226c8caa5c0..7a15dee249e26 100644
--- a/packages/next/src/client/link.tsx
+++ b/packages/next/src/client/link.tsx
@@ -12,12 +12,12 @@ import { isLocalURL } from '../shared/lib/router/utils/is-local-url'
import { formatUrl } from '../shared/lib/router/utils/format-url'
import { isAbsoluteUrl } from '../shared/lib/utils'
import { addLocale } from './add-locale'
-import { RouterContext } from '../shared/lib/router-context'
+import { RouterContext } from '../shared/lib/router-context.shared-runtime'
import {
AppRouterContext,
AppRouterInstance,
PrefetchOptions as AppRouterPrefetchOptions,
-} from '../shared/lib/app-router-context'
+} from '../shared/lib/app-router-context.shared-runtime'
import { useIntersection } from './use-intersection'
import { getDomainLocale } from './get-domain-locale'
import { addBasePath } from './add-base-path'
diff --git a/packages/next/src/client/router.ts b/packages/next/src/client/router.ts
index 342ecb623df74..f43126691e5e5 100644
--- a/packages/next/src/client/router.ts
+++ b/packages/next/src/client/router.ts
@@ -2,7 +2,7 @@
import React from 'react'
import Router from '../shared/lib/router/router'
import type { NextRouter } from '../shared/lib/router/router'
-import { RouterContext } from '../shared/lib/router-context'
+import { RouterContext } from '../shared/lib/router-context.shared-runtime'
import isError from '../lib/is-error'
type SingletonRouterBase = {
diff --git a/packages/next/src/client/script.tsx b/packages/next/src/client/script.tsx
index a4b2c6dcd3184..f695e691c482d 100644
--- a/packages/next/src/client/script.tsx
+++ b/packages/next/src/client/script.tsx
@@ -3,7 +3,7 @@
import ReactDOM from 'react-dom'
import React, { useEffect, useContext, useRef } from 'react'
import { ScriptHTMLAttributes } from 'react'
-import { HeadManagerContext } from '../shared/lib/head-manager-context'
+import { HeadManagerContext } from '../shared/lib/head-manager-context.shared-runtime'
import { DOMAttributeNames } from './head-manager'
import { requestIdleCallback } from './request-idle-callback'
diff --git a/packages/next/src/export/worker.ts b/packages/next/src/export/worker.ts
index 31f58755996a4..b9fb7b9afd60a 100644
--- a/packages/next/src/export/worker.ts
+++ b/packages/next/src/export/worker.ts
@@ -59,7 +59,7 @@ import {
RSC,
} from '../client/components/app-router-headers'
-const envConfig = require('../shared/lib/runtime-config')
+const envConfig = require('../shared/lib/runtime-config.shared-runtime')
;(globalThis as any).__NEXT_DATA__ = {
nextExport: true,
@@ -307,8 +307,10 @@ export default async function exportPage({
await promises.mkdir(baseDir, { recursive: true })
let renderResult: RenderResult | undefined
let curRenderOpts: RenderOpts = {}
- const { renderToHTML } =
- require('../server/render') as typeof import('../server/render')
+ const renderToHTML =
+ require('../server/future/route-modules/pages/module.compiled')
+ .renderToHTML as typeof import('../server/render').renderToHTML
+
let renderMethod = renderToHTML
let inAmpMode = false,
hybridAmp = false
@@ -479,7 +481,6 @@ export default async function exportPage({
const module = await RouteModuleLoader.load(
filename
)
-
// Call the handler with the request and context from the module.
const response = await module.handle(request, context)
@@ -535,8 +536,9 @@ export default async function exportPage({
results.fromBuildExportRevalidate = 0
}
} else {
- const { renderToHTMLOrFlight } =
- require('../server/app-render/app-render') as typeof import('../server/app-render/app-render')
+ const renderToHTMLOrFlight =
+ require('../server/future/route-modules/app-page/module.compiled')
+ .renderToHTMLOrFlight as typeof import('../server/app-render/app-render').renderToHTMLOrFlight
try {
curRenderOpts.params ||= {}
diff --git a/packages/next/src/lib/chalk.ts b/packages/next/src/lib/chalk.ts
index 8e40472953f8f..d0939d9148b97 100644
--- a/packages/next/src/lib/chalk.ts
+++ b/packages/next/src/lib/chalk.ts
@@ -1,6 +1,6 @@
let chalk: typeof import('next/dist/compiled/chalk')
-if (process.env.NEXT_RUNTIME === 'edge') {
+if (process.env.NEXT_RUNTIME === 'edge' || process.env.NEXT_MINIMAL) {
chalk = require('./web/chalk').default
} else {
chalk = require('next/dist/compiled/chalk')
diff --git a/packages/next/src/lib/constants.ts b/packages/next/src/lib/constants.ts
index fc94397c6aca7..46f85311a9f0a 100644
--- a/packages/next/src/lib/constants.ts
+++ b/packages/next/src/lib/constants.ts
@@ -132,6 +132,10 @@ const WEBPACK_LAYERS_NAMES = {
* The server bundle layer for metadata routes.
*/
appMetadataRoute: 'app-metadata-route',
+ /**
+ * The layer for the server bundle for App Route handlers.
+ */
+ appRouteHandler: 'app-route-handler',
}
export const WEBPACK_LAYERS = {
@@ -141,6 +145,7 @@ export const WEBPACK_LAYERS = {
WEBPACK_LAYERS_NAMES.reactServerComponents,
WEBPACK_LAYERS_NAMES.actionBrowser,
WEBPACK_LAYERS_NAMES.appMetadataRoute,
+ WEBPACK_LAYERS_NAMES.appRouteHandler,
],
},
}
diff --git a/packages/next/src/pages/_document.tsx b/packages/next/src/pages/_document.tsx
index a8526011c5d33..f0a29cb15d1fc 100644
--- a/packages/next/src/pages/_document.tsx
+++ b/packages/next/src/pages/_document.tsx
@@ -17,8 +17,11 @@ import { BuildManifest, getPageFiles } from '../server/get-page-files'
import { htmlEscapeJsonString } from '../server/htmlescape'
import isError from '../lib/is-error'
-import { HtmlContext, useHtmlContext } from '../shared/lib/html-context'
-import type { HtmlProps } from '../shared/lib/html-context'
+import {
+ HtmlContext,
+ useHtmlContext,
+} from '../shared/lib/html-context.shared-runtime'
+import type { HtmlProps } from '../shared/lib/html-context.shared-runtime'
export { DocumentContext, DocumentInitialProps, DocumentProps }
diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts
index 6b8bc3228a005..9f6059ec48f5a 100644
--- a/packages/next/src/server/app-render/action-handler.ts
+++ b/packages/next/src/server/app-render/action-handler.ts
@@ -19,10 +19,10 @@ import {
isRedirectError,
} from '../../client/components/redirect'
import RenderResult from '../render-result'
-import { StaticGenerationStore } from '../../client/components/static-generation-async-storage'
+import { StaticGenerationStore } from '../../client/components/static-generation-async-storage.external'
import { FlightRenderResult } from './flight-render-result'
import { ActionResult } from './types'
-import { ActionAsyncStorage } from '../../client/components/action-async-storage'
+import { ActionAsyncStorage } from '../../client/components/action-async-storage.external'
import {
filterReqHeaders,
actionsForbiddenHeaders,
@@ -31,7 +31,8 @@ import {
appendMutableCookies,
getModifiedCookieValues,
} from '../web/spec-extension/adapters/request-cookies'
-import { RequestStore } from '../../client/components/request-async-storage'
+
+import { RequestStore } from '../../client/components/request-async-storage.external'
import {
NEXT_CACHE_REVALIDATED_TAGS_HEADER,
NEXT_CACHE_REVALIDATE_TAG_TOKEN_HEADER,
diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx
index 30749ac66a83d..1dd2eb8f7c639 100644
--- a/packages/next/src/server/app-render/app-render.tsx
+++ b/packages/next/src/server/app-render/app-render.tsx
@@ -11,9 +11,9 @@ import type {
Segment,
} from './types'
-import type { StaticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage'
+import type { StaticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage.external'
import type { StaticGenerationBailout } from '../../client/components/static-generation-bailout'
-import type { RequestAsyncStorage } from '../../client/components/request-async-storage'
+import type { RequestAsyncStorage } from '../../client/components/request-async-storage.external'
import React from 'react'
import { createServerComponentRenderer } from './create-server-components-renderer'
@@ -286,10 +286,13 @@ export async function renderToHTMLOrFlight(
* that we need to resolve the final metadata.
*/
- const requestId =
- process.env.NEXT_RUNTIME === 'edge'
- ? crypto.randomUUID()
- : require('next/dist/compiled/nanoid').nanoid()
+ let requestId: string
+
+ if (process.env.NEXT_RUNTIME === 'edge') {
+ requestId = crypto.randomUUID()
+ } else {
+ requestId = require('next/dist/compiled/nanoid').nanoid()
+ }
const LayoutRouter =
ComponentMod.LayoutRouter as typeof import('../../client/components/layout-router').default
@@ -1392,7 +1395,7 @@ export async function renderToHTMLOrFlight(
)
const { HeadManagerContext } =
- require('../../shared/lib/head-manager-context') as typeof import('../../shared/lib/head-manager-context')
+ require('../../shared/lib/head-manager-context.shared-runtime') as typeof import('../../shared/lib/head-manager-context.shared-runtime')
// On each render, create a new `ServerInsertedHTML` context to capture
// injected nodes from user code (`useServerInsertedHTML`).
diff --git a/packages/next/src/server/app-render/entry-base.ts b/packages/next/src/server/app-render/entry-base.ts
index 6bc5fd7e7ace1..0cc53e0214d86 100644
--- a/packages/next/src/server/app-render/entry-base.ts
+++ b/packages/next/src/server/app-render/entry-base.ts
@@ -1,36 +1,26 @@
-const { default: AppRouter } =
- require('next/dist/client/components/app-router') as typeof import('../../client/components/app-router')
-const { default: LayoutRouter } =
- require('next/dist/client/components/layout-router') as typeof import('../../client/components/layout-router')
-const { default: RenderFromTemplateContext } =
- require('next/dist/client/components/render-from-template-context') as typeof import('../../client/components/render-from-template-context')
-
-const { staticGenerationAsyncStorage } =
- require('next/dist/client/components/static-generation-async-storage') as typeof import('../../client/components/static-generation-async-storage')
-
-const { requestAsyncStorage } =
- require('next/dist/client/components/request-async-storage') as typeof import('../../client/components/request-async-storage')
-const { actionAsyncStorage } =
- require('next/dist/client/components/action-async-storage') as typeof import('../../client/components/action-async-storage')
-
-const { staticGenerationBailout } =
- require('next/dist/client/components/static-generation-bailout') as typeof import('../../client/components/static-generation-bailout')
-const { default: StaticGenerationSearchParamsBailoutProvider } =
- require('next/dist/client/components/static-generation-searchparams-bailout-provider') as typeof import('../../client/components/static-generation-searchparams-bailout-provider')
-const { createSearchParamsBailoutProxy } =
- require('next/dist/client/components/searchparams-bailout-proxy') as typeof import('../../client/components/searchparams-bailout-proxy')
-
-const serverHooks =
- require('next/dist/client/components/hooks-server-context') as typeof import('../../client/components/hooks-server-context')
-
const {
renderToReadableStream,
decodeReply,
decodeAction,
// eslint-disable-next-line import/no-extraneous-dependencies
} = require('react-server-dom-webpack/server.edge')
-const { preloadStyle, preloadFont, preconnect } =
- require('next/dist/server/app-render/rsc/preloads') as typeof import('../../server/app-render/rsc/preloads')
+
+import AppRouter from '../../client/components/app-router'
+import LayoutRouter from '../../client/components/layout-router'
+import RenderFromTemplateContext from '../../client/components/render-from-template-context'
+import { staticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage.external'
+import { requestAsyncStorage } from '../../client/components/request-async-storage.external'
+import { actionAsyncStorage } from '../../client/components/action-async-storage.external'
+import { staticGenerationBailout } from '../../client/components/static-generation-bailout'
+import StaticGenerationSearchParamsBailoutProvider from '../../client/components/static-generation-searchparams-bailout-provider'
+import { createSearchParamsBailoutProxy } from '../../client/components/searchparams-bailout-proxy'
+import * as serverHooks from '../../client/components/hooks-server-context'
+
+import {
+ preloadStyle,
+ preloadFont,
+ preconnect,
+} from '../../server/app-render/rsc/preloads'
const { NotFoundBoundary } =
require('next/dist/client/components/not-found-boundary') as typeof import('../../client/components/not-found-boundary')
diff --git a/packages/next/src/server/app-render/server-inserted-html.tsx b/packages/next/src/server/app-render/server-inserted-html.tsx
index f044c24feaba3..764dc62792077 100644
--- a/packages/next/src/server/app-render/server-inserted-html.tsx
+++ b/packages/next/src/server/app-render/server-inserted-html.tsx
@@ -2,7 +2,7 @@
// elements into the HTML stream.
import React from 'react'
-import { ServerInsertedHTMLContext } from '../../shared/lib/server-inserted-html'
+import { ServerInsertedHTMLContext } from '../../shared/lib/server-inserted-html.shared-runtime'
export function createServerInsertedHTML() {
const serverInsertedHTMLCallbacks: (() => React.ReactNode)[] = []
diff --git a/packages/next/src/server/async-storage/request-async-storage-wrapper.ts b/packages/next/src/server/async-storage/request-async-storage-wrapper.ts
index 50795855c53d4..1376ecfb197cd 100644
--- a/packages/next/src/server/async-storage/request-async-storage-wrapper.ts
+++ b/packages/next/src/server/async-storage/request-async-storage-wrapper.ts
@@ -1,7 +1,7 @@
import type { BaseNextRequest, BaseNextResponse } from '../base-http'
import type { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http'
import type { AsyncLocalStorage } from 'async_hooks'
-import type { RequestStore } from '../../client/components/request-async-storage'
+import type { RequestStore } from '../../client/components/request-async-storage.external'
import type { RenderOpts } from '../app-render/types'
import type { AsyncStorageWrapper } from './async-storage-wrapper'
import type { NextRequest } from '../web/spec-extension/request'
diff --git a/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts b/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts
index a28ac0e8ecb2a..d5adfc9de38b4 100644
--- a/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts
+++ b/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts
@@ -1,5 +1,5 @@
import type { AsyncStorageWrapper } from './async-storage-wrapper'
-import type { StaticGenerationStore } from '../../client/components/static-generation-async-storage'
+import type { StaticGenerationStore } from '../../client/components/static-generation-async-storage.external'
import type { AsyncLocalStorage } from 'async_hooks'
import type { IncrementalCache } from '../lib/incremental-cache'
diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts
index d826f2bdd4e04..fab999db35ddc 100644
--- a/packages/next/src/server/base-server.ts
+++ b/packages/next/src/server/base-server.ts
@@ -55,7 +55,7 @@ import {
getCookieParser,
checkIsOnDemandRevalidate,
} from './api-utils'
-import { setConfig } from '../shared/lib/runtime-config'
+import { setConfig } from '../shared/lib/runtime-config.shared-runtime'
import { setRevalidateHeaders } from './send-payload/revalidate-headers'
import { execOnce } from '../shared/lib/utils'
@@ -427,7 +427,11 @@ export default abstract class Server {
} = this.nextConfig
this.buildId = this.getBuildId()
- this.minimalMode = minimalMode || !!process.env.NEXT_PRIVATE_MINIMAL_MODE
+ // this is a hack to avoid Webpack knowing this is equal to this.minimalMode
+ // because we replace this.minimalMode to true in production bundles.
+ const minimalModeKey = 'minimalMode'
+ this[minimalModeKey] =
+ minimalMode || !!process.env.NEXT_PRIVATE_MINIMAL_MODE
this.hasAppDir = this.getHasAppDir(dev)
const serverComponents = this.hasAppDir
diff --git a/packages/next/src/server/dev/next-dev-server.ts b/packages/next/src/server/dev/next-dev-server.ts
index 1eca11b7358cb..839fa1b13c0e4 100644
--- a/packages/next/src/server/dev/next-dev-server.ts
+++ b/packages/next/src/server/dev/next-dev-server.ts
@@ -41,7 +41,7 @@ import {
UnwrapPromise,
withCoalescedInvoke,
} from '../../lib/coalesced-function'
-import { loadDefaultErrorComponents } from '../load-components'
+import { loadDefaultErrorComponents } from '../load-default-error-components'
import { DecodeError, MiddlewareNotFoundError } from '../../shared/lib/utils'
import * as Log from '../../build/output/log'
import isError, { getProperError } from '../../lib/is-error'
diff --git a/packages/next/src/server/dev/static-paths-worker.ts b/packages/next/src/server/dev/static-paths-worker.ts
index 68932df7a36b0..ddd6526e52f23 100644
--- a/packages/next/src/server/dev/static-paths-worker.ts
+++ b/packages/next/src/server/dev/static-paths-worker.ts
@@ -14,8 +14,10 @@ import { loadComponents } from '../load-components'
import { setHttpClientAndAgentOptions } from '../setup-http-agent-env'
import { IncrementalCache } from '../lib/incremental-cache'
import * as serverHooks from '../../client/components/hooks-server-context'
-import { staticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage'
-import { AppRouteRouteModule } from '../future/route-modules/app-route/module'
+import { staticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage.external'
+
+const { AppRouteRouteModule } =
+ require('../future/route-modules/app-route/module.compiled') as typeof import('../future/route-modules/app-route/module')
type RuntimeConfig = any
@@ -56,7 +58,7 @@ export async function loadStaticPaths({
fallback?: boolean | 'blocking'
}> {
// update work memory runtime-config
- require('../../shared/lib/runtime-config').setConfig(config)
+ require('../../shared/lib/runtime-config.shared-runtime').setConfig(config)
setHttpClientAndAgentOptions({
httpAgentOptions,
})
diff --git a/packages/next/src/server/future/helpers/module-loader/node-module-loader.ts b/packages/next/src/server/future/helpers/module-loader/node-module-loader.ts
index 3283eb00a53f5..6f70685df7e75 100644
--- a/packages/next/src/server/future/helpers/module-loader/node-module-loader.ts
+++ b/packages/next/src/server/future/helpers/module-loader/node-module-loader.ts
@@ -7,7 +7,10 @@ export class NodeModuleLoader implements ModuleLoader {
public async load(id: string): Promise {
if (process.env.NEXT_RUNTIME !== 'edge') {
// Need to `await` to cover the case that route is marked ESM modules by ESM escalation.
- return await require(id)
+ return await (process.env.NEXT_MINIMAL
+ ? // @ts-ignore
+ __non_webpack_require__(id)
+ : require(id))
}
throw new Error('NodeModuleLoader is not supported in edge runtime.')
diff --git a/packages/next/src/server/future/route-modules/app-page/module.compiled.ts b/packages/next/src/server/future/route-modules/app-page/module.compiled.ts
new file mode 100644
index 0000000000000..78601739acbe5
--- /dev/null
+++ b/packages/next/src/server/future/route-modules/app-page/module.compiled.ts
@@ -0,0 +1,11 @@
+if (process.env.NEXT_RUNTIME === 'edge') {
+ module.exports = require('next/dist/server/future/route-modules/app-page/module.js')
+} else {
+ if (process.env.NODE_ENV === 'development') {
+ module.exports = require('next/dist/compiled/next-server/app-page.runtime.dev.js')
+ } else if (process.env.TURBOPACK) {
+ module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.prod.js')
+ } else {
+ module.exports = require('next/dist/compiled/next-server/app-page.runtime.prod.js')
+ }
+}
diff --git a/packages/next/src/server/future/route-modules/app-page/module.ts b/packages/next/src/server/future/route-modules/app-page/module.ts
index 418e37420d7e9..daa0291a1c8b4 100644
--- a/packages/next/src/server/future/route-modules/app-page/module.ts
+++ b/packages/next/src/server/future/route-modules/app-page/module.ts
@@ -11,6 +11,7 @@ import {
type RouteModuleOptions,
type RouteModuleHandleContext,
} from '../route-module'
+import * as sharedModules from './shared-modules'
type AppPageUserlandModule = {
/**
@@ -34,6 +35,8 @@ export class AppPageRouteModule extends RouteModule<
AppPageRouteDefinition,
AppPageUserlandModule
> {
+ static readonly sharedModules = sharedModules
+
public render(
req: IncomingMessage,
res: ServerResponse,
@@ -49,4 +52,6 @@ export class AppPageRouteModule extends RouteModule<
}
}
+export { renderToHTMLOrFlight }
+
export default AppPageRouteModule
diff --git a/packages/next/src/server/future/route-modules/app-page/shared-modules.ts b/packages/next/src/server/future/route-modules/app-page/shared-modules.ts
new file mode 100644
index 0000000000000..e986c1bad3894
--- /dev/null
+++ b/packages/next/src/server/future/route-modules/app-page/shared-modules.ts
@@ -0,0 +1,13 @@
+// the name of the export has to be the camelCase version of the file name (without the extension)
+export * as headManagerContext from '../../../../shared/lib/head-manager-context.shared-runtime'
+export * as serverInsertedHtml from '../../../../shared/lib/server-inserted-html.shared-runtime'
+export * as appRouterContext from '../../../../shared/lib/app-router-context.shared-runtime'
+export * as hooksClientContext from '../../../../shared/lib/hooks-client-context.shared-runtime'
+export * as routerContext from '../../../../shared/lib/router-context.shared-runtime'
+export * as htmlContext from '../../../../shared/lib/html-context.shared-runtime'
+export * as ampContext from '../../../../shared/lib/amp-context.shared-runtime'
+export * as adapters from '../../../../shared/lib/router/adapters.shared-runtime'
+export * as loadableContext from '../../../../shared/lib/loadable-context.shared-runtime'
+export * as imageConfigContext from '../../../../shared/lib/image-config-context.shared-runtime'
+export * as runtimeConfig from '../../../../shared/lib/runtime-config.shared-runtime'
+export * as loadable from '../../../../shared/lib/loadable.shared-runtime'
diff --git a/packages/next/src/server/future/route-modules/app-route/module.compiled.ts b/packages/next/src/server/future/route-modules/app-route/module.compiled.ts
new file mode 100644
index 0000000000000..f5909104bc772
--- /dev/null
+++ b/packages/next/src/server/future/route-modules/app-route/module.compiled.ts
@@ -0,0 +1,11 @@
+if (process.env.NEXT_RUNTIME === 'edge') {
+ module.exports = require('next/dist/server/future/route-modules/app-route/module.js')
+} else {
+ if (process.env.NODE_ENV === 'development') {
+ module.exports = require('next/dist/compiled/next-server/app-route.runtime.dev.js')
+ } else if (process.env.TURBOPACK) {
+ module.exports = require('next/dist/compiled/next-server/app-route-turbo.runtime.prod.js')
+ } else {
+ module.exports = require('next/dist/compiled/next-server/app-route.runtime.prod.js')
+ }
+}
diff --git a/packages/next/src/server/future/route-modules/app-route/module.ts b/packages/next/src/server/future/route-modules/app-route/module.ts
index bf47738d35fea..d1d36d31501e4 100644
--- a/packages/next/src/server/future/route-modules/app-route/module.ts
+++ b/packages/next/src/server/future/route-modules/app-route/module.ts
@@ -35,22 +35,14 @@ import { appendMutableCookies } from '../../../web/spec-extension/adapters/reque
import { RouteKind } from '../../route-kind'
import { parsedUrlQueryToParams } from './helpers/parsed-url-query-to-params'
-// These are imported weirdly like this because of the way that the bundling
-// works. We need to import the built files from the dist directory, but we
-// can't do that directly because we need types from the source files. So we
-// import the types from the source files and then import the built files.
-const { requestAsyncStorage } =
- require('next/dist/client/components/request-async-storage') as typeof import('../../../../client/components/request-async-storage')
-const { staticGenerationAsyncStorage } =
- require('next/dist/client/components/static-generation-async-storage') as typeof import('../../../../client/components/static-generation-async-storage')
-const serverHooks =
- require('next/dist/client/components/hooks-server-context') as typeof import('../../../../client/components/hooks-server-context')
-const headerHooks =
- require('next/dist/client/components/headers') as typeof import('../../../../client/components/headers')
-const { staticGenerationBailout } =
- require('next/dist/client/components/static-generation-bailout') as typeof import('../../../../client/components/static-generation-bailout')
-const { actionAsyncStorage } =
- require('next/dist/client/components/action-async-storage') as typeof import('../../../../client/components/action-async-storage')
+import * as serverHooks from '../../../../client/components/hooks-server-context'
+import * as headerHooks from '../../../../client/components/headers'
+import { staticGenerationBailout } from '../../../../client/components/static-generation-bailout'
+
+import { requestAsyncStorage } from '../../../../client/components/request-async-storage.external'
+import { staticGenerationAsyncStorage } from '../../../../client/components/static-generation-async-storage.external'
+import { actionAsyncStorage } from '../../../../client/components/action-async-storage.external'
+import * as sharedModules from './shared-modules'
/**
* AppRouteRouteHandlerContext is the context that is passed to the route
@@ -147,6 +139,8 @@ export class AppRouteRouteModule extends RouteModule<
*/
public readonly staticGenerationBailout = staticGenerationBailout
+ public static readonly sharedModules = sharedModules
+
/**
* A reference to the mutation related async storage, such as mutations of
* cookies.
diff --git a/packages/next/src/server/future/route-modules/app-route/shared-modules.ts b/packages/next/src/server/future/route-modules/app-route/shared-modules.ts
new file mode 100644
index 0000000000000..e6139d5a69404
--- /dev/null
+++ b/packages/next/src/server/future/route-modules/app-route/shared-modules.ts
@@ -0,0 +1,3 @@
+// the name of the export has to be the camelCase version of the file name (without the extension)
+// TODO: remove this. We need it because using notFound from next/navigation imports this file :(
+export * as appRouterContext from '../../../../shared/lib/app-router-context.shared-runtime'
diff --git a/packages/next/src/server/future/route-modules/pages-api/module.compiled.ts b/packages/next/src/server/future/route-modules/pages-api/module.compiled.ts
new file mode 100644
index 0000000000000..ed74c41adb918
--- /dev/null
+++ b/packages/next/src/server/future/route-modules/pages-api/module.compiled.ts
@@ -0,0 +1,11 @@
+if (process.env.NEXT_RUNTIME === 'edge') {
+ module.exports = require('next/dist/server/future/route-modules/pages-api/module.js')
+} else {
+ if (process.env.NODE_ENV === 'development') {
+ module.exports = require('next/dist/compiled/next-server/pages-api.runtime.dev.js')
+ } else if (process.env.TURBOPACK) {
+ module.exports = require('next/dist/compiled/next-server/pages-api-turbo.runtime.prod.js')
+ } else {
+ module.exports = require('next/dist/compiled/next-server/pages-api.runtime.prod.js')
+ }
+}
diff --git a/packages/next/src/server/future/route-modules/pages-api/module.ts b/packages/next/src/server/future/route-modules/pages-api/module.ts
index 88dbda73b464c..976daeeec4a87 100644
--- a/packages/next/src/server/future/route-modules/pages-api/module.ts
+++ b/packages/next/src/server/future/route-modules/pages-api/module.ts
@@ -100,6 +100,16 @@ export class PagesAPIRouteModule extends RouteModule<
PagesAPIRouteDefinition,
PagesAPIUserlandModule
> {
+ constructor(options: PagesAPIRouteModuleOptions) {
+ super(options)
+
+ if (typeof options.userland.default !== 'function') {
+ throw new Error(
+ `Page ${options.definition.page} does not export a default function.`
+ )
+ }
+ }
+
/**
*
* @param req the incoming server request
diff --git a/packages/next/src/server/future/route-modules/pages/module.compiled.ts b/packages/next/src/server/future/route-modules/pages/module.compiled.ts
new file mode 100644
index 0000000000000..a935b62abdcad
--- /dev/null
+++ b/packages/next/src/server/future/route-modules/pages/module.compiled.ts
@@ -0,0 +1,11 @@
+if (process.env.NEXT_RUNTIME === 'edge') {
+ module.exports = require('next/dist/server/future/route-modules/pages/module.js')
+} else {
+ if (process.env.NODE_ENV === 'development') {
+ module.exports = require('next/dist/compiled/next-server/pages.runtime.dev.js')
+ } else if (process.env.TURBOPACK) {
+ module.exports = require('next/dist/compiled/next-server/pages-turbo.runtime.prod.js')
+ } else {
+ module.exports = require('next/dist/compiled/next-server/pages.runtime.prod.js')
+ }
+}
diff --git a/packages/next/src/server/future/route-modules/pages/module.ts b/packages/next/src/server/future/route-modules/pages/module.ts
index dac8ae5546441..e2730ef668901 100644
--- a/packages/next/src/server/future/route-modules/pages/module.ts
+++ b/packages/next/src/server/future/route-modules/pages/module.ts
@@ -17,7 +17,8 @@ import {
type RouteModuleHandleContext,
type RouteModuleOptions,
} from '../route-module'
-import { renderToHTMLImpl } from '../../../render'
+import { renderToHTMLImpl, renderToHTML } from '../../../render'
+import * as sharedModules from './shared-modules'
/**
* The userland module for a page. This is the module that is exported from the
@@ -104,6 +105,8 @@ export class PagesRouteModule extends RouteModule<
> {
private readonly components: PagesComponents
+ static readonly sharedModules = sharedModules
+
constructor(options: PagesRouteModuleOptions) {
super(options)
@@ -129,4 +132,7 @@ export class PagesRouteModule extends RouteModule<
}
}
+// needed for the static build
+export { renderToHTML }
+
export default PagesRouteModule
diff --git a/packages/next/src/server/future/route-modules/pages/shared-modules.ts b/packages/next/src/server/future/route-modules/pages/shared-modules.ts
new file mode 100644
index 0000000000000..55cdfbdeca37c
--- /dev/null
+++ b/packages/next/src/server/future/route-modules/pages/shared-modules.ts
@@ -0,0 +1,12 @@
+// the name of the export has to be the camelCase version of the file name (without the extension)
+export * as htmlContext from '../../../../shared/lib/html-context.shared-runtime'
+export * as routerContext from '../../../../shared/lib/router-context.shared-runtime'
+export * as ampContext from '../../../../shared/lib/amp-context.shared-runtime'
+export * as headManagerContext from '../../../../shared/lib/head-manager-context.shared-runtime'
+export * as adapters from '../../../../shared/lib/router/adapters.shared-runtime'
+export * as loadableContext from '../../../../shared/lib/loadable-context.shared-runtime'
+export * as appRouterContext from '../../../../shared/lib/app-router-context.shared-runtime'
+export * as hooksClientContext from '../../../../shared/lib/hooks-client-context.shared-runtime'
+export * as imageConfigContext from '../../../../shared/lib/image-config-context.shared-runtime'
+export * as runtimeConfig from '../../../../shared/lib/runtime-config.shared-runtime'
+export * as loadable from '../../../../shared/lib/loadable.shared-runtime'
diff --git a/packages/next/src/server/future/route-modules/route-module.ts b/packages/next/src/server/future/route-modules/route-module.ts
index 52188ed506dff..a8e5dd6c5945a 100644
--- a/packages/next/src/server/future/route-modules/route-module.ts
+++ b/packages/next/src/server/future/route-modules/route-module.ts
@@ -44,6 +44,11 @@ export abstract class RouteModule<
*/
public readonly definition: Readonly
+ /**
+ * The shared modules that are exposed and required for the route module.
+ */
+ public static readonly sharedModules: any
+
constructor({ userland, definition }: RouteModuleOptions) {
this.userland = userland
this.definition = definition
diff --git a/packages/next/src/server/lib/incremental-cache/index.ts b/packages/next/src/server/lib/incremental-cache/index.ts
index ae2b11b4dc00f..3032aa685300b 100644
--- a/packages/next/src/server/lib/incremental-cache/index.ts
+++ b/packages/next/src/server/lib/incremental-cache/index.ts
@@ -131,7 +131,10 @@ export class IncrementalCache {
maxMemoryCacheSize = parseInt(process.env.__NEXT_TEST_MAX_ISR_CACHE, 10)
}
this.dev = dev
- this.minimalMode = minimalMode
+ // this is a hack to avoid Webpack knowing this is equal to this.minimalMode
+ // because we replace this.minimalMode to true in production bundles.
+ const minimalModeKey = 'minimalMode'
+ this[minimalModeKey] = minimalMode
this.requestHeaders = requestHeaders
this.requestProtocol = requestProtocol
this.allowedRevalidateHeaderKeys = allowedRevalidateHeaderKeys
diff --git a/packages/next/src/server/lib/patch-fetch.ts b/packages/next/src/server/lib/patch-fetch.ts
index fb4d02c97b251..080361704b718 100644
--- a/packages/next/src/server/lib/patch-fetch.ts
+++ b/packages/next/src/server/lib/patch-fetch.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage'
+import type { StaticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage.external'
import type * as ServerHooks from '../../client/components/hooks-server-context'
import { AppRenderSpan, NextNodeServerSpan } from './trace/constants'
diff --git a/packages/next/src/server/lib/server-ipc/index.ts b/packages/next/src/server/lib/server-ipc/index.ts
index 8e7bd60a8855d..023cbde2d25d8 100644
--- a/packages/next/src/server/lib/server-ipc/index.ts
+++ b/packages/next/src/server/lib/server-ipc/index.ts
@@ -115,6 +115,7 @@ export const createWorker = async (
__NEXT_PRIVATE_STANDALONE_CONFIG:
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG,
NODE_ENV: process.env.NODE_ENV,
+ __NEXT_PRIVATE_RENDER_RUNTIME: type,
__NEXT_PRIVATE_PREBUNDLED_REACT:
type === 'app' ? (useServerActions ? 'experimental' : 'next') : '',
...(process.env.NEXT_CPU_PROF
diff --git a/packages/next/src/server/lib/trace/constants.ts b/packages/next/src/server/lib/trace/constants.ts
index 50eb4528c7dec..1b45358bdf8ed 100644
--- a/packages/next/src/server/lib/trace/constants.ts
+++ b/packages/next/src/server/lib/trace/constants.ts
@@ -43,7 +43,6 @@ enum NextNodeServerSpan {
generatePublicRoutes = 'NextNodeServer.generatePublicRoutes',
generateImageRoutes = 'NextNodeServer.generateImageRoutes.route',
sendRenderResult = 'NextNodeServer.sendRenderResult',
- sendStatic = 'NextNodeServer.sendStatic',
proxyRequest = 'NextNodeServer.proxyRequest',
runApi = 'NextNodeServer.runApi',
render = 'NextNodeServer.render',
diff --git a/packages/next/src/server/load-components.ts b/packages/next/src/server/load-components.ts
index d2b563493ebe6..39da802ff39b1 100644
--- a/packages/next/src/server/load-components.ts
+++ b/packages/next/src/server/load-components.ts
@@ -55,7 +55,7 @@ export type LoadComponentsReturnType = {
/**
* Load manifest file with retries, defaults to 3 attempts.
*/
-async function loadManifestWithRetries(
+export async function loadManifestWithRetries(
manifestPath: string,
attempts = 3
): Promise {
@@ -87,34 +87,6 @@ async function loadJSManifest(
}
}
-async function loadDefaultErrorComponentsImpl(
- distDir: string
-): Promise {
- const Document = interopDefault(require('next/dist/pages/_document'))
- const AppMod = require('next/dist/pages/_app')
- const App = interopDefault(AppMod)
-
- // Load the compiled route module for this builtin error.
- // TODO: (wyattjoh) replace this with just exporting the route module when the transition is complete
- const ComponentMod =
- require('./future/route-modules/pages/builtin/_error') as typeof import('./future/route-modules/pages/builtin/_error')
- const Component = ComponentMod.routeModule.userland.default
-
- return {
- App,
- Document,
- Component,
- pageConfig: {},
- buildManifest: await loadManifestWithRetries(
- join(distDir, `fallback-${BUILD_MANIFEST}`)
- ),
- reactLoadableManifest: {},
- ComponentMod,
- pathname: '/_error',
- routeModule: ComponentMod.routeModule,
- }
-}
-
async function loadComponentsImpl({
distDir,
pathname,
@@ -205,8 +177,3 @@ export const loadComponents = getTracer().wrap(
LoadComponentsSpan.loadComponents,
loadComponentsImpl
)
-
-export const loadDefaultErrorComponents = getTracer().wrap(
- LoadComponentsSpan.loadDefaultErrorComponents,
- loadDefaultErrorComponentsImpl
-)
diff --git a/packages/next/src/server/load-default-error-components.ts b/packages/next/src/server/load-default-error-components.ts
new file mode 100644
index 0000000000000..c390e9180b3d9
--- /dev/null
+++ b/packages/next/src/server/load-default-error-components.ts
@@ -0,0 +1,78 @@
+import type {
+ AppType,
+ DocumentType,
+ NextComponentType,
+} from '../shared/lib/utils'
+import type { ClientReferenceManifest } from '../build/webpack/plugins/flight-manifest-plugin'
+import type {
+ PageConfig,
+ GetStaticPaths,
+ GetServerSideProps,
+ GetStaticProps,
+} from 'next/types'
+import type { RouteModule } from './future/route-modules/route-module'
+
+import { BUILD_MANIFEST } from '../shared/lib/constants'
+import { join } from 'path'
+import { BuildManifest } from './get-page-files'
+import { interopDefault } from '../lib/interop-default'
+import { getTracer } from './lib/trace/tracer'
+import { LoadComponentsSpan } from './lib/trace/constants'
+import { loadManifestWithRetries } from './load-components'
+export type ManifestItem = {
+ id: number | string
+ files: string[]
+}
+
+export type ReactLoadableManifest = { [moduleId: string]: ManifestItem }
+
+export type LoadComponentsReturnType = {
+ Component: NextComponentType
+ pageConfig: PageConfig
+ buildManifest: BuildManifest
+ subresourceIntegrityManifest?: Record
+ reactLoadableManifest: ReactLoadableManifest
+ clientReferenceManifest?: ClientReferenceManifest
+ serverActionsManifest?: any
+ Document: DocumentType
+ App: AppType
+ getStaticProps?: GetStaticProps
+ getStaticPaths?: GetStaticPaths
+ getServerSideProps?: GetServerSideProps
+ ComponentMod: any
+ routeModule?: RouteModule
+ isAppPath?: boolean
+ pathname: string
+}
+
+async function loadDefaultErrorComponentsImpl(
+ distDir: string
+): Promise {
+ const Document = interopDefault(require('next/dist/pages/_document'))
+ const AppMod = require('next/dist/pages/_app')
+ const App = interopDefault(AppMod)
+
+ // Load the compiled route module for this builtin error.
+ // TODO: (wyattjoh) replace this with just exporting the route module when the transition is complete
+ const ComponentMod =
+ require('./future/route-modules/pages/builtin/_error') as typeof import('./future/route-modules/pages/builtin/_error')
+ const Component = ComponentMod.routeModule.userland.default
+
+ return {
+ App,
+ Document,
+ Component,
+ pageConfig: {},
+ buildManifest: await loadManifestWithRetries(
+ join(distDir, `fallback-${BUILD_MANIFEST}`)
+ ),
+ reactLoadableManifest: {},
+ ComponentMod,
+ pathname: '/_error',
+ routeModule: ComponentMod.routeModule,
+ }
+}
+export const loadDefaultErrorComponents = getTracer().wrap(
+ LoadComponentsSpan.loadDefaultErrorComponents,
+ loadDefaultErrorComponentsImpl
+)
diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts
index 087752225090f..7abf3605541ad 100644
--- a/packages/next/src/server/next-server.ts
+++ b/packages/next/src/server/next-server.ts
@@ -15,7 +15,7 @@ import {
import type { MiddlewareManifest } from '../build/webpack/plugins/middleware-plugin'
import type RenderResult from './render-result'
import type { FetchEventResult } from './web/types'
-import type { PrerenderManifest, RoutesManifest } from '../build'
+import type { PrerenderManifest } from '../build'
import { BaseNextRequest, BaseNextResponse } from './base-http'
import type { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin'
import type { PayloadOptions } from './send-payload'
@@ -26,7 +26,6 @@ import {
} from '../shared/lib/router/utils/route-matcher'
import type { MiddlewareRouteMatch } from '../shared/lib/router/utils/middleware-route-matcher'
import type { RouteMatch } from './future/route-matches/route-match'
-import { renderToHTML, type RenderOpts } from './render'
import fs from 'fs'
import { join, resolve, isAbsolute } from 'path'
@@ -49,7 +48,6 @@ import { findDir } from '../lib/find-pages-dir'
import { UrlWithParsedQuery } from 'url'
import { NodeNextRequest, NodeNextResponse } from './base-http/node'
import { sendRenderResult } from './send-payload'
-import { getExtension, serveStatic } from './serve-static'
import { ParsedUrlQuery } from 'querystring'
import { ParsedUrl, parseUrl } from '../shared/lib/router/utils/parse-url'
import * as Log from '../build/output/log'
@@ -96,7 +94,6 @@ import { invokeRequest } from './lib/server-ipc/invoke-request'
import { pipeReadable } from './pipe-readable'
import { filterReqHeaders, ipcForbiddenHeaders } from './lib/server-ipc/utils'
import { createRequestResponseMocks } from './lib/mock-request'
-import chalk from 'next/dist/compiled/chalk'
import { NEXT_RSC_UNION_QUERY } from '../client/components/app-router-headers'
import { signalFromNodeResponse } from './web/spec-extension/adapters/next-request'
import { RouteModuleLoader } from './future/helpers/module-loader/route-module-loader'
@@ -382,14 +379,6 @@ export default class NextNodeServer extends BaseServer {
})
}
- protected sendStatic(
- req: NodeNextRequest,
- res: NodeNextResponse,
- path: string
- ): Promise {
- return serveStatic(req.originalRequest, res.originalResponse, path)
- }
-
protected async runApi(
req: BaseNextRequest | NodeNextRequest,
res: BaseNextResponse | NodeNextResponse,
@@ -452,7 +441,7 @@ export default class NextNodeServer extends BaseServer {
res: NodeNextResponse,
pathname: string,
query: NextParsedUrlQuery,
- renderOpts: RenderOpts
+ renderOpts: import('./render').RenderOpts
): Promise {
return getTracer().trace(NextNodeServerSpan.renderHTML, async () =>
this.renderHTMLImpl(req, res, pathname, query, renderOpts)
@@ -464,17 +453,35 @@ export default class NextNodeServer extends BaseServer {
res: NodeNextResponse,
pathname: string,
query: NextParsedUrlQuery,
- renderOpts: RenderOpts
+ renderOpts: import('./render').RenderOpts
): Promise {
- // Due to the way we pass data by mutating `renderOpts`, we can't extend the
- // object here but only updating its `nextFontManifest` field.
- // https://github.com/vercel/next.js/blob/df7cbd904c3bd85f399d1ce90680c0ecf92d2752/packages/next/server/render.tsx#L947-L952
- renderOpts.nextFontManifest = this.nextFontManifest
-
- if (this.hasAppDir && renderOpts.isAppPath) {
- const { renderToHTMLOrFlight: appRenderToHTMLOrFlight } =
- require('./app-render/app-render') as typeof import('./app-render/app-render')
- return appRenderToHTMLOrFlight(
+ if (process.env.NEXT_MINIMAL) {
+ throw new Error(
+ 'invariant: renderHTML should not be called in minimal mode'
+ )
+ // the `else` branch is needed for tree-shaking
+ } else {
+ // Due to the way we pass data by mutating `renderOpts`, we can't extend the
+ // object here but only updating its `nextFontManifest` field.
+ // https://github.com/vercel/next.js/blob/df7cbd904c3bd85f399d1ce90680c0ecf92d2752/packages/next/server/render.tsx#L947-L952
+ renderOpts.nextFontManifest = this.nextFontManifest
+
+ if (this.hasAppDir && renderOpts.isAppPath) {
+ const { renderToHTMLOrFlight: appRenderToHTMLOrFlight } =
+ require('./future/route-modules/app-page/module.compiled') as typeof import('./app-render/app-render')
+ return appRenderToHTMLOrFlight(
+ req.originalRequest,
+ res.originalResponse,
+ pathname,
+ query,
+ renderOpts
+ )
+ }
+
+ // TODO: re-enable this once we've refactored to use implicit matches
+ // throw new Error('Invariant: render should have used routeModule')
+
+ return require('./future/route-modules/pages/module.compiled').renderToHTML(
req.originalRequest,
res.originalResponse,
pathname,
@@ -482,17 +489,6 @@ export default class NextNodeServer extends BaseServer {
renderOpts
)
}
-
- // TODO: re-enable this once we've refactored to use implicit matches
- // throw new Error('Invariant: render should have used routeModule')
-
- return renderToHTML(
- req.originalRequest,
- res.originalResponse,
- pathname,
- query,
- renderOpts
- )
}
protected async imageOptimizer(
@@ -500,55 +496,63 @@ export default class NextNodeServer extends BaseServer {
res: NodeNextResponse,
paramsResult: import('./image-optimizer').ImageParamsResult
): Promise<{ buffer: Buffer; contentType: string; maxAge: number }> {
- const { imageOptimizer } =
- require('./image-optimizer') as typeof import('./image-optimizer')
-
- return imageOptimizer(
- req.originalRequest,
- res.originalResponse,
- paramsResult,
- this.nextConfig,
- this.renderOpts.dev,
- async (newReq, newRes, newParsedUrl) => {
- if (newReq.url === req.url) {
- throw new Error(`Invariant attempted to optimize _next/image itself`)
- }
-
- if (this.isRenderWorker) {
- const invokeRes = await invokeRequest(
- `http://${this.fetchHostname || 'localhost'}:${this.port}${
- newReq.url || ''
- }`,
- {
- method: newReq.method || 'GET',
- headers: newReq.headers,
- signal: signalFromNodeResponse(res.originalResponse),
- }
- )
- const filteredResHeaders = filterReqHeaders(
- toNodeOutgoingHttpHeaders(invokeRes.headers),
- ipcForbiddenHeaders
- )
+ if (process.env.NEXT_MINIMAL) {
+ throw new Error(
+ 'invariant: imageOptimizer should not be called in minimal mode'
+ )
+ } else {
+ const { imageOptimizer } =
+ require('./image-optimizer') as typeof import('./image-optimizer')
- for (const key of Object.keys(filteredResHeaders)) {
- newRes.setHeader(key, filteredResHeaders[key] || '')
+ return imageOptimizer(
+ req.originalRequest,
+ res.originalResponse,
+ paramsResult,
+ this.nextConfig,
+ this.renderOpts.dev,
+ async (newReq, newRes, newParsedUrl) => {
+ if (newReq.url === req.url) {
+ throw new Error(
+ `Invariant attempted to optimize _next/image itself`
+ )
}
- newRes.statusCode = invokeRes.status || 200
- if (invokeRes.body) {
- await pipeReadable(invokeRes.body, newRes)
- } else {
- res.send()
+ if (this.isRenderWorker) {
+ const invokeRes = await invokeRequest(
+ `http://${this.fetchHostname || 'localhost'}:${this.port}${
+ newReq.url || ''
+ }`,
+ {
+ method: newReq.method || 'GET',
+ headers: newReq.headers,
+ signal: signalFromNodeResponse(res.originalResponse),
+ }
+ )
+ const filteredResHeaders = filterReqHeaders(
+ toNodeOutgoingHttpHeaders(invokeRes.headers),
+ ipcForbiddenHeaders
+ )
+
+ for (const key of Object.keys(filteredResHeaders)) {
+ newRes.setHeader(key, filteredResHeaders[key] || '')
+ }
+ newRes.statusCode = invokeRes.status || 200
+
+ if (invokeRes.body) {
+ await pipeReadable(invokeRes.body, newRes)
+ } else {
+ res.send()
+ }
+ return
}
- return
+ return this.getRequestHandler()(
+ new NodeNextRequest(newReq),
+ new NodeNextResponse(newRes),
+ newParsedUrl
+ )
}
- return this.getRequestHandler()(
- new NodeNextRequest(newReq),
- new NodeNextResponse(newRes),
- newParsedUrl
- )
- }
- )
+ )
+ }
}
protected getPagePath(pathname: string, locales?: string[]): string {
@@ -719,99 +723,109 @@ export default class NextNodeServer extends BaseServer {
res: BaseNextResponse,
parsedUrl: NextUrlWithParsedQuery
) {
- if (this.minimalMode || this.nextConfig.output === 'export') {
+ if (
+ this.minimalMode ||
+ this.nextConfig.output === 'export' ||
+ process.env.NEXT_MINIMAL
+ ) {
res.statusCode = 400
res.body('Bad Request').send()
return {
finished: true,
}
- }
- const { ImageOptimizerCache } =
- require('./image-optimizer') as typeof import('./image-optimizer')
+ // the `else` branch is needed for tree-shaking
+ } else {
+ const { ImageOptimizerCache } =
+ require('./image-optimizer') as typeof import('./image-optimizer')
- const imageOptimizerCache = new ImageOptimizerCache({
- distDir: this.distDir,
- nextConfig: this.nextConfig,
- })
+ const imageOptimizerCache = new ImageOptimizerCache({
+ distDir: this.distDir,
+ nextConfig: this.nextConfig,
+ })
- const { getHash, sendResponse, ImageError } =
- require('./image-optimizer') as typeof import('./image-optimizer')
+ const { getHash, sendResponse, ImageError } =
+ require('./image-optimizer') as typeof import('./image-optimizer')
- if (!this.imageResponseCache) {
- throw new Error('invariant image optimizer cache was not initialized')
- }
- const imagesConfig = this.nextConfig.images
+ if (!this.imageResponseCache) {
+ throw new Error('invariant image optimizer cache was not initialized')
+ }
+ const imagesConfig = this.nextConfig.images
- if (imagesConfig.loader !== 'default' || imagesConfig.unoptimized) {
- await this.render404(req, res)
- return { finished: true }
- }
- const paramsResult = ImageOptimizerCache.validateParams(
- (req as NodeNextRequest).originalRequest,
- parsedUrl.query,
- this.nextConfig,
- !!this.renderOpts.dev
- )
+ if (imagesConfig.loader !== 'default' || imagesConfig.unoptimized) {
+ await this.render404(req, res)
+ return { finished: true }
+ }
+ const paramsResult = ImageOptimizerCache.validateParams(
+ (req as NodeNextRequest).originalRequest,
+ parsedUrl.query,
+ this.nextConfig,
+ !!this.renderOpts.dev
+ )
- if ('errorMessage' in paramsResult) {
- res.statusCode = 400
- res.body(paramsResult.errorMessage).send()
- return { finished: true }
- }
- const cacheKey = ImageOptimizerCache.getCacheKey(paramsResult)
+ if ('errorMessage' in paramsResult) {
+ res.statusCode = 400
+ res.body(paramsResult.errorMessage).send()
+ return { finished: true }
+ }
+ const cacheKey = ImageOptimizerCache.getCacheKey(paramsResult)
- try {
- const cacheEntry = await this.imageResponseCache.get(
- cacheKey,
- async () => {
- const { buffer, contentType, maxAge } = await this.imageOptimizer(
- req as NodeNextRequest,
- res as NodeNextResponse,
- paramsResult
- )
- const etag = getHash([buffer])
+ try {
+ const { getExtension } =
+ require('./serve-static') as typeof import('./serve-static')
+ const cacheEntry = await this.imageResponseCache.get(
+ cacheKey,
+ async () => {
+ const { buffer, contentType, maxAge } = await this.imageOptimizer(
+ req as NodeNextRequest,
+ res as NodeNextResponse,
+ paramsResult
+ )
+ const etag = getHash([buffer])
+
+ return {
+ value: {
+ kind: 'IMAGE',
+ buffer,
+ etag,
+ extension: getExtension(contentType) as string,
+ },
+ revalidate: maxAge,
+ }
+ },
+ {
+ incrementalCache: imageOptimizerCache,
+ }
+ )
+ if (cacheEntry?.value?.kind !== 'IMAGE') {
+ throw new Error(
+ 'invariant did not get entry from image response cache'
+ )
+ }
+ sendResponse(
+ (req as NodeNextRequest).originalRequest,
+ (res as NodeNextResponse).originalResponse,
+ paramsResult.href,
+ cacheEntry.value.extension,
+ cacheEntry.value.buffer,
+ paramsResult.isStatic,
+ cacheEntry.isMiss ? 'MISS' : cacheEntry.isStale ? 'STALE' : 'HIT',
+ imagesConfig,
+ cacheEntry.revalidate || 0,
+ Boolean(this.renderOpts.dev)
+ )
+ } catch (err) {
+ if (err instanceof ImageError) {
+ res.statusCode = err.statusCode
+ res.body(err.message).send()
return {
- value: {
- kind: 'IMAGE',
- buffer,
- etag,
- extension: getExtension(contentType) as string,
- },
- revalidate: maxAge,
+ finished: true,
}
- },
- {
- incrementalCache: imageOptimizerCache,
- }
- )
-
- if (cacheEntry?.value?.kind !== 'IMAGE') {
- throw new Error('invariant did not get entry from image response cache')
- }
- sendResponse(
- (req as NodeNextRequest).originalRequest,
- (res as NodeNextResponse).originalResponse,
- paramsResult.href,
- cacheEntry.value.extension,
- cacheEntry.value.buffer,
- paramsResult.isStatic,
- cacheEntry.isMiss ? 'MISS' : cacheEntry.isStale ? 'STALE' : 'HIT',
- imagesConfig,
- cacheEntry.revalidate || 0,
- Boolean(this.renderOpts.dev)
- )
- } catch (err) {
- if (err instanceof ImageError) {
- res.statusCode = err.statusCode
- res.body(err.message).send()
- return {
- finished: true,
}
+ throw err
}
- throw err
+ return { finished: true }
}
- return { finished: true }
}
protected async handleCatchallRenderRequest(
@@ -1012,6 +1026,7 @@ export default class NextNodeServer extends BaseServer {
const enabledVerboseLogging =
this.nextConfig.experimental.logging === 'verbose'
if (this.renderOpts.dev) {
+ const chalk = require('next/dist/compiled/chalk')
const _req = req as NodeNextRequest | IncomingMessage
const _res = res as NodeNextResponse | ServerResponse
const origReq = 'originalRequest' in _req ? _req.originalRequest : _req
@@ -1432,6 +1447,12 @@ export default class NextNodeServer extends BaseServer {
parsed: UrlWithParsedQuery
onWarning?: (warning: Error) => void
}) {
+ if (process.env.NEXT_MINIMAL) {
+ throw new Error(
+ 'invariant: runMiddleware should not be called in minimal mode'
+ )
+ }
+
// Middleware is skipped for on-demand revalidate requests
if (
checkIsOnDemandRevalidate(params.request, this.renderOpts.previewProps)
@@ -1675,10 +1696,7 @@ export default class NextNodeServer extends BaseServer {
protected getRoutesManifest(): NormalizedRouteManifest | undefined {
return getTracer().trace(NextNodeServerSpan.getRoutesManifest, () => {
- const manifest: RoutesManifest = require(join(
- this.distDir,
- ROUTES_MANIFEST
- ))
+ const manifest = loadManifest(join(this.distDir, ROUTES_MANIFEST))
let rewrites = manifest.rewrites ?? {
beforeFiles: [],
@@ -1736,6 +1754,11 @@ export default class NextNodeServer extends BaseServer {
match?: RouteMatch
onWarning?: (warning: Error) => void
}): Promise {
+ if (process.env.NEXT_MINIMAL) {
+ throw new Error(
+ 'Middleware is not supported in minimal mode. Please remove the `NEXT_MINIMAL` environment variable.'
+ )
+ }
let edgeInfo: ReturnType | undefined
const { query, page, match } = params
diff --git a/packages/next/src/server/render-result.ts b/packages/next/src/server/render-result.ts
index b93dfce5fae21..2a8252e4fd143 100644
--- a/packages/next/src/server/render-result.ts
+++ b/packages/next/src/server/render-result.ts
@@ -1,4 +1,4 @@
-import { StaticGenerationStore } from '../client/components/static-generation-async-storage'
+import { StaticGenerationStore } from '../client/components/static-generation-async-storage.external'
import { pipeReadable, PipeTarget } from './pipe-readable'
type ContentTypeOption = string | undefined
diff --git a/packages/next/src/server/render.tsx b/packages/next/src/server/render.tsx
index ac0989082aa9b..fe36e793348e2 100644
--- a/packages/next/src/server/render.tsx
+++ b/packages/next/src/server/render.tsx
@@ -1,7 +1,7 @@
import type { IncomingMessage, ServerResponse } from 'http'
import type { ParsedUrlQuery } from 'querystring'
import type { NextRouter } from '../shared/lib/router/router'
-import type { HtmlProps } from '../shared/lib/html-context'
+import type { HtmlProps } from '../shared/lib/html-context.shared-runtime'
import type { DomainLocale } from './config'
import type {
AppType,
@@ -52,12 +52,12 @@ import {
} from '../shared/lib/constants'
import { isSerializableProps } from '../lib/is-serializable-props'
import { isInAmpMode } from '../shared/lib/amp-mode'
-import { AmpStateContext } from '../shared/lib/amp-context'
+import { AmpStateContext } from '../shared/lib/amp-context.shared-runtime'
import { defaultHead } from '../shared/lib/head'
-import { HeadManagerContext } from '../shared/lib/head-manager-context'
-import Loadable from '../shared/lib/loadable'
-import { LoadableContext } from '../shared/lib/loadable-context'
-import { RouterContext } from '../shared/lib/router-context'
+import { HeadManagerContext } from '../shared/lib/head-manager-context.shared-runtime'
+import Loadable from '../shared/lib/loadable.shared-runtime'
+import { LoadableContext } from '../shared/lib/loadable-context.shared-runtime'
+import { RouterContext } from '../shared/lib/router-context.shared-runtime'
import { isDynamicRoute } from '../shared/lib/router/utils/is-dynamic'
import {
ComponentsEnhancer,
@@ -65,7 +65,7 @@ import {
isResSent,
loadGetInitialProps,
} from '../shared/lib/utils'
-import { HtmlContext } from '../shared/lib/html-context'
+import { HtmlContext } from '../shared/lib/html-context.shared-runtime'
import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path'
import { denormalizePagePath } from '../shared/lib/page-path/denormalize-page-path'
import { getRequestMeta, NextParsedUrlQuery } from './request-meta'
@@ -79,16 +79,16 @@ import {
renderToInitialStream,
continueFromInitialStream,
} from './stream-utils/node-web-streams-helper'
-import { ImageConfigContext } from '../shared/lib/image-config-context'
+import { ImageConfigContext } from '../shared/lib/image-config-context.shared-runtime'
import stripAnsi from 'next/dist/compiled/strip-ansi'
import { stripInternalQueries } from './internal-utils'
import {
adaptForAppRouterInstance,
adaptForSearchParams,
PathnameContextProviderAdapter,
-} from '../shared/lib/router/adapters'
-import { AppRouterContext } from '../shared/lib/app-router-context'
-import { SearchParamsContext } from '../shared/lib/hooks-client-context'
+} from '../shared/lib/router/adapters.shared-runtime'
+import { AppRouterContext } from '../shared/lib/app-router-context.shared-runtime'
+import { SearchParamsContext } from '../shared/lib/hooks-client-context.shared-runtime'
import { getTracer } from './lib/trace/tracer'
import { RenderSpan } from './lib/trace/constants'
import { ReflectAdapter } from './web/spec-extension/adapters/reflect'
diff --git a/packages/next/src/server/require-hook.ts b/packages/next/src/server/require-hook.ts
index 1f53b3b479109..9b2e1526eec0e 100644
--- a/packages/next/src/server/require-hook.ts
+++ b/packages/next/src/server/require-hook.ts
@@ -2,11 +2,13 @@
// This is needed for userland plugins to attach to the same webpack instance as Next.js'.
// Individually compiled modules are as defined for the compilation in bundles/webpack/packages/*.
+import path, { dirname } from 'path'
+
// This module will only be loaded once per process.
-const { dirname } = require('path')
const mod = require('module')
const resolveFilename = mod._resolveFilename
+const originalRequire = mod.prototype.require
const hookPropertyMap = new Map()
let aliasedPrebundledReact = false
@@ -19,10 +21,9 @@ const resolve = process.env.NEXT_MINIMAL
const toResolveMap = (map: Record): [string, string][] =>
Object.entries(map).map(([key, value]) => [key, resolve(value)])
-// these must use require.resolve to be statically analyzable
export const defaultOverrides = {
- 'styled-jsx': dirname(require.resolve('styled-jsx/package.json')),
- 'styled-jsx/style': require.resolve('styled-jsx/style'),
+ 'styled-jsx': dirname(resolve('styled-jsx/package.json')),
+ 'styled-jsx/style': resolve('styled-jsx/style'),
}
export const baseOverrides = {
@@ -78,7 +79,6 @@ export function addHookAliases(aliases: [string, string][] = []) {
}
}
-// Add default aliases
addHookAliases(toResolveMap(defaultOverrides))
// Override built-in React packages if necessary
@@ -117,3 +117,29 @@ mod._resolveFilename = function (
// We use `bind` here to avoid referencing outside variables to create potential memory leaks.
}.bind(null, resolveFilename, hookPropertyMap)
+
+// This is a hack to make sure that if a user requires a Next.js module that wasn't bundled
+// that needs to point to the rendering runtime version, it will point to the correct one.
+// This can happen on `pages` when a user requires a dependency that uses next/image for example.
+// This is only needed in production as in development we fallback to the external version.
+if (
+ process.env.NODE_ENV !== 'development' &&
+ process.env.__NEXT_PRIVATE_RENDER_RUNTIME &&
+ !process.env.TURBOPACK
+) {
+ const currentRuntime = `${
+ process.env.__NEXT_PRIVATE_RENDER_RUNTIME === 'pages'
+ ? 'next/dist/compiled/next-server/pages.runtime'
+ : 'next/dist/compiled/next-server/app-page.runtime'
+ }.prod`
+
+ mod.prototype.require = function (request: string) {
+ if (request.endsWith('.shared-runtime')) {
+ const base = path.basename(request, '.shared-runtime')
+ const camelized = base.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
+ const instance = originalRequire.call(this, currentRuntime)
+ return instance.default.sharedModules[camelized]
+ }
+ return originalRequire.call(this, request)
+ }
+}
diff --git a/packages/next/src/server/response-cache/index.ts b/packages/next/src/server/response-cache/index.ts
index 6d135da26e939..7bd6710cc4a80 100644
--- a/packages/next/src/server/response-cache/index.ts
+++ b/packages/next/src/server/response-cache/index.ts
@@ -20,7 +20,10 @@ export default class ResponseCache {
constructor(minimalMode: boolean) {
this.pendingResponses = new Map()
- this.minimalMode = minimalMode
+ // this is a hack to avoid Webpack knowing this is equal to this.minimalMode
+ // because we replace this.minimalMode to true in production bundles.
+ const minimalModeKey = 'minimalMode'
+ this[minimalModeKey] = minimalMode
}
public get(
diff --git a/packages/next/src/server/response-cache/web.ts b/packages/next/src/server/response-cache/web.ts
index e37ccca314812..f255fdd5412d4 100644
--- a/packages/next/src/server/response-cache/web.ts
+++ b/packages/next/src/server/response-cache/web.ts
@@ -15,7 +15,9 @@ export default class WebResponseCache {
constructor(minimalMode: boolean) {
this.pendingResponses = new Map()
- this.minimalMode = minimalMode
+ // this is a hack to avoid Webpack knowing this is equal to this.minimalMode
+ // because we replace this.minimalMode to true in production bundles.
+ Object.assign(this, { minimalMode })
}
public get(
diff --git a/packages/next/src/server/web/adapter.ts b/packages/next/src/server/web/adapter.ts
index 1ea32a75956cd..5c6ad3e7ed5ab 100644
--- a/packages/next/src/server/web/adapter.ts
+++ b/packages/next/src/server/web/adapter.ts
@@ -18,7 +18,7 @@ import {
import { NEXT_QUERY_PARAM_PREFIX } from '../../lib/constants'
import { ensureInstrumentationRegistered } from './globals'
import { RequestAsyncStorageWrapper } from '../async-storage/request-async-storage-wrapper'
-import { requestAsyncStorage } from '../../client/components/request-async-storage'
+import { requestAsyncStorage } from '../../client/components/request-async-storage.external'
import { PrerenderManifest } from '../../build'
class NextRequestHint extends NextRequest {
diff --git a/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts b/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts
index df3c369eef877..d44ea986cad65 100644
--- a/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts
+++ b/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts
@@ -1,5 +1,5 @@
import type { RequestCookies } from '../cookies'
-import { StaticGenerationStore } from '../../../../client/components/static-generation-async-storage'
+import { StaticGenerationStore } from '../../../../client/components/static-generation-async-storage.external'
import { ResponseCookies } from '../cookies'
import { ReflectAdapter } from './reflect'
diff --git a/packages/next/src/server/web/spec-extension/revalidate-tag.ts b/packages/next/src/server/web/spec-extension/revalidate-tag.ts
index 8d7cd68bd3a9a..7c7bff8c2f784 100644
--- a/packages/next/src/server/web/spec-extension/revalidate-tag.ts
+++ b/packages/next/src/server/web/spec-extension/revalidate-tag.ts
@@ -1,7 +1,7 @@
import {
StaticGenerationAsyncStorage,
StaticGenerationStore,
-} from '../../../client/components/static-generation-async-storage'
+} from '../../../client/components/static-generation-async-storage.external'
export function revalidateTag(tag: string) {
const staticGenerationAsyncStorage = (
diff --git a/packages/next/src/server/web/spec-extension/unstable-cache.ts b/packages/next/src/server/web/spec-extension/unstable-cache.ts
index aad3ed2baf20a..1e85b5c290971 100644
--- a/packages/next/src/server/web/spec-extension/unstable-cache.ts
+++ b/packages/next/src/server/web/spec-extension/unstable-cache.ts
@@ -2,7 +2,7 @@ import {
StaticGenerationStore,
staticGenerationAsyncStorage as _staticGenerationAsyncStorage,
StaticGenerationAsyncStorage,
-} from '../../../client/components/static-generation-async-storage'
+} from '../../../client/components/static-generation-async-storage.external'
import { CACHE_ONE_YEAR } from '../../../lib/constants'
import { addImplicitTags } from '../../lib/patch-fetch'
diff --git a/packages/next/src/shared/lib/amp-context.ts b/packages/next/src/shared/lib/amp-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/amp-context.ts
rename to packages/next/src/shared/lib/amp-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/amp.ts b/packages/next/src/shared/lib/amp.ts
index 04518b2389357..8edd21db9c299 100644
--- a/packages/next/src/shared/lib/amp.ts
+++ b/packages/next/src/shared/lib/amp.ts
@@ -1,5 +1,5 @@
import React from 'react'
-import { AmpStateContext } from './amp-context'
+import { AmpStateContext } from './amp-context.shared-runtime'
import { isInAmpMode } from './amp-mode'
export function useAmp(): boolean {
diff --git a/packages/next/src/shared/lib/app-router-context.ts b/packages/next/src/shared/lib/app-router-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/app-router-context.ts
rename to packages/next/src/shared/lib/app-router-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/dynamic.tsx b/packages/next/src/shared/lib/dynamic.tsx
index cb497fc587d4f..390410edda29e 100644
--- a/packages/next/src/shared/lib/dynamic.tsx
+++ b/packages/next/src/shared/lib/dynamic.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import Loadable from './loadable'
+import Loadable from './loadable.shared-runtime'
const isServerSide = typeof window === 'undefined'
diff --git a/packages/next/src/shared/lib/head-manager-context.ts b/packages/next/src/shared/lib/head-manager-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/head-manager-context.ts
rename to packages/next/src/shared/lib/head-manager-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/head.tsx b/packages/next/src/shared/lib/head.tsx
index 3156e259f656f..42f95767bfa4c 100644
--- a/packages/next/src/shared/lib/head.tsx
+++ b/packages/next/src/shared/lib/head.tsx
@@ -2,8 +2,8 @@
import React, { useContext } from 'react'
import Effect from './side-effect'
-import { AmpStateContext } from './amp-context'
-import { HeadManagerContext } from './head-manager-context'
+import { AmpStateContext } from './amp-context.shared-runtime'
+import { HeadManagerContext } from './head-manager-context.shared-runtime'
import { isInAmpMode } from './amp-mode'
import { warnOnce } from './utils/warn-once'
diff --git a/packages/next/src/shared/lib/hooks-client-context.ts b/packages/next/src/shared/lib/hooks-client-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/hooks-client-context.ts
rename to packages/next/src/shared/lib/hooks-client-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/html-context.ts b/packages/next/src/shared/lib/html-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/html-context.ts
rename to packages/next/src/shared/lib/html-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/image-config-context.ts b/packages/next/src/shared/lib/image-config-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/image-config-context.ts
rename to packages/next/src/shared/lib/image-config-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/loadable-context.ts b/packages/next/src/shared/lib/loadable-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/loadable-context.ts
rename to packages/next/src/shared/lib/loadable-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/loadable.tsx b/packages/next/src/shared/lib/loadable.shared-runtime.tsx
similarity index 99%
rename from packages/next/src/shared/lib/loadable.tsx
rename to packages/next/src/shared/lib/loadable.shared-runtime.tsx
index 1592d98551093..82ba84182701f 100644
--- a/packages/next/src/shared/lib/loadable.tsx
+++ b/packages/next/src/shared/lib/loadable.shared-runtime.tsx
@@ -23,7 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
// Modified to be compatible with webpack 4 / Next.js
import React from 'react'
-import { LoadableContext } from './loadable-context'
+import { LoadableContext } from './loadable-context.shared-runtime'
function resolve(obj: any) {
return obj && obj.default ? obj.default : obj
diff --git a/packages/next/src/shared/lib/router-context.ts b/packages/next/src/shared/lib/router-context.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/router-context.ts
rename to packages/next/src/shared/lib/router-context.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/router/adapters.tsx b/packages/next/src/shared/lib/router/adapters.shared-runtime.tsx
similarity index 95%
rename from packages/next/src/shared/lib/router/adapters.tsx
rename to packages/next/src/shared/lib/router/adapters.shared-runtime.tsx
index ce68a8bec1e8b..29f92dda8dc08 100644
--- a/packages/next/src/shared/lib/router/adapters.tsx
+++ b/packages/next/src/shared/lib/router/adapters.shared-runtime.tsx
@@ -1,7 +1,10 @@
import type { ParsedUrlQuery } from 'node:querystring'
import React, { useMemo, useRef } from 'react'
-import type { AppRouterInstance, NavigateOptions } from '../app-router-context'
-import { PathnameContext } from '../hooks-client-context'
+import type {
+ AppRouterInstance,
+ NavigateOptions,
+} from '../app-router-context.shared-runtime'
+import { PathnameContext } from '../hooks-client-context.shared-runtime'
import type { NextRouter } from './router'
import { isDynamicRoute } from './utils'
diff --git a/packages/next/src/shared/lib/router/adapters.test.tsx b/packages/next/src/shared/lib/router/adapters.test.tsx
index fa8e48f2fc088..e47ce2174dd35 100644
--- a/packages/next/src/shared/lib/router/adapters.test.tsx
+++ b/packages/next/src/shared/lib/router/adapters.test.tsx
@@ -1,4 +1,4 @@
-import { adaptForAppRouterInstance } from './adapters'
+import { adaptForAppRouterInstance } from './adapters.shared-runtime'
import { NextRouter } from './router'
describe('adaptForAppRouterInstance', () => {
diff --git a/packages/next/src/shared/lib/runtime-config.ts b/packages/next/src/shared/lib/runtime-config.shared-runtime.ts
similarity index 100%
rename from packages/next/src/shared/lib/runtime-config.ts
rename to packages/next/src/shared/lib/runtime-config.shared-runtime.ts
diff --git a/packages/next/src/shared/lib/server-inserted-html.tsx b/packages/next/src/shared/lib/server-inserted-html.shared-runtime.tsx
similarity index 100%
rename from packages/next/src/shared/lib/server-inserted-html.tsx
rename to packages/next/src/shared/lib/server-inserted-html.shared-runtime.tsx
diff --git a/packages/next/src/shared/lib/utils.ts b/packages/next/src/shared/lib/utils.ts
index f967be459022b..4e8036a6894a2 100644
--- a/packages/next/src/shared/lib/utils.ts
+++ b/packages/next/src/shared/lib/utils.ts
@@ -1,4 +1,4 @@
-import type { HtmlProps } from './html-context'
+import type { HtmlProps } from './html-context.shared-runtime'
import type { ComponentType } from 'react'
import type { DomainLocale } from '../../server/config'
import type { Env } from '@next/env'
diff --git a/packages/next/src/trace/index.ts b/packages/next/src/trace/index.ts
index e242e19c9041f..e3928f775f613 100644
--- a/packages/next/src/trace/index.ts
+++ b/packages/next/src/trace/index.ts
@@ -1,4 +1,5 @@
import { trace, flushAllTraces, Span, SpanStatus } from './trace'
import { SpanId, setGlobal } from './shared'
-export { trace, flushAllTraces, SpanId, Span, SpanStatus, setGlobal }
+export { trace, flushAllTraces, Span, setGlobal, SpanStatus }
+export type { SpanId }
diff --git a/packages/next/taskfile-webpack.js b/packages/next/taskfile-webpack.js
new file mode 100644
index 0000000000000..04495d7b3621c
--- /dev/null
+++ b/packages/next/taskfile-webpack.js
@@ -0,0 +1,35 @@
+const webpack = require('webpack')
+
+module.exports = function (task) {
+ task.plugin('webpack', {}, function* (_, options) {
+ options = options || {}
+
+ const compiler = webpack(options.config)
+
+ if (options.watch) {
+ compiler.watch({}, (err, stats) => {
+ if (err || stats.hasErrors()) {
+ console.error(err || stats.toString())
+ } else {
+ console.log(`${options.name} compiled successfully.`)
+ }
+ })
+ } else {
+ yield new Promise((resolve, reject) => {
+ compiler.run((err, stats) => {
+ if (err || stats.hasErrors()) {
+ console.error(err || stats.toString())
+ reject(err || stats.toString())
+ }
+ if (process.env.ANALYZE) {
+ require('fs').writeFileSync(
+ require('path').join(__dirname, options.name + '-stats.json'),
+ JSON.stringify(stats.toJson())
+ )
+ }
+ resolve()
+ })
+ })
+ }
+ })
+}
diff --git a/packages/next/taskfile.js b/packages/next/taskfile.js
index f38289c3d4984..321490234153b 100644
--- a/packages/next/taskfile.js
+++ b/packages/next/taskfile.js
@@ -2357,7 +2357,7 @@ export async function ncc(task, opts) {
)
}
-export async function compile(task, opts) {
+export async function next_compile(task, opts) {
await task.parallel(
[
'cli',
@@ -2388,12 +2388,16 @@ export async function compile(task, opts) {
],
opts
)
+}
+
+export async function compile(task, opts) {
+ await task.serial(['next_compile', 'next_bundle'], opts)
+
await task.serial([
'ncc_react_refresh_utils',
'ncc_next__react_dev_overlay',
'ncc_next_font',
'capsize_metrics',
- 'minimal_next_server',
])
}
@@ -2658,157 +2662,38 @@ export async function release(task) {
await task.clear('dist').start('build')
}
-export async function minimal_next_server(task) {
- const outputName = 'next-server.js'
- const cachedOutputName = `${outputName}.cache`
-
- const minimalExternals = [
- 'react',
- 'react/package.json',
- 'react/jsx-runtime',
- 'react/jsx-dev-runtime',
- 'react-dom',
- 'react-dom/package.json',
- 'react-dom/client',
- 'react-dom/server',
- 'react-dom/server.browser',
- 'react-dom/server.edge',
- 'react-server-dom-webpack/client',
- 'react-server-dom-webpack/client.edge',
- 'react-server-dom-webpack/server.edge',
- 'react-server-dom-webpack/server.node',
- 'styled-jsx',
- 'styled-jsx/style',
- '@opentelemetry/api',
- 'next/dist/compiled/@next/react-dev-overlay/dist/middleware',
- 'next/dist/compiled/@ampproject/toolbox-optimizer',
- 'next/dist/compiled/edge-runtime',
- 'next/dist/compiled/@edge-runtime/ponyfill',
- 'next/dist/compiled/undici',
- 'next/dist/compiled/raw-body',
- 'next/dist/server/capsize-font-metrics.json',
- 'critters',
- 'next/dist/compiled/node-html-parser',
- 'next/dist/compiled/compression',
- 'next/dist/compiled/jsonwebtoken',
- 'next/dist/compiled/@mswjs/interceptors/ClientRequest',
- ].reduce((acc, pkg) => {
- acc[pkg] = pkg
- return acc
- }, {})
-
- Object.assign(minimalExternals, {
- '/(.*)config$/': 'next/dist/server/config',
- './web/sandbox': 'next/dist/server/web/sandbox',
+export async function next_bundle_prod(task, opts) {
+ await task.source('dist').webpack({
+ watch: opts.dev,
+ config: require('./webpack.config')({
+ dev: false,
+ }),
+ name: 'next-bundle-prod',
})
+}
- const webpack = require('webpack')
- const TerserPlugin = require('terser-webpack-plugin')
- // const BundleAnalyzerPlugin =
- // require('webpack-bundle-analyzer').BundleAnalyzerPlugin
- /** @type {webpack.Configuration} */
- const config = {
- entry: join(__dirname, 'dist/server/next-server.js'),
- target: 'node',
- mode: 'production',
- output: {
- path: join(__dirname, 'dist/compiled/minimal-next-server'),
- filename: outputName,
- libraryTarget: 'commonjs2',
- },
- // left in for debugging
- optimization: {
- moduleIds: 'named',
- // minimize: false,
- minimize: true,
- minimizer: [
- new TerserPlugin({
- extractComments: false,
- terserOptions: {
- format: {
- comments: false,
- },
- compress: {
- passes: 2,
- },
- },
- }),
- ],
- },
- plugins: [
- new webpack.DefinePlugin({
- 'process.env.NODE_ENV': JSON.stringify('production'),
- 'process.env.NEXT_MINIMAL': JSON.stringify('true'),
- 'process.env.NEXT_RUNTIME': JSON.stringify('nodejs'),
- }),
- // new BundleAnalyzerPlugin({}),
- ],
- externals: [minimalExternals],
- }
-
- await new Promise((resolve, reject) => {
- webpack(config, (err, stats) => {
- if (err) return reject(err)
- if (stats.hasErrors()) {
- return reject(new Error(stats.toString('errors-only')))
- }
- resolve()
- })
+export async function next_bundle_dev(task, opts) {
+ await task.source('dist').webpack({
+ watch: opts.dev,
+ config: require('./webpack.config')({
+ dev: true,
+ }),
+ name: 'next-bundle-dev',
})
+}
- const wrappedTemplate = `
-const filename = ${JSON.stringify(outputName)}
-const { readFileSync } = require('fs'),
- { Script } = require('vm'),
- { wrap } = require('module'),
- { join } = require('path');
-const basename = join(__dirname, filename)
-
-const source = readFileSync(basename, 'utf-8')
-
-const cachedData =
- !process.pkg &&
- require('process').platform !== 'win32' &&
- readFileSync(join(__dirname, '${cachedOutputName}'))
-
-const scriptOpts = { filename: basename, columnOffset: 0 }
-
-const script = new Script(
- wrap(source),
- cachedData ? Object.assign({ cachedData }, scriptOpts) : scriptOpts
-)
-
-script.runInThisContext()(exports, require, module, __filename, __dirname)
-`
-
- await fs.writeFile(
- join(__dirname, `dist/compiled/minimal-next-server/next-server-cached.js`),
- wrappedTemplate
- )
-
- const Module = require('module')
- const vm = require('vm')
- const filename = resolve(
- __dirname,
- 'dist/compiled/minimal-next-server',
- outputName
- )
-
- const content = require('fs').readFileSync(filename, 'utf8')
-
- const wrapper = Module.wrap(content)
- var script = new vm.Script(wrapper, {
- filename: filename,
- lineOffset: 0,
- displayErrors: true,
+export async function next_bundle_turbo_prod(task, opts) {
+ await task.source('dist').webpack({
+ watch: opts.dev,
+ config: require('./webpack.config')({
+ turbo: true,
+ }),
+ name: 'next-bundle-prod-turbo',
})
-
- script.runInThisContext()(exports, require, module, __filename, __dirname)
-
- const buffer = script.createCachedData()
-
- await fs.writeFile(
- join(__dirname, `dist/compiled/minimal-next-server/${cachedOutputName}`),
- buffer
+}
+export async function next_bundle(task, opts) {
+ await task.parallel(
+ ['next_bundle_prod', 'next_bundle_dev', 'next_bundle_turbo_prod'],
+ opts
)
}
diff --git a/packages/next/webpack.config.js b/packages/next/webpack.config.js
new file mode 100644
index 0000000000000..8e7c3063fa5ed
--- /dev/null
+++ b/packages/next/webpack.config.js
@@ -0,0 +1,145 @@
+const webpack = require('webpack')
+const path = require('path')
+const TerserPlugin = require('terser-webpack-plugin')
+const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
+
+const minimalExternals = [
+ 'react',
+ 'react/package.json',
+ 'react/jsx-runtime',
+ 'react/jsx-dev-runtime',
+ 'react-dom',
+ 'react-dom/package.json',
+ 'react-dom/client',
+ 'react-dom/server',
+ 'react-dom/server.browser',
+ 'react-dom/server.edge',
+ 'react-server-dom-webpack/client',
+ 'react-server-dom-webpack/client.edge',
+ 'react-server-dom-webpack/server.edge',
+ 'react-server-dom-webpack/server.node',
+ 'styled-jsx',
+ 'styled-jsx/style',
+ '@opentelemetry/api',
+ 'next/dist/compiled/@next/react-dev-overlay/dist/middleware',
+ 'next/dist/compiled/@ampproject/toolbox-optimizer',
+ 'next/dist/compiled/edge-runtime',
+ 'next/dist/compiled/@edge-runtime/ponyfill',
+ 'next/dist/compiled/undici',
+ 'next/dist/compiled/raw-body',
+ 'next/dist/server/capsize-font-metrics.json',
+ 'critters',
+ 'next/dist/compiled/node-html-parser',
+ 'next/dist/compiled/compression',
+ 'next/dist/compiled/jsonwebtoken',
+ 'next/dist/compiled/@opentelemetry/api',
+ 'next/dist/compiled/@mswjs/interceptors/ClientRequest',
+]
+
+const externalsMap = {
+ './web/sandbox': 'next/dist/server/web/sandbox',
+}
+
+const externalsRegexMap = {
+ '(.*)trace/tracer$': 'next/dist/server/lib/trace/tracer',
+}
+
+module.exports = ({ dev, turbo }) => {
+ const externalHandler = ({ context, request, getResolve }, callback) => {
+ ;(async () => {
+ if (
+ ((dev || turbo) && request.endsWith('.shared-runtime')) ||
+ request.endsWith('.external')
+ ) {
+ const resolve = getResolve()
+ const resolved = await resolve(context, request)
+ const relative = path.relative(
+ path.join(__dirname, '..'),
+ resolved.replace('esm' + path.sep, '')
+ )
+ callback(null, `commonjs ${relative}`)
+ } else {
+ const regexMatch = Object.keys(externalsRegexMap).find((regex) =>
+ new RegExp(regex).test(request)
+ )
+ if (regexMatch) {
+ return callback(null, 'commonjs ' + externalsRegexMap[regexMatch])
+ }
+ callback()
+ }
+ })()
+ }
+
+ /** @type {webpack.Configuration} */
+ return {
+ entry: {
+ server: path.join(__dirname, 'dist/esm/server/next-server.js'),
+ 'app-page': path.join(
+ __dirname,
+ 'dist/esm/server/future/route-modules/app-page/module.js'
+ ),
+ 'app-route': path.join(
+ __dirname,
+ 'dist/esm/server/future/route-modules/app-route/module.js'
+ ),
+ pages: path.join(
+ __dirname,
+ 'dist/esm/server/future/route-modules/pages/module.js'
+ ),
+ 'pages-api': path.join(
+ __dirname,
+ 'dist/esm/server/future/route-modules/pages-api/module.js'
+ ),
+ },
+ target: 'node',
+ mode: 'production',
+ output: {
+ path: path.join(__dirname, 'dist/compiled/next-server'),
+ filename: `[name]${turbo ? '-turbo' : ''}.runtime.${
+ dev ? 'dev' : 'prod'
+ }.js`,
+ libraryTarget: 'commonjs2',
+ },
+ optimization: {
+ moduleIds: 'named',
+ minimize: true,
+ // splitChunks: {
+ // chunks: 'all',
+ // },
+ concatenateModules: true,
+ minimizer: [
+ new TerserPlugin({
+ extractComments: false,
+ terserOptions: {
+ format: {
+ comments: false,
+ },
+ compress: {
+ passes: 2,
+ },
+ },
+ }),
+ ],
+ },
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env.NEXT_MINIMAL': JSON.stringify('true'),
+ 'this.serverOptions.experimentalTestProxy': JSON.stringify(false),
+ 'this.minimalMode': JSON.stringify(true),
+ 'this.renderOpts.dev': JSON.stringify(dev),
+ 'process.env.NODE_ENV': JSON.stringify(
+ dev ? 'development' : 'production'
+ ),
+ 'process.env.NEXT_RUNTIME': JSON.stringify('nodejs'),
+ }),
+ !!process.env.ANALYZE &&
+ new BundleAnalyzerPlugin({
+ analyzerPort: 8888 + (dev ? 0 : 1) + (turbo ? 1 : 0),
+ }),
+ ].filter(Boolean),
+ stats: {
+ optimizationBailout: true,
+ },
+ externals: [...minimalExternals, externalsMap, externalHandler],
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2ce02614924c0..c0bf75436a03f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1381,6 +1381,9 @@ importers:
terser:
specifier: 5.14.1
version: 5.14.1
+ terser-webpack-plugin:
+ specifier: 5.3.9
+ version: 5.3.9(@swc/core@1.3.55)(webpack@5.86.0)
text-table:
specifier: 0.2.0
version: 0.2.0
diff --git a/scripts/minimal-server.js b/scripts/minimal-server.js
index f4f30ac97ce25..08f9125a4f0cc 100644
--- a/scripts/minimal-server.js
+++ b/scripts/minimal-server.js
@@ -1,3 +1,4 @@
+console.time('next-wall-time')
// Usage: node scripts/minimal-server.js
// This script is used to run a minimal Next.js server in production mode.
@@ -44,11 +45,13 @@ if (process.env.LOG_READFILE) {
require('fs').readFile = function (path, options, callback) {
readFileCount++
+ console.log(`readFile: ${path}`)
return originalReadFile.apply(this, arguments)
}
require('fs').readFileSync = function (path, options) {
readFileSyncCount++
+ console.log(`readFileSync: ${path}`)
return originalReadFileSync.apply(this, arguments)
}
}
@@ -56,10 +59,9 @@ if (process.env.LOG_READFILE) {
console.time('next-cold-start')
const NextServer = process.env.USE_BUNDLED_NEXT
- ? require('next/dist/compiled/minimal-next-server/next-server-cached').default
+ ? require('next/dist/compiled/next-server/server.runtime.prod').default
: require('next/dist/server/next-server').default
-console.timeEnd('next-cold-start')
if (process.env.LOG_READFILE) {
console.log(`readFileCount: ${readFileCount + readFileSyncCount}`)
}
@@ -101,9 +103,20 @@ require('http')
if (process.env.LOG_READFILE) {
console.log(`readFileCount: ${readFileCount + readFileSyncCount}`)
}
- require('process').exit(0)
})
})
.listen(3000, () => {
console.timeEnd('next-cold-start')
+ fetch('http://localhost:3000/')
+ .then((res) => res.text())
+ .then((text) => {
+ console.log(text)
+ })
+ .catch((err) => {
+ console.error(err)
+ })
+ .finally(() => {
+ console.timeEnd('next-wall-time')
+ require('process').exit(0)
+ })
})
diff --git a/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts b/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts
index a61e222c3872e..3e5e6b82ea050 100644
--- a/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts
+++ b/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts
@@ -113,7 +113,7 @@ createNextDescribe(
await check(() => {
const fullLog = logs.join('')
- return fullLog.includes('Error: Body exceeded 1.5mb limit') &&
+ return fullLog.includes('[Error]: Body exceeded 1.5mb limit') &&
fullLog.includes(
'To configure the body size limit for Server Actions, see'
)
diff --git a/test/e2e/getserversideprops/app/pages/index.js b/test/e2e/getserversideprops/app/pages/index.js
index 4433c9c2ee84e..da17edc01839d 100644
--- a/test/e2e/getserversideprops/app/pages/index.js
+++ b/test/e2e/getserversideprops/app/pages/index.js
@@ -1,6 +1,6 @@
import Link from 'next/link'
import ReactDOM from 'react-dom/server'
-import { RouterContext } from 'next/dist/shared/lib/router-context'
+import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime'
import { useRouter } from 'next/router'
function RouterComp(props) {
diff --git a/test/e2e/opentelemetry/opentelemetry.test.ts b/test/e2e/opentelemetry/opentelemetry.test.ts
index ae798ec7c5c2d..13e0fefea2787 100644
--- a/test/e2e/opentelemetry/opentelemetry.test.ts
+++ b/test/e2e/opentelemetry/opentelemetry.test.ts
@@ -77,80 +77,80 @@ createNextDescribe(
await check(async () => {
expect(await getSanitizedTraces(1)).toMatchInlineSnapshot(`
- Array [
- Object {
- "attributes": Object {
- "http.method": "GET",
- "http.url": "https://vercel.com/",
- "net.peer.name": "vercel.com",
- "next.span_name": "fetch GET https://vercel.com/",
- "next.span_type": "AppRender.fetch",
- },
- "kind": 2,
- "name": "fetch GET https://vercel.com/",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.route": "/app/[param]/rsc-fetch",
- "next.span_name": "render route (app) /app/[param]/rsc-fetch",
- "next.span_type": "AppRender.getBodyResult",
- },
- "kind": 0,
- "name": "render route (app) /app/[param]/rsc-fetch",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "http.method": "GET",
- "http.route": "/app/[param]/rsc-fetch",
- "http.status_code": 200,
- "http.target": "/app/param/rsc-fetch",
- "next.route": "/app/[param]/rsc-fetch",
- "next.span_name": "GET /app/[param]/rsc-fetch",
- "next.span_type": "BaseServer.handleRequest",
- },
- "kind": 1,
- "name": "GET /app/[param]/rsc-fetch",
- "parentId": undefined,
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.page": "/app/[param]/layout",
- "next.span_name": "generateMetadata /app/[param]/layout",
- "next.span_type": "ResolveMetadata.generateMetadata",
- },
- "kind": 0,
- "name": "generateMetadata /app/[param]/layout",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.page": "/app/[param]/rsc-fetch/page",
- "next.span_name": "generateMetadata /app/[param]/rsc-fetch/page",
- "next.span_type": "ResolveMetadata.generateMetadata",
- },
- "kind": 0,
- "name": "generateMetadata /app/[param]/rsc-fetch/page",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- ]
- `)
+ Array [
+ Object {
+ "attributes": Object {
+ "http.method": "GET",
+ "http.url": "https://vercel.com/",
+ "net.peer.name": "vercel.com",
+ "next.span_name": "fetch GET https://vercel.com/",
+ "next.span_type": "AppRender.fetch",
+ },
+ "kind": 2,
+ "name": "fetch GET https://vercel.com/",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.route": "/app/[param]/rsc-fetch",
+ "next.span_name": "render route (app) /app/[param]/rsc-fetch",
+ "next.span_type": "AppRender.getBodyResult",
+ },
+ "kind": 0,
+ "name": "render route (app) /app/[param]/rsc-fetch",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "http.method": "GET",
+ "http.route": "/app/[param]/rsc-fetch",
+ "http.status_code": 200,
+ "http.target": "/app/param/rsc-fetch",
+ "next.route": "/app/[param]/rsc-fetch",
+ "next.span_name": "GET /app/[param]/rsc-fetch",
+ "next.span_type": "BaseServer.handleRequest",
+ },
+ "kind": 1,
+ "name": "GET /app/[param]/rsc-fetch",
+ "parentId": undefined,
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.page": "/app/[param]/layout",
+ "next.span_name": "generateMetadata /app/[param]/layout",
+ "next.span_type": "ResolveMetadata.generateMetadata",
+ },
+ "kind": 0,
+ "name": "generateMetadata /app/[param]/layout",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.page": "/app/[param]/rsc-fetch/page",
+ "next.span_name": "generateMetadata /app/[param]/rsc-fetch/page",
+ "next.span_type": "ResolveMetadata.generateMetadata",
+ },
+ "kind": 0,
+ "name": "generateMetadata /app/[param]/rsc-fetch/page",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ ]
+ `)
return 'success'
}, 'success')
})
@@ -160,37 +160,39 @@ createNextDescribe(
await check(async () => {
expect(await getSanitizedTraces(1)).toMatchInlineSnapshot(`
- Array [
- Object {
- "attributes": Object {
- "next.route": "/api/app/[param]/data/route",
- "next.span_name": "executing api route (app) /api/app/[param]/data/route",
- "next.span_type": "AppRouteRouteHandlers.runHandler",
- },
- "kind": 0,
- "name": "executing api route (app) /api/app/[param]/data/route",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
+ Array [
+ Object {
+ "attributes": Object {
+ "next.route": "/api/app/[param]/data/route",
+ "next.span_name": "executing api route (app) /api/app/[param]/data/route",
+ "next.span_type": "AppRouteRouteHandlers.runHandler",
+ },
+ "kind": 0,
+ "name": "executing api route (app) /api/app/[param]/data/route",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
},
- },
- Object {
- "attributes": Object {
- "http.method": "GET",
- "http.status_code": 200,
- "http.target": "/api/app/param/data",
- "next.span_name": "GET /api/app/param/data",
- "next.span_type": "BaseServer.handleRequest",
+ Object {
+ "attributes": Object {
+ "http.method": "GET",
+ "http.route": "/api/app/[param]/data/route",
+ "http.status_code": 200,
+ "http.target": "/api/app/param/data",
+ "next.route": "/api/app/[param]/data/route",
+ "next.span_name": "GET /api/app/[param]/data/route",
+ "next.span_type": "BaseServer.handleRequest",
+ },
+ "kind": 1,
+ "name": "GET /api/app/[param]/data/route",
+ "parentId": undefined,
+ "status": Object {
+ "code": 0,
+ },
},
- "kind": 1,
- "name": "GET /api/app/param/data",
- "parentId": undefined,
- "status": Object {
- "code": 0,
- },
- },
- ]
- `)
+ ]
+ `)
return 'success'
}, 'success')
})
@@ -202,52 +204,52 @@ createNextDescribe(
await check(async () => {
expect(await getSanitizedTraces(1)).toMatchInlineSnapshot(`
- Array [
- Object {
- "attributes": Object {
- "http.method": "GET",
- "http.route": "/pages/[param]/getServerSideProps",
- "http.status_code": 200,
- "http.target": "/pages/param/getServerSideProps",
- "next.route": "/pages/[param]/getServerSideProps",
- "next.span_name": "GET /pages/[param]/getServerSideProps",
- "next.span_type": "BaseServer.handleRequest",
- },
- "kind": 1,
- "name": "GET /pages/[param]/getServerSideProps",
- "parentId": undefined,
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.route": "/pages/[param]/getServerSideProps",
- "next.span_name": "getServerSideProps /pages/[param]/getServerSideProps",
- "next.span_type": "Render.getServerSideProps",
- },
- "kind": 0,
- "name": "getServerSideProps /pages/[param]/getServerSideProps",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.route": "/pages/[param]/getServerSideProps",
- "next.span_name": "render route (pages) /pages/[param]/getServerSideProps",
- "next.span_type": "Render.renderDocument",
- },
- "kind": 0,
- "name": "render route (pages) /pages/[param]/getServerSideProps",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- ]
- `)
+ Array [
+ Object {
+ "attributes": Object {
+ "http.method": "GET",
+ "http.route": "/pages/[param]/getServerSideProps",
+ "http.status_code": 200,
+ "http.target": "/pages/param/getServerSideProps",
+ "next.route": "/pages/[param]/getServerSideProps",
+ "next.span_name": "GET /pages/[param]/getServerSideProps",
+ "next.span_type": "BaseServer.handleRequest",
+ },
+ "kind": 1,
+ "name": "GET /pages/[param]/getServerSideProps",
+ "parentId": undefined,
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.route": "/pages/[param]/getServerSideProps",
+ "next.span_name": "getServerSideProps /pages/[param]/getServerSideProps",
+ "next.span_type": "Render.getServerSideProps",
+ },
+ "kind": 0,
+ "name": "getServerSideProps /pages/[param]/getServerSideProps",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.route": "/pages/[param]/getServerSideProps",
+ "next.span_name": "render route (pages) /pages/[param]/getServerSideProps",
+ "next.span_type": "Render.renderDocument",
+ },
+ "kind": 0,
+ "name": "render route (pages) /pages/[param]/getServerSideProps",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ ]
+ `)
return 'success'
}, 'success')
})
@@ -257,52 +259,52 @@ createNextDescribe(
await check(async () => {
expect(await getSanitizedTraces(1)).toMatchInlineSnapshot(`
- Array [
- Object {
- "attributes": Object {
- "http.method": "GET",
- "http.route": "/pages/[param]/getStaticProps",
- "http.status_code": 200,
- "http.target": "/pages/param/getStaticProps",
- "next.route": "/pages/[param]/getStaticProps",
- "next.span_name": "GET /pages/[param]/getStaticProps",
- "next.span_type": "BaseServer.handleRequest",
- },
- "kind": 1,
- "name": "GET /pages/[param]/getStaticProps",
- "parentId": undefined,
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.route": "/pages/[param]/getStaticProps",
- "next.span_name": "getStaticProps /pages/[param]/getStaticProps",
- "next.span_type": "Render.getStaticProps",
- },
- "kind": 0,
- "name": "getStaticProps /pages/[param]/getStaticProps",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.route": "/pages/[param]/getStaticProps",
- "next.span_name": "render route (pages) /pages/[param]/getStaticProps",
- "next.span_type": "Render.renderDocument",
- },
- "kind": 0,
- "name": "render route (pages) /pages/[param]/getStaticProps",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- ]
- `)
+ Array [
+ Object {
+ "attributes": Object {
+ "http.method": "GET",
+ "http.route": "/pages/[param]/getStaticProps",
+ "http.status_code": 200,
+ "http.target": "/pages/param/getStaticProps",
+ "next.route": "/pages/[param]/getStaticProps",
+ "next.span_name": "GET /pages/[param]/getStaticProps",
+ "next.span_type": "BaseServer.handleRequest",
+ },
+ "kind": 1,
+ "name": "GET /pages/[param]/getStaticProps",
+ "parentId": undefined,
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.route": "/pages/[param]/getStaticProps",
+ "next.span_name": "getStaticProps /pages/[param]/getStaticProps",
+ "next.span_type": "Render.getStaticProps",
+ },
+ "kind": 0,
+ "name": "getStaticProps /pages/[param]/getStaticProps",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.route": "/pages/[param]/getStaticProps",
+ "next.span_name": "render route (pages) /pages/[param]/getStaticProps",
+ "next.span_type": "Render.renderDocument",
+ },
+ "kind": 0,
+ "name": "render route (pages) /pages/[param]/getStaticProps",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ ]
+ `)
return 'success'
}, 'success')
})
@@ -312,38 +314,38 @@ createNextDescribe(
await check(async () => {
expect(await getSanitizedTraces(1)).toMatchInlineSnapshot(`
- Array [
- Object {
- "attributes": Object {
- "http.method": "GET",
- "http.route": "/api/pages/[param]/basic",
- "http.status_code": 200,
- "http.target": "/api/pages/param/basic",
- "next.route": "/api/pages/[param]/basic",
- "next.span_name": "GET /api/pages/[param]/basic",
- "next.span_type": "BaseServer.handleRequest",
- },
- "kind": 1,
- "name": "GET /api/pages/[param]/basic",
- "parentId": undefined,
- "status": Object {
- "code": 0,
- },
- },
- Object {
- "attributes": Object {
- "next.span_name": "executing api route (pages) /api/pages/[param]/basic",
- "next.span_type": "Node.runHandler",
- },
- "kind": 0,
- "name": "executing api route (pages) /api/pages/[param]/basic",
- "parentId": "[parent-id]",
- "status": Object {
- "code": 0,
- },
- },
- ]
- `)
+ Array [
+ Object {
+ "attributes": Object {
+ "http.method": "GET",
+ "http.route": "/api/pages/[param]/basic",
+ "http.status_code": 200,
+ "http.target": "/api/pages/param/basic",
+ "next.route": "/api/pages/[param]/basic",
+ "next.span_name": "GET /api/pages/[param]/basic",
+ "next.span_type": "BaseServer.handleRequest",
+ },
+ "kind": 1,
+ "name": "GET /api/pages/[param]/basic",
+ "parentId": undefined,
+ "status": Object {
+ "code": 0,
+ },
+ },
+ Object {
+ "attributes": Object {
+ "next.span_name": "executing api route (pages) /api/pages/[param]/basic",
+ "next.span_type": "Node.runHandler",
+ },
+ "kind": 0,
+ "name": "executing api route (pages) /api/pages/[param]/basic",
+ "parentId": "[parent-id]",
+ "status": Object {
+ "code": 0,
+ },
+ },
+ ]
+ `)
return 'success'
}, 'success')
})
diff --git a/test/e2e/prerender-native-module.test.ts b/test/e2e/prerender-native-module.test.ts
index c23b1d2d05cd0..34adb36ce5bd8 100644
--- a/test/e2e/prerender-native-module.test.ts
+++ b/test/e2e/prerender-native-module.test.ts
@@ -85,8 +85,6 @@ describe('prerender native module', () => {
/node_modules\/sqlite3\/.*?\.node/,
/node_modules\/sqlite\/.*?\.js/,
/node_modules\/next/,
- /next\/router\.js/,
- /next\/dist\/client\/router\.js/,
/\/data\.sqlite/,
],
notTests: [],
@@ -99,7 +97,6 @@ describe('prerender native module', () => {
)
const { version, files } = JSON.parse(contents)
expect(version).toBe(1)
-
expect(
check.tests.every((item) => files.some((file) => item.test(file)))
).toBe(true)
diff --git a/test/e2e/prerender.test.ts b/test/e2e/prerender.test.ts
index f21b4224fe236..1ff677e583b15 100644
--- a/test/e2e/prerender.test.ts
+++ b/test/e2e/prerender.test.ts
@@ -2070,7 +2070,6 @@ describe('Prerender', () => {
/node_modules\/react\/index\.js/,
/node_modules\/react\/package\.json/,
/node_modules\/react\/cjs\/react\.production\.min\.js/,
- /node_modules\/next/,
],
notTests: [],
},
@@ -2082,7 +2081,6 @@ describe('Prerender', () => {
/node_modules\/react\/index\.js/,
/node_modules\/react\/package\.json/,
/node_modules\/react\/cjs\/react\.production\.min\.js/,
- /node_modules\/next/,
/\/world.txt/,
],
notTests: [
@@ -2098,9 +2096,6 @@ describe('Prerender', () => {
/node_modules\/react\/index\.js/,
/node_modules\/react\/package\.json/,
/node_modules\/react\/cjs\/react\.production\.min\.js/,
- /node_modules\/next/,
- /next\/router\.js/,
- /next\/dist\/client\/router\.js/,
/node_modules\/@firebase\/firestore\/.*?\.js/,
],
notTests: [/\/world.txt/],
diff --git a/test/integration/externalize-next-server/app/node_modules/comps/index.js b/test/integration/externalize-next-server/app/node_modules/comps/index.js
deleted file mode 100644
index 74c3153f1b835..0000000000000
--- a/test/integration/externalize-next-server/app/node_modules/comps/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const react = require('react')
-
-module.exports = function() {
- return react.createElement('p', null, 'MyComp:', typeof window)
-}
diff --git a/test/integration/externalize-next-server/app/node_modules/comps/package.json b/test/integration/externalize-next-server/app/node_modules/comps/package.json
deleted file mode 100644
index 6e665b646a6ad..0000000000000
--- a/test/integration/externalize-next-server/app/node_modules/comps/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "comps",
- "version": "1.0.0",
- "main": "index.js",
- "license": "MIT"
-}
diff --git a/test/integration/externalize-next-server/app/package.json b/test/integration/externalize-next-server/app/package.json
deleted file mode 100644
index c5bd706a3a950..0000000000000
--- a/test/integration/externalize-next-server/app/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "externalize-next-server-app",
- "version": "1.0.0",
- "main": "index.js",
- "license": "MIT"
-}
diff --git a/test/integration/externalize-next-server/app/pages/index.js b/test/integration/externalize-next-server/app/pages/index.js
deleted file mode 100644
index 9ceb7bee3db17..0000000000000
--- a/test/integration/externalize-next-server/app/pages/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import MyComp from 'comps'
-
-const Page = () => (
- <>
- Hello {typeof window}
-
- >
-)
-
-Page.getInitialProps = () => ({})
-
-export default Page
diff --git a/test/integration/externalize-next-server/test/index.test.js b/test/integration/externalize-next-server/test/index.test.js
deleted file mode 100644
index bba968de16585..0000000000000
--- a/test/integration/externalize-next-server/test/index.test.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* eslint-env jest */
-import path from 'path'
-import { nextBuild, readNextBuildServerPageFile } from 'next-test-utils'
-
-const appDir = path.join(__dirname, '../app')
-
-describe('externalize next/dist/shared', () => {
- beforeAll(async () => {
- await nextBuild(appDir)
- })
-
- it('Bundle next/dist/shared/lib/head.js but not next/dist/shared/lib/head-manager-context.js in _error', async () => {
- const content = readNextBuildServerPageFile(appDir, '/_error')
- expect(content).toContain(
- `require("next/dist/shared/lib/head-manager-context.js")`
- )
- expect(content).not.toContain(`require("next/dist/shared/lib/head.js")`)
- })
-})
diff --git a/test/integration/jsconfig-baseurl/test/index.test.js b/test/integration/jsconfig-baseurl/test/index.test.js
index 91f084ce1d55e..4ad014d0e8f03 100644
--- a/test/integration/jsconfig-baseurl/test/index.test.js
+++ b/test/integration/jsconfig-baseurl/test/index.test.js
@@ -72,12 +72,6 @@ describe('TypeScript Features', () => {
const helloTrace = await fs.readJSON(
join(appDir, '.next/server/pages/hello.js.nft.json')
)
- const appTrace = await fs.readJSON(
- join(appDir, '.next/server/pages/_app.js.nft.json')
- )
- expect(
- appTrace.files.some((file) => file.includes('node_modules/next'))
- ).toBe(true)
expect(
helloTrace.files.some((file) => file.includes('components/world.js'))
).toBe(false)
diff --git a/test/integration/jsconfig-paths/test/index.test.js b/test/integration/jsconfig-paths/test/index.test.js
index 77c84e7edfbb4..bc3c635b9ce96 100644
--- a/test/integration/jsconfig-paths/test/index.test.js
+++ b/test/integration/jsconfig-paths/test/index.test.js
@@ -89,9 +89,6 @@ function runTests() {
await nextBuild(appDir)
})
it('should trace correctly', async () => {
- const appTrace = await fs.readJSON(
- join(appDir, '.next/server/pages/_app.js.nft.json')
- )
const singleAliasTrace = await fs.readJSON(
join(appDir, '.next/server/pages/single-alias.js.nft.json')
)
@@ -107,9 +104,7 @@ function runTests() {
const basicAliasTrace = await fs.readJSON(
join(appDir, '.next/server/pages/basic-alias.js.nft.json')
)
- expect(
- appTrace.files.some((file) => file.includes('node_modules/next'))
- ).toBe(true)
+
expect(
singleAliasTrace.files.some((file) =>
file.includes('components/hello.js')