diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index a393832b857be..a0569b6d7c19c 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -36,3 +36,5 @@ Cargo.toml @timneutkens @ijjk @shu
Cargo.lock @timneutkens @ijjk @shuding @huozhi @vercel/web-tooling
/.cargo/config.toml @timneutkens @ijjk @shuding @huozhi @vercel/web-tooling
/.config/nextest.toml @timneutkens @ijjk @shuding @huozhi @vercel/web-tooling
+/test/build-turbopack-tests-manifest.js @timneutkens @ijjk @shuding @huozhi @vercel/web-tooling
+/test/turbopack-tests-manifest.json @timneutkens @ijjk @shuding @huozhi @vercel/web-tooling
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3b28ea4bab515..c2892a71599f5 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -21,8 +21,6 @@
// Debugging.
"debug.javascript.unmapMissingSources": true,
"files.exclude": {
- "**/node_modules": false,
- "node_modules": true,
"*[!test]**/node_modules": true
},
// Ensure enough terminal history is preserved when running tests.
diff --git a/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx b/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx
index d2a419db65b1b..fd1ff7ab33de8 100644
--- a/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx
+++ b/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx
@@ -16,7 +16,7 @@ description: API Reference for the revalidatePath function.
revalidatePath(path: string, type?: 'page' | 'layout'): void;
```
-- `path`: A string representing the filesystem path associated with the data you want to revalidate. This is the literal route segment (for example, `/product/123`) not the path on the filesystem `/product/[slug]/page`. Must be less than 1024 characters.
+- `path`: Either a string representing the filesystem path associated with the data you want to revalidate (for example, `/product/[slug]/page`), or the literal route segment (for example, `/product/123`). Must be less than 1024 characters.
- `type`: (optional) `'page'` or `'layout'` string to change the type of path to revalidate.
## Returns
diff --git a/examples/with-supabase/README.md b/examples/with-supabase/README.md
index 84194136a3a6e..8a4b42d302f82 100644
--- a/examples/with-supabase/README.md
+++ b/examples/with-supabase/README.md
@@ -1,24 +1,91 @@
-# Supabase Starter
+
+
+
+
-This starter configures Supabase Auth to use cookies, making the user's session available throughout the entire Next.js app - Client Components, Server Components, Route Handlers, Server Actions and Middleware.
+
+ This starter configures Supabase Auth to use cookies, making the user's session available throughout the entire Next.js app - Client Components, Server Components, Route Handlers, Server Actions and Middleware.
+
+
-The Vercel deployment will guide you through creating a Supabase account and project. After installation of the Supabase integration, all relevant environment variables will be set up so that the project is usable immediately after deployment 🚀
+## Features
-[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&integration-ids=oac_jUduyjQgOyzev1fjrW83NYOv)
+- [Next.js App router ready](https://nextjs.org) App Router
+ - Client Components examples
+ - React Server Components (RSCs) examples
+ - Route Handlers examples
+ - Server Actions examples
+- [supabase-js](https://supabase.com/docs/reference/javascript). Supabase's
+ isomorphic JavaScript library.
+- [Supabase Auth](https://supabase.com/auth) using cookies, making the user's session available throughout the entire Next.js app, for both client and server.
+- Styling with [Tailwind CSS](https://tailwindcss.com)
+- Optional deployment with [Supabase Vercel Integration and Vercel deploy](#deploy-your-own)
+ - Enviroment variables automatically assigned to Vercel project
-## How to use
+## Demo
+
+You can view a fully working demo at [demo-nextjs-with-supabase.com](https://demo-nextjs-with-supabase.com).
+
+## Deploy to Vercel
+
+Vercel deployment will guide you through creating a Supabase account and project.
+
+After installation of the Supabase integration, all relevant environment variables will be assigned to the project so the deployment is fully functioning.
+
+[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&demo-title=nextjs-with-supabase&demo-description=This%20starter%20configures%20Supabase%20Auth%20to%20use%20cookies%2C%20making%20the%20user's%20session%20available%20throughout%20the%20entire%20Next.js%20app%20-%20Client%20Components%2C%20Server%20Components%2C%20Route%20Handlers%2C%20Server%20Actions%20and%20Middleware.&demo-url=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2F&external-id=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&demo-image=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2Fopengraph-image.png&integration-ids=oac_VqOgBHqhEoFTPzGkPd7L0iH6)
+
+The above will also clone the Starter kit to your GitHub, you can clone that locally and develop locally.
+
+If you wish to just develop locally and not deploy to Vercel, [follow the steps below](#how-to-use).
+
+## Clone and run locally
+
+1. You'll first need a Supabase project which can be made [via the Supabase dashboard](https://database.new)
+
+2. Create a Next.js app using the Supabase Starter template npx command
-1. Create a [new Supabase project](https://database.new)
-1. Run `npx create-next-app -e with-supabase` to create a Next.js app using the Supabase Starter template
-1. Use `cd` to change into the app's directory
-1. Run `npm install` to install dependencies
-1. Rename `.env.local.example` to `.env.local` and update the values for `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` from [your Supabase project's API settings](https://app.supabase.com/project/_/settings/api)
-1. Run `npm run dev` to start the local development server
+ ```bash
+ npx create-next-app -e with-supabase
+ ```
+
+3. Use `cd` to change into the app's directory
+
+ ```bash
+ cd name-of-new-app
+ ```
+
+4. Rename `.env.local.example` to `.env.local` and update the following:
+
+ ```
+ NEXT_PUBLIC_SUPABASE_URL=[INSERT SUPABASE PROJECT URL]
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=[INSERT SUPABASE PROJECT API ANON KEY]
+ ```
+
+ Both `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` can be found in [your Supabase project's API settings](https://app.supabase.com/project/_/settings/api)
+
+5. You can now run the Next.js local development server:
+
+ ```bash
+ npm run dev
+ ```
+
+ The starter kit should now be running on [localhost:3000](http://localhost:3000/).
> Check out [the docs for Local Development](https://supabase.com/docs/guides/getting-started/local-development) to also run Supabase locally.
+## How to use
+
+There are a variety of example files for you to copy and build your app with in the starter kit.
+
### Create a Supabase client
Check out the [`/app/_examples`](./app/_examples/) folder for an example of creating a Supabase client in:
diff --git a/examples/with-supabase/app/opengraph-image.png b/examples/with-supabase/app/opengraph-image.png
new file mode 100644
index 0000000000000..57595e662c3b5
Binary files /dev/null and b/examples/with-supabase/app/opengraph-image.png differ
diff --git a/examples/with-supabase/app/page.tsx b/examples/with-supabase/app/page.tsx
index d8ba2eed6211b..001442668bec1 100644
--- a/examples/with-supabase/app/page.tsx
+++ b/examples/with-supabase/app/page.tsx
@@ -4,6 +4,7 @@ import Link from 'next/link'
import LogoutButton from '../components/LogoutButton'
import SupabaseLogo from '../components/SupabaseLogo'
import NextJsLogo from '../components/NextJsLogo'
+import DeployButton from '../components/DeployButton'
export const dynamic = 'force-dynamic'
@@ -49,22 +50,20 @@ export default async function Index() {
diff --git a/examples/with-supabase/components/DeployButton.tsx b/examples/with-supabase/components/DeployButton.tsx
new file mode 100644
index 0000000000000..6e0b7d80f4399
--- /dev/null
+++ b/examples/with-supabase/components/DeployButton.tsx
@@ -0,0 +1,25 @@
+'use client'
+
+export default function DeployButton() {
+ return (
+
+
+ Deploy to Vercel
+
+ )
+}
diff --git a/packages/font/src/google/font-data.json b/packages/font/src/google/font-data.json
index e9bb2a4221bbd..7d9e4378c4339 100644
--- a/packages/font/src/google/font-data.json
+++ b/packages/font/src/google/font-data.json
@@ -9,6 +9,25 @@
"styles": ["normal"],
"subsets": ["adlam", "latin", "latin-ext"]
},
+ "AR One Sans": {
+ "weights": ["400", "500", "600", "700", "variable"],
+ "styles": ["normal"],
+ "axes": [
+ {
+ "tag": "ARRR",
+ "min": 10,
+ "max": 60,
+ "defaultValue": 10
+ },
+ {
+ "tag": "wght",
+ "min": 400,
+ "max": 700,
+ "defaultValue": 400
+ }
+ ],
+ "subsets": ["latin", "latin-ext", "vietnamese"]
+ },
"Abel": {
"weights": ["400"],
"styles": ["normal"],
@@ -3853,6 +3872,19 @@
"styles": ["normal", "italic"],
"subsets": ["greek"]
},
+ "Gabarito": {
+ "weights": ["400", "500", "600", "700", "800", "900", "variable"],
+ "styles": ["normal"],
+ "axes": [
+ {
+ "tag": "wght",
+ "min": 400,
+ "max": 900,
+ "defaultValue": 400
+ }
+ ],
+ "subsets": ["latin", "latin-ext"]
+ },
"Gabriela": {
"weights": ["400"],
"styles": ["normal"],
@@ -5260,9 +5292,17 @@
"subsets": ["devanagari", "latin", "latin-ext"]
},
"Kameron": {
- "weights": ["400", "700"],
+ "weights": ["400", "500", "600", "700", "variable"],
"styles": ["normal"],
- "subsets": ["latin"]
+ "axes": [
+ {
+ "tag": "wght",
+ "min": 400,
+ "max": 700,
+ "defaultValue": 400
+ }
+ ],
+ "subsets": ["latin", "latin-ext"]
},
"Kanit": {
"weights": ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
@@ -7421,7 +7461,7 @@
"Noto Sans Bhaiksuki": {
"weights": ["400"],
"styles": ["normal"],
- "subsets": ["bhaiksuki"]
+ "subsets": ["bhaiksuki", "latin", "latin-ext"]
},
"Noto Sans Brahmi": {
"weights": ["400"],
@@ -7749,9 +7789,17 @@
"subsets": ["gujarati", "latin", "latin-ext"]
},
"Noto Sans Gunjala Gondi": {
- "weights": ["400"],
+ "weights": ["400", "500", "600", "700", "variable"],
"styles": ["normal"],
- "subsets": ["gunjala-gondi"]
+ "axes": [
+ {
+ "tag": "wght",
+ "min": 400,
+ "max": 700,
+ "defaultValue": 400
+ }
+ ],
+ "subsets": ["gunjala-gondi", "latin", "latin-ext"]
},
"Noto Sans Gurmukhi": {
"weights": [
@@ -8322,6 +8370,19 @@
"styles": ["normal"],
"subsets": ["latin", "latin-ext", "nko"]
},
+ "Noto Sans NKo Unjoined": {
+ "weights": ["400", "500", "600", "700", "variable"],
+ "styles": ["normal"],
+ "axes": [
+ {
+ "tag": "wght",
+ "min": 400,
+ "max": 700,
+ "defaultValue": 400
+ }
+ ],
+ "subsets": ["latin", "latin-ext", "nko"]
+ },
"Noto Sans Nabataean": {
"weights": ["400"],
"styles": ["normal"],
@@ -8658,7 +8719,7 @@
"Noto Sans Symbols 2": {
"weights": ["400"],
"styles": ["normal"],
- "subsets": ["latin", "latin-ext", "symbols"]
+ "subsets": ["braille", "latin", "latin-ext", "mayan-numerals", "symbols"]
},
"Noto Sans Syriac": {
"weights": [
@@ -9858,6 +9919,30 @@
"styles": ["normal"],
"subsets": ["latin", "latin-ext"]
},
+ "Onest": {
+ "weights": [
+ "100",
+ "200",
+ "300",
+ "400",
+ "500",
+ "600",
+ "700",
+ "800",
+ "900",
+ "variable"
+ ],
+ "styles": ["normal"],
+ "axes": [
+ {
+ "tag": "wght",
+ "min": 100,
+ "max": 900,
+ "defaultValue": 400
+ }
+ ],
+ "subsets": ["cyrillic", "cyrillic-ext", "latin", "latin-ext"]
+ },
"Oooh Baby": {
"weights": ["400"],
"styles": ["normal"],
@@ -10332,6 +10417,19 @@
"styles": ["normal"],
"subsets": ["latin", "latin-ext"]
},
+ "Pixelify Sans": {
+ "weights": ["400", "500", "600", "700", "variable"],
+ "styles": ["normal"],
+ "axes": [
+ {
+ "tag": "wght",
+ "min": 400,
+ "max": 700,
+ "defaultValue": 400
+ }
+ ],
+ "subsets": ["cyrillic", "latin", "latin-ext"]
+ },
"Plaster": {
"weights": ["400"],
"styles": ["normal"],
@@ -13465,6 +13563,11 @@
"styles": ["normal"],
"subsets": ["cyrillic", "latin", "latin-ext", "vietnamese"]
},
+ "Young Serif": {
+ "weights": ["400"],
+ "styles": ["normal"],
+ "subsets": ["latin", "latin-ext"]
+ },
"Yrsa": {
"weights": ["300", "400", "500", "600", "700", "variable"],
"styles": ["normal", "italic"],
diff --git a/packages/font/src/google/index.ts b/packages/font/src/google/index.ts
index e7de16d88d231..ac1987902e635 100644
--- a/packages/font/src/google/index.ts
+++ b/packages/font/src/google/index.ts
@@ -31,6 +31,25 @@ export declare function ADLaM_Display<
adjustFontFallback?: boolean
subsets?: Array<'adlam' | 'latin' | 'latin-ext'>
}): T extends undefined ? NextFont : NextFontWithVariable
+export declare function AR_One_Sans<
+ T extends CssVariable | undefined = undefined
+>(options?: {
+ weight?:
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | 'variable'
+ | Array<'400' | '500' | '600' | '700'>
+ style?: 'normal' | Array<'normal'>
+ display?: Display
+ variable?: T
+ preload?: boolean
+ fallback?: string[]
+ adjustFontFallback?: boolean
+ subsets?: Array<'latin' | 'latin-ext' | 'vietnamese'>
+ axes?: 'ARRR'[]
+}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Abel<
T extends CssVariable | undefined = undefined
>(options: {
@@ -6886,6 +6905,26 @@ export declare function GFS_Neohellenic<
adjustFontFallback?: boolean
subsets?: Array<'greek'>
}): T extends undefined ? NextFont : NextFontWithVariable
+export declare function Gabarito<
+ T extends CssVariable | undefined = undefined
+>(options?: {
+ weight?:
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | '800'
+ | '900'
+ | 'variable'
+ | Array<'400' | '500' | '600' | '700' | '800' | '900'>
+ style?: 'normal' | Array<'normal'>
+ display?: Display
+ variable?: T
+ preload?: boolean
+ fallback?: string[]
+ adjustFontFallback?: boolean
+ subsets?: Array<'latin' | 'latin-ext'>
+}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Gabriela<
T extends CssVariable | undefined = undefined
>(options: {
@@ -9461,15 +9500,21 @@ export declare function Kalam<
}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Kameron<
T extends CssVariable | undefined = undefined
->(options: {
- weight: '400' | '700' | Array<'400' | '700'>
+>(options?: {
+ weight?:
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | 'variable'
+ | Array<'400' | '500' | '600' | '700'>
style?: 'normal' | Array<'normal'>
display?: Display
variable?: T
preload?: boolean
fallback?: string[]
adjustFontFallback?: boolean
- subsets?: Array<'latin'>
+ subsets?: Array<'latin' | 'latin-ext'>
}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Kanit<
T extends CssVariable | undefined = undefined
@@ -13481,7 +13526,7 @@ export declare function Noto_Sans_Bhaiksuki<
preload?: boolean
fallback?: string[]
adjustFontFallback?: boolean
- subsets?: Array<'bhaiksuki'>
+ subsets?: Array<'bhaiksuki' | 'latin' | 'latin-ext'>
}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Noto_Sans_Brahmi<
T extends CssVariable | undefined = undefined
@@ -13926,15 +13971,21 @@ export declare function Noto_Sans_Gujarati<
}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Noto_Sans_Gunjala_Gondi<
T extends CssVariable | undefined = undefined
->(options: {
- weight: '400' | Array<'400'>
+>(options?: {
+ weight?:
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | 'variable'
+ | Array<'400' | '500' | '600' | '700'>
style?: 'normal' | Array<'normal'>
display?: Display
variable?: T
preload?: boolean
fallback?: string[]
adjustFontFallback?: boolean
- subsets?: Array<'gunjala-gondi'>
+ subsets?: Array<'gunjala-gondi' | 'latin' | 'latin-ext'>
}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Noto_Sans_Gurmukhi<
T extends CssVariable | undefined = undefined
@@ -14738,6 +14789,24 @@ export declare function Noto_Sans_NKo<
adjustFontFallback?: boolean
subsets?: Array<'latin' | 'latin-ext' | 'nko'>
}): T extends undefined ? NextFont : NextFontWithVariable
+export declare function Noto_Sans_NKo_Unjoined<
+ T extends CssVariable | undefined = undefined
+>(options?: {
+ weight?:
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | 'variable'
+ | Array<'400' | '500' | '600' | '700'>
+ style?: 'normal' | Array<'normal'>
+ display?: Display
+ variable?: T
+ preload?: boolean
+ fallback?: string[]
+ adjustFontFallback?: boolean
+ subsets?: Array<'latin' | 'latin-ext' | 'nko'>
+}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Noto_Sans_Nabataean<
T extends CssVariable | undefined = undefined
>(options: {
@@ -15324,7 +15393,9 @@ export declare function Noto_Sans_Symbols_2<
preload?: boolean
fallback?: string[]
adjustFontFallback?: boolean
- subsets?: Array<'latin' | 'latin-ext' | 'symbols'>
+ subsets?: Array<
+ 'braille' | 'latin' | 'latin-ext' | 'mayan-numerals' | 'symbols'
+ >
}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Noto_Sans_Syriac<
T extends CssVariable | undefined = undefined
@@ -16896,6 +16967,31 @@ export declare function Oleo_Script_Swash_Caps<
adjustFontFallback?: boolean
subsets?: Array<'latin' | 'latin-ext'>
}): T extends undefined ? NextFont : NextFontWithVariable
+export declare function Onest<
+ T extends CssVariable | undefined = undefined
+>(options?: {
+ weight?:
+ | '100'
+ | '200'
+ | '300'
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | '800'
+ | '900'
+ | 'variable'
+ | Array<
+ '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'
+ >
+ style?: 'normal' | Array<'normal'>
+ display?: Display
+ variable?: T
+ preload?: boolean
+ fallback?: string[]
+ adjustFontFallback?: boolean
+ subsets?: Array<'cyrillic' | 'cyrillic-ext' | 'latin' | 'latin-ext'>
+}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Oooh_Baby<
T extends CssVariable | undefined = undefined
>(options: {
@@ -17744,6 +17840,24 @@ export declare function Pirata_One<
adjustFontFallback?: boolean
subsets?: Array<'latin' | 'latin-ext'>
}): T extends undefined ? NextFont : NextFontWithVariable
+export declare function Pixelify_Sans<
+ T extends CssVariable | undefined = undefined
+>(options?: {
+ weight?:
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | 'variable'
+ | Array<'400' | '500' | '600' | '700'>
+ style?: 'normal' | Array<'normal'>
+ display?: Display
+ variable?: T
+ preload?: boolean
+ fallback?: string[]
+ adjustFontFallback?: boolean
+ subsets?: Array<'cyrillic' | 'latin' | 'latin-ext'>
+}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Plaster<
T extends CssVariable | undefined = undefined
>(options: {
@@ -23356,6 +23470,18 @@ export declare function Yomogi<
adjustFontFallback?: boolean
subsets?: Array<'cyrillic' | 'latin' | 'latin-ext' | 'vietnamese'>
}): T extends undefined ? NextFont : NextFontWithVariable
+export declare function Young_Serif<
+ T extends CssVariable | undefined = undefined
+>(options: {
+ weight: '400' | Array<'400'>
+ style?: 'normal' | Array<'normal'>
+ display?: Display
+ variable?: T
+ preload?: boolean
+ fallback?: string[]
+ adjustFontFallback?: boolean
+ subsets?: Array<'latin' | 'latin-ext'>
+}): T extends undefined ? NextFont : NextFontWithVariable
export declare function Yrsa<
T extends CssVariable | undefined = undefined
>(options?: {
diff --git a/packages/next-swc/crates/next-api/src/app.rs b/packages/next-swc/crates/next-api/src/app.rs
index da21b09f6a8bd..fc3fe96bdbd66 100644
--- a/packages/next-swc/crates/next-api/src/app.rs
+++ b/packages/next-swc/crates/next-api/src/app.rs
@@ -348,7 +348,7 @@ impl AppProject {
.iter()
.map(|(pathname, app_entrypoint)| async {
Ok((
- pathname.clone(),
+ pathname.to_string(),
*app_entry_point_to_route(self, app_entrypoint.clone()).await?,
))
})
diff --git a/packages/next-swc/crates/next-api/src/project.rs b/packages/next-swc/crates/next-api/src/project.rs
index b87f44b1ab905..71b317a67ce3c 100644
--- a/packages/next-swc/crates/next-api/src/project.rs
+++ b/packages/next-swc/crates/next-api/src/project.rs
@@ -348,10 +348,13 @@ impl Project {
#[turbo_tasks::function]
pub(super) async fn client_compile_time_info(self: Vc) -> Result> {
let this = self.await?;
+
Ok(get_client_compile_time_info(
this.mode,
this.browserslist_query.clone(),
self.dist_root_string(),
+ this.next_config,
+ find_app_dir(self.project_path()),
))
}
diff --git a/packages/next-swc/crates/next-build/src/next_build.rs b/packages/next-swc/crates/next-build/src/next_build.rs
index 6c73fed464ee0..6484ea7d0fe2d 100644
--- a/packages/next-swc/crates/next-build/src/next_build.rs
+++ b/packages/next-swc/crates/next-build/src/next_build.rs
@@ -7,6 +7,7 @@ use std::{
use anyhow::{Context, Result};
use dunce::canonicalize;
use next_core::{
+ app_structure::find_app_dir_if_enabled,
mode::NextMode,
next_app::get_app_client_references_chunks,
next_client::{get_client_chunking_context, get_client_compile_time_info},
@@ -132,8 +133,14 @@ pub(crate) async fn next_build(options: TransientInstance) -> Resu
let next_config = load_next_config(execution_context.with_layer("next_config".to_string()));
let mode = NextMode::Build;
- let client_compile_time_info =
- get_client_compile_time_info(mode, browserslist_query, node_root.to_string());
+ let app_dir = find_app_dir_if_enabled(project_root);
+ let client_compile_time_info = get_client_compile_time_info(
+ mode,
+ browserslist_query,
+ node_root.to_string(),
+ next_config,
+ app_dir,
+ );
let server_compile_time_info = get_server_compile_time_info(mode, env, ServerAddr::empty());
// TODO(alexkirsz) Pages should build their own routes, outside of a FS.
diff --git a/packages/next-swc/crates/next-core/src/app_structure.rs b/packages/next-swc/crates/next-core/src/app_structure.rs
index 2314cf7deb3cd..326edcdad30f4 100644
--- a/packages/next-swc/crates/next-core/src/app_structure.rs
+++ b/packages/next-swc/crates/next-core/src/app_structure.rs
@@ -8,8 +8,8 @@ use indexmap::{
};
use serde::{Deserialize, Serialize};
use turbo_tasks::{
- debug::ValueDebugFormat, trace::TraceRawVcs, Completion, Completions, TaskInput, ValueToString,
- Vc,
+ debug::ValueDebugFormat, trace::TraceRawVcs, Completion, Completions, TaskInput, ValueDefault,
+ ValueToString, Vc,
};
use turbopack_binding::{
turbo::tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath},
@@ -473,7 +473,27 @@ pub enum Entrypoint {
}
#[turbo_tasks::value(transparent)]
-pub struct Entrypoints(IndexMap);
+pub struct Entrypoints(IndexMap);
+
+#[turbo_tasks::value_impl]
+impl Entrypoints {
+ #[turbo_tasks::function]
+ pub fn paths(&self) -> Vc {
+ Vc::cell(self.0.keys().cloned().collect())
+ }
+}
+
+#[turbo_tasks::value(transparent)]
+#[derive(Default)]
+pub struct EntrypointPaths(Vec);
+
+#[turbo_tasks::value_impl]
+impl ValueDefault for EntrypointPaths {
+ #[turbo_tasks::function]
+ fn value_default() -> Vc {
+ Self::default().cell()
+ }
+}
fn is_parallel_route(name: &str) -> bool {
name.starts_with('@')
@@ -505,7 +525,7 @@ async fn add_parallel_route(
fn conflict_issue(
app_dir: Vc,
- e: &OccupiedEntry,
+ e: &OccupiedEntry,
a: &str,
b: &str,
value_a: &AppPage,
@@ -532,13 +552,11 @@ fn conflict_issue(
async fn add_app_page(
app_dir: Vc,
- result: &mut IndexMap,
+ result: &mut IndexMap,
page: AppPage,
loader_tree: Vc,
) -> Result<()> {
- let pathname = AppPath::from(page.clone());
-
- let mut e = match result.entry(format!("{pathname}")) {
+ let mut e = match result.entry(page.clone().into()) {
Entry::Occupied(e) => e,
Entry::Vacant(e) => {
e.insert(Entrypoint::AppPage { page, loader_tree });
@@ -589,13 +607,11 @@ async fn add_app_page(
fn add_app_route(
app_dir: Vc,
- result: &mut IndexMap,
+ result: &mut IndexMap,
page: AppPage,
path: Vc,
) {
- let pathname = AppPath::from(page.clone());
-
- let e = match result.entry(format!("{pathname}")) {
+ let e = match result.entry(page.clone().into()) {
Entry::Occupied(e) => e,
Entry::Vacant(e) => {
e.insert(Entrypoint::AppRoute { page, path });
@@ -632,13 +648,11 @@ fn add_app_route(
fn add_app_metadata_route(
app_dir: Vc,
- result: &mut IndexMap,
+ result: &mut IndexMap,
page: AppPage,
metadata: MetadataItem,
) {
- let pathname = AppPath::from(page.clone());
-
- let e = match result.entry(format!("{pathname}")) {
+ let e = match result.entry(page.clone().into()) {
Entry::Occupied(e) => e,
Entry::Vacant(e) => {
e.insert(Entrypoint::AppMetadata { page, metadata });
diff --git a/packages/next-swc/crates/next-core/src/next_app/bloom_filter.rs b/packages/next-swc/crates/next-core/src/next_app/bloom_filter.rs
new file mode 100644
index 0000000000000..286f82949f02f
--- /dev/null
+++ b/packages/next-swc/crates/next-core/src/next_app/bloom_filter.rs
@@ -0,0 +1,180 @@
+use std::{collections::HashSet, f64::consts::LN_2};
+
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ next_app::{AppPage, AppPath, PageSegment, PathSegment},
+ next_config::Redirect,
+};
+
+pub struct ClientRouterFilter {
+ pub static_filter: BloomFilter,
+ pub dynamic_filter: BloomFilter,
+}
+
+pub fn create_client_router_filter(
+ paths: &[AppPath],
+ redirects: &[Redirect],
+ allowed_error_rate: Option,
+) -> ClientRouterFilter {
+ let mut static_paths = HashSet::new();
+ let mut dynamic_paths = HashSet::new();
+
+ for path in paths {
+ if path.is_dynamic() {
+ let mut sub_path = AppPath::default();
+
+ for segment in path.iter() {
+ if !matches!(segment, PathSegment::Static(_)) {
+ break;
+ }
+
+ sub_path.0.push(segment.clone());
+ }
+
+ if !sub_path.is_empty() {
+ dynamic_paths.insert(sub_path.to_string());
+ }
+ } else {
+ static_paths.insert(path.to_string());
+ }
+ }
+
+ for redirect in redirects {
+ let app_page = AppPage::parse(&redirect.source).unwrap_or_default();
+
+ if app_page
+ .iter()
+ .all(|token| matches!(token, PageSegment::Static(_)))
+ {
+ static_paths.insert(app_page.to_string());
+ }
+ }
+
+ let static_filter = BloomFilter::from(static_paths.iter(), allowed_error_rate.unwrap_or(0.01));
+ let dynamic_filter =
+ BloomFilter::from(dynamic_paths.iter(), allowed_error_rate.unwrap_or(0.01));
+
+ ClientRouterFilter {
+ static_filter,
+ dynamic_filter,
+ }
+}
+
+// minimal implementation MurmurHash2 hash function
+fn murmurhash2(s: &str) -> u32 {
+ const M: u32 = 0x5bd1e995;
+
+ let mut h: u32 = 0;
+ for &b in s.as_bytes() {
+ h = (h ^ b as u32).wrapping_mul(M);
+ h ^= h >> 13;
+ h = h.wrapping_mul(M);
+ }
+
+ h
+}
+
+#[cfg(test)]
+mod test {
+ use crate::next_app::{
+ bloom_filter::{create_client_router_filter, murmurhash2, BloomFilter},
+ AppPath, PathSegment,
+ };
+
+ // testing that we get the same output as the javascript implementation.
+ #[test]
+ fn test_murmurhash2() {
+ assert_eq!(murmurhash2("/"), 4097004964);
+ assert_eq!(murmurhash2("/test"), 3006934538);
+ assert_eq!(murmurhash2("/test/route/123/long/as/heck"), 3187325762);
+ assert_eq!(
+ murmurhash2("/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
+ 2001750934
+ );
+ }
+
+ // testing that we get the same output as the javascript implementation.
+ #[test]
+ fn test_create_client_router_filter() {
+ let app_paths = &[
+ AppPath(vec![]),
+ AppPath(vec![PathSegment::Static("favicon.ico".to_string())]),
+ AppPath(vec![PathSegment::Static("_not-found".to_string())]),
+ AppPath(vec![PathSegment::Static("app".to_string())]),
+ ];
+
+ assert_eq!(
+ create_client_router_filter(app_paths, &[], None).static_filter,
+ BloomFilter {
+ num_items: 4,
+ error_rate: 0.01,
+ num_bits: 39,
+ num_hashes: 7,
+ bit_array: vec![
+ 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1
+ ]
+ }
+ )
+ }
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
+#[serde(rename_all = "camelCase")]
+pub struct BloomFilter {
+ num_items: usize,
+ error_rate: f64,
+ num_bits: usize,
+ num_hashes: usize,
+ bit_array: Vec,
+}
+
+impl BloomFilter {
+ pub fn new(num_items: usize, error_rate: f64) -> Self {
+ let num_bits = (-(num_items as f64 * error_rate.ln()) / LN_2.powi(2)).ceil() as usize;
+ let num_hashes = ((num_bits as f64 / num_items as f64) * LN_2).ceil() as usize;
+ let bit_array = vec![0; num_bits];
+
+ BloomFilter {
+ num_items,
+ error_rate,
+ num_bits,
+ num_hashes,
+ bit_array,
+ }
+ }
+
+ pub fn from<'a>(items: impl IntoIterator, error_rate: f64) -> Self {
+ let items = items.into_iter().collect::>();
+
+ let mut filter = Self::new(items.len(), error_rate);
+ for item in items {
+ filter.add(item)
+ }
+ filter
+ }
+
+ pub fn add(&mut self, item: &str) {
+ let hash_values = self.get_hash_values(item);
+ hash_values.iter().for_each(|&hash| {
+ self.bit_array[hash] = 1;
+ });
+ }
+
+ pub fn contains(&self, item: &str) -> bool {
+ let hash_values = self.get_hash_values(item);
+ hash_values.iter().all(|&hash| self.bit_array[hash] == 1)
+ }
+
+ fn get_hash_values(&self, item: &str) -> Vec {
+ let mut hash_values = Vec::new();
+
+ for i in 1..self.num_hashes + 1 {
+ let hash = murmurhash2(&format!("{item}{i}")) as usize % self.num_bits;
+ hash_values.push(hash);
+ }
+
+ hash_values
+ }
+}
diff --git a/packages/next-swc/crates/next-core/src/next_app/mod.rs b/packages/next-swc/crates/next-core/src/next_app/mod.rs
index 5b14d51757e6d..d0f5910f4c282 100644
--- a/packages/next-swc/crates/next-core/src/next_app/mod.rs
+++ b/packages/next-swc/crates/next-core/src/next_app/mod.rs
@@ -3,6 +3,7 @@ pub mod app_client_shared_chunks;
pub mod app_entry;
pub mod app_page_entry;
pub mod app_route_entry;
+pub mod bloom_filter;
pub mod metadata;
use std::{
@@ -285,6 +286,19 @@ impl Display for PathSegment {
)]
pub struct AppPath(pub Vec);
+impl AppPath {
+ pub fn is_dynamic(&self) -> bool {
+ self.iter().any(|segment| {
+ matches!(
+ (segment,),
+ (PathSegment::Dynamic(_)
+ | PathSegment::CatchAll(_)
+ | PathSegment::OptionalCatchAll(_),)
+ )
+ })
+ }
+}
+
impl Deref for AppPath {
type Target = [PathSegment];
diff --git a/packages/next-swc/crates/next-core/src/next_client/context.rs b/packages/next-swc/crates/next-core/src/next_client/context.rs
index a165be526cf0f..a455934b75ef8 100644
--- a/packages/next-swc/crates/next-core/src/next_client/context.rs
+++ b/packages/next-swc/crates/next-core/src/next_client/context.rs
@@ -1,4 +1,4 @@
-use core::{default::Default, result::Result::Ok};
+use core::result::Result::Ok;
use anyhow::Result;
use turbo_tasks::{Value, Vc};
@@ -34,10 +34,12 @@ use turbopack_binding::{
use super::transforms::get_next_client_transforms_rules;
use crate::{
+ app_structure::{get_entrypoints, EntrypointPaths, OptionAppDir},
babel::maybe_add_babel_loader,
embed_js::next_js_fs,
env::env_for_js,
mode::NextMode,
+ next_app::{bloom_filter::create_client_router_filter, AppPath},
next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping},
next_client::runtime_entry::{RuntimeEntries, RuntimeEntry},
next_config::NextConfig,
@@ -65,50 +67,83 @@ use crate::{
util::foreign_code_context_condition,
};
-fn defines(mode: NextMode, dist_root_path: Option<&str>) -> CompileTimeDefines {
- // [TODO] macro may need to allow dynamically expand from some iterable values
- let mut defines = compile_time_defines!(
+fn defines(
+ mode: NextMode,
+ dist_root_path: &str,
+ next_config: &NextConfig,
+ app_paths: &[AppPath],
+) -> Result {
+ let filter = create_client_router_filter(
+ app_paths,
+ if next_config
+ .experimental
+ .client_router_filter_redirects
+ .unwrap_or_default()
+ {
+ next_config
+ .original_redirects
+ .as_deref()
+ .unwrap_or_default()
+ } else {
+ &[]
+ },
+ next_config.experimental.client_router_filter_allowed_rate,
+ );
+
+ // TODO: macro may need to allow dynamically expand from some iterable values
+ // TODO(WEB-937): there are more defines needed, see
+ // packages/next/src/build/webpack/plugins/define-env-plugin.ts
+ Ok(compile_time_defines!(
+ process.browser = true,
process.turbopack = true,
+ process.env.TURBOPACK = true,
process.env.NODE_ENV = mode.node_env(),
- process.env.__NEXT_CLIENT_ROUTER_FILTER_ENABLED = false,
+ process.env.NEXT_RUNTIME = "".to_string(),
+ process.env.__NEXT_CLIENT_ROUTER_FILTER_ENABLED = next_config
+ .experimental
+ .client_router_filter
+ .unwrap_or_default(),
+ process.env.__NEXT_CLIENT_ROUTER_S_FILTER = serde_json::to_value(&filter.static_filter)?,
+ process.env.__NEXT_CLIENT_ROUTER_D_FILTER = serde_json::to_value(&filter.dynamic_filter)?,
+ process.env.__NEXT_DIST_DIR = dist_root_path.to_string(),
process.env.__NEXT_HAS_REWRITES = true,
process.env.__NEXT_I18N_SUPPORT = false,
- );
-
- if let Some(dist_root_path) = dist_root_path {
- defines.0.insert(
- vec![
- "process".to_string(),
- "env".to_string(),
- "__NEXT_DIST_DIR".to_string(),
- ],
- dist_root_path.to_string().into(),
- );
- }
-
- // TODO(WEB-937) there are more defines needed, see
- // packages/next/src/build/webpack-config.ts
-
- defines
+ ))
}
#[turbo_tasks::function]
async fn next_client_defines(
mode: NextMode,
dist_root_path: Vc,
+ next_config: Vc,
+ app_paths: Vc,
) -> Result> {
let dist_root_path = &*dist_root_path.await?;
- Ok(defines(mode, Some(dist_root_path.as_str())).cell())
+ Ok(defines(
+ mode,
+ dist_root_path.as_str(),
+ &*next_config.await?,
+ &app_paths.await?,
+ )?
+ .cell())
}
#[turbo_tasks::function]
async fn next_client_free_vars(
mode: NextMode,
dist_root_path: Vc,
+ next_config: Vc,
+ app_paths: Vc,
) -> Result> {
let dist_root_path = &*dist_root_path.await?;
Ok(free_var_references!(
- ..defines(mode, Some(dist_root_path.as_str())).into_iter(),
+ ..defines(
+ mode,
+ dist_root_path.as_str(),
+ &*next_config.await?,
+ &app_paths.await?
+ )?
+ .into_iter(),
Buffer = FreeVarReference::EcmaScriptModule {
request: "node:buffer".to_string(),
lookup_path: None,
@@ -123,12 +158,28 @@ async fn next_client_free_vars(
.cell())
}
+#[turbo_tasks::function]
+async fn get_app_paths(
+ app_dir: Vc,
+ next_config: Vc,
+) -> Result> {
+ Ok(if let Some(app_dir) = *app_dir.await? {
+ get_entrypoints(app_dir, next_config.page_extensions()).paths()
+ } else {
+ Default::default()
+ })
+}
+
#[turbo_tasks::function]
pub fn get_client_compile_time_info(
mode: NextMode,
browserslist_query: String,
dist_root_path: Vc,
+ next_config: Vc,
+ app_dir: Vc,
) -> Vc {
+ let app_paths = get_app_paths(app_dir, next_config);
+
CompileTimeInfo::builder(Environment::new(Value::new(ExecutionEnvironment::Browser(
BrowserEnvironment {
dom: true,
@@ -138,8 +189,18 @@ pub fn get_client_compile_time_info(
}
.into(),
))))
- .defines(next_client_defines(mode, dist_root_path))
- .free_var_references(next_client_free_vars(mode, dist_root_path))
+ .defines(next_client_defines(
+ mode,
+ dist_root_path,
+ next_config,
+ app_paths,
+ ))
+ .free_var_references(next_client_free_vars(
+ mode,
+ dist_root_path,
+ next_config,
+ app_paths,
+ ))
.cell()
}
diff --git a/packages/next-swc/crates/next-core/src/next_config.rs b/packages/next-swc/crates/next-core/src/next_config.rs
index f9427f13e8029..7bfcd97e488dc 100644
--- a/packages/next-swc/crates/next-core/src/next_config.rs
+++ b/packages/next-swc/crates/next-core/src/next_config.rs
@@ -89,6 +89,10 @@ pub struct NextConfig {
pub asset_prefix: Option,
pub base_path: Option,
+ ///
+ #[serde(rename = "_originalRedirects")]
+ pub original_redirects: Option>,
+
// Partially supported
pub compiler: Option,
@@ -403,57 +407,117 @@ pub enum LoaderItem {
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "camelCase")]
pub struct ExperimentalConfig {
- pub strict_next_head: Option,
- pub server_components_external_packages: Option>,
- pub turbo: Option,
pub allowed_revalidate_header_keys: Option>,
+ pub client_router_filter: Option,
+ /// decimal for percent for possible false positives e.g. 0.01 for 10%
+ /// potential false matches lower percent increases size of the filter
+ pub client_router_filter_allowed_rate: Option,
+ pub client_router_filter_redirects: Option,
pub fetch_cache_key_prefix: Option,
+ /// In-memory cache size in bytes.
+ ///
+ /// If `isr_memory_cache_size: 0` disables in-memory caching.
pub isr_memory_cache_size: Option,
pub isr_flush_to_disk: Option,
+ /// For use with `@next/mdx`. Compile MDX files using the new Rust compiler.
+ /// @see https://nextjs.org/docs/app/api-reference/next-config-js/mdxRs
mdx_rs: Option,
+ /// A list of packages that should be treated as external in the RSC server
+ /// build. @see https://nextjs.org/docs/app/api-reference/next-config-js/server_components_external_packages
+ pub server_components_external_packages: Option>,
+ pub strict_next_head: Option,
pub swc_plugins: Option>,
- // This is used in Next.js, doesn't require compiler changes.
- client_router_filter_redirects: Option,
- // Doesn't apply to Turbopack.
- webpack_build_worker: Option,
+ pub turbo: Option,
+ pub turbotrace: Option,
- // unsupported
- optimize_package_imports: Option>,
+ // ---
+ // UNSUPPORTED
+ // ---
+ adjust_font_fallbacks: Option,
adjust_font_fallbacks_with_size_adjust: Option,
- allow_middleware_response_body: Option,
amp: Option,
+ app_document_preloading: Option,
+ case_sensitive_routes: Option,
cpus: Option,
cra_compat: Option,
+ deployment_id: Option,
disable_optimized_loading: Option,
disable_postcss_preset_env: Option,
esm_externals: Option,
+ extension_alias: Option,
external_dir: Option,
- fallback_node_polyfills: Option,
- font_loaders: Option,
+ external_middleware_rewrites_resolve: Option,
+ /// If set to `false`, webpack won't fall back to polyfill Node.js modules
+ /// in the browser Full list of old polyfills is accessible here:
+ /// [webpack/webpack#Module_notound_error.js#L13-L42](https://github.com/webpack/webpack/blob/2a0536cf510768111a3a6dceeb14cb79b9f59273/lib/Module_not_found_error.js#L13-L42)
+ fallback_node_polyfills: Option, // false
force_swc_transforms: Option,
fully_specified: Option,
gzip_size: Option,
+ /// custom path to a cache handler to use
incremental_cache_handler_path: Option,
+ instrumentation_hook: Option,
large_page_data_bytes: Option,
+ logging: Option,
manual_client_base_path: Option,
+ memory_based_workers_count: Option,
middleware_prefetch: Option,
next_script_workers: Option,
optimistic_client_cache: Option,
+ /// Optimize React APIs for server builds.
+ optimize_server_react: Option,
+ /// optimizeCss can be boolean or critters' option object
+ /// Use Record as critters doesn't export its Option type
+ /// https://github.com/GoogleChromeLabs/critters/blob/a590c05f9197b656d2aeaae9369df2483c26b072/packages/critters/src/index.d.ts
optimize_css: Option,
+ /// Automatically apply the "modularize_imports" optimization to imports of
+ /// the specified packages.
+ optimize_package_imports: Option>,
output_file_tracing_ignores: Option>,
+ output_file_tracing_includes: Option,
output_file_tracing_root: Option,
+ /// Using this feature will enable the `react@experimental` for the `app`
+ /// directory.
+ ppr: Option,
proxy_timeout: Option,
scroll_restoration: Option,
+ /// Enables server actions. Using this feature will enable the
+ /// `react@experimental` for the `app` directory. @see https://nextjs.org/docs/app/api-reference/functions/server-actions
+ server_actions: Option,
+ /// Allows adjusting body parser size limit for server actions.
+ server_actions_body_size_limit: Option,
+ /// enables the minification of server code.
+ server_minification: Option,
+ /// Enables source maps generation for the server production bundle.
+ server_source_maps: Option,
sri: Option,
- swc_minify_debug_options: Option,
+ swc_minify: Option,
+ /// This option is removed
+ swc_minify_debug_options: Option<()>,
swc_trace_profiling: Option,
- transpile_packages: Option>,
- pub turbotrace: Option,
+ /// @internal Used by the Next.js internals only.
+ trust_host_header: Option,
+ /// Generate Route types and enable type checking for Link and Router.push,
+ /// etc. This option requires `appDir` to be enabled first.
+ /// @see https://nextjs.org/docs/app/api-reference/next-config-js/typedRoutes
+ typed_routes: Option,
url_imports: Option,
- web_vitals_attribution: Option,
+ use_deployment_id: Option,
+ use_deployment_id_server_actions: Option,
+ web_vitals_attribution: Option>,
+ /// This option is to enable running the Webpack build in a worker thread
+ /// (doesn't apply to Turbopack).
+ webpack_build_worker: Option,
worker_threads: Option,
}
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
+#[serde(untagged)]
+enum SizeLimit {
+ Number(f64),
+ WithUnit(String),
+}
+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "kebab-case")]
enum MiddlewarePrefetchType {
diff --git a/packages/next/src/server/lib/router-utils/setup-dev.ts b/packages/next/src/server/lib/router-utils/setup-dev.ts
index 6d5d80da1356a..f18f3f7ce76a8 100644
--- a/packages/next/src/server/lib/router-utils/setup-dev.ts
+++ b/packages/next/src/server/lib/router-utils/setup-dev.ts
@@ -1196,7 +1196,7 @@ async function startWatcher(opts: SetupOpts) {
await writeMiddlewareManifest()
await writeOtherManifests()
- processIssues(page, page, writtenEndpoint, true)
+ processIssues(page, page, writtenEndpoint)
break
}
@@ -1222,7 +1222,7 @@ async function startWatcher(opts: SetupOpts) {
await writeMiddlewareManifest()
await writeOtherManifests()
- processIssues(page, page, writtenEndpoint, true)
+ processIssues(page, page, writtenEndpoint)
break
}
diff --git a/packages/next/src/shared/lib/bloom-filter.ts b/packages/next/src/shared/lib/bloom-filter.ts
index fd7e6e75a4a6e..18e4490f82a92 100644
--- a/packages/next/src/shared/lib/bloom-filter.ts
+++ b/packages/next/src/shared/lib/bloom-filter.ts
@@ -45,7 +45,7 @@ export class BloomFilter {
bitArray: this.bitArray,
}
- if (typeof window === 'undefined' && process.env.NEXT_RUNTIME !== 'edge') {
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
if (this.errorRate < 0.01) {
const filterData = JSON.stringify(data)
const gzipSize = require('next/dist/compiled/gzip-size').sync(
diff --git a/test/build-turbopack-tests-manifest.js b/test/build-turbopack-tests-manifest.js
index d9f134047d43f..2c3e6bb86c1d3 100644
--- a/test/build-turbopack-tests-manifest.js
+++ b/test/build-turbopack-tests-manifest.js
@@ -19,52 +19,57 @@ const INITIALIZING_TEST_CASES = [
'should build successfully',
]
+// please make sure this is sorted alphabetically when making changes.
const SKIPPED_TEST_SUITES = {
- 'test/e2e/basepath.test.ts': [
- 'basePath should 404 when manually adding basePath with router.push',
- 'basePath should 404 when manually adding basePath with router.replace',
- ],
- 'test/integration/dynamic-routing/test/middleware.test.js': [
- 'Dynamic Routing dev mode should resolve dynamic route href for page added later',
- 'Dynamic Routing production mode should output a routes-manifest correctly',
+ 'test/development/acceptance-app/ReactRefreshLogBox-builtins.test.ts': [
+ 'ReactRefreshLogBox app turbo Module not found missing global CSS',
],
- 'test/integration/css/test/css-modules.test.js': [
- 'CSS Modules Composes Ordering Development Mode should have correct color on index page (on nav from other)',
+ 'test/development/acceptance-app/ReactRefreshRegression.test.ts': [
+ 'ReactRefreshRegression app can fast refresh a page with dynamic rendering',
+ 'ReactRefreshRegression app can fast refresh a page with config',
],
'test/development/acceptance/ReactRefreshRequire.test.ts': [
'ReactRefreshRequire re-runs accepted modules',
'ReactRefreshRequire propagates a hot update to closest accepted module',
'ReactRefreshRequire propagates hot update to all inverse dependencies',
],
+ 'test/e2e/basepath.test.ts': [
+ 'basePath should 404 when manually adding basePath with router.push',
+ 'basePath should 404 when manually adding basePath with router.replace',
+ ],
'test/e2e/middleware-rewrites/test/index.test.ts': [
'Middleware Rewrite should have props for afterFiles rewrite to SSG page',
],
- 'test/integration/dynamic-routing/test/index.test.js': [
- 'Dynamic Routing production mode should have correct cache entries on prefetch',
- 'Dynamic Routing production mode should render dynamic route with query',
- ],
- 'test/development/acceptance-app/ReactRefreshLogBox-builtins.test.ts': [
- 'ReactRefreshLogBox app turbo Module not found missing global CSS',
- ],
- 'test/development/acceptance-app/ReactRefreshRegression.test.ts': [
- 'ReactRefreshRegression app can fast refresh a page with dynamic rendering',
- 'ReactRefreshRegression app can fast refresh a page with config',
- ],
'test/integration/absolute-assetprefix/test/index.test.js': [
'absolute assetPrefix with path prefix should work with getStaticPaths prerendered',
],
+ 'test/integration/app-document-remove-hmr/test/index.test.js': [
+ '_app removal HMR should HMR when _document is removed',
+ ],
'test/integration/create-next-app/package-manager.test.ts': [
'should use pnpm as the package manager on supplying --use-pnpm',
'should use pnpm as the package manager on supplying --use-pnpm with example',
'should infer pnpm as the package manager',
'should infer pnpm as the package manager with example',
],
+ 'test/integration/css/test/css-modules.test.js': [
+ 'CSS Modules Composes Ordering Development Mode should have correct color on index page (on nav from other)',
+ ],
+ 'test/integration/custom-error/test/index.test.js': [/Custom _error/],
+ 'test/integration/dynamic-routing/test/index.test.js': [
+ 'Dynamic Routing production mode should have correct cache entries on prefetch',
+ 'Dynamic Routing production mode should render dynamic route with query',
+ ],
+ 'test/integration/dynamic-routing/test/middleware.test.js': [
+ 'Dynamic Routing dev mode should resolve dynamic route href for page added later',
+ 'Dynamic Routing production mode should output a routes-manifest correctly',
+ ],
+ 'test/integration/import-assertion/test/index.test.js': [
+ /should handle json assertions/,
+ ],
'test/integration/trailing-slashes/test/index.test.js': [
'Trailing slashes dev mode, with basepath, trailingSlash: true /docs/linker?href=/ should navigate to /docs/',
],
- 'test/integration/app-document-remove-hmr/test/index.test.js': [
- '_app removal HMR should HMR when _document is removed',
- ],
}
async function updatePassingTests() {
diff --git a/test/turbopack-tests-manifest.json b/test/turbopack-tests-manifest.json
index 2f4e525da0c5c..32345dad548fb 100644
--- a/test/turbopack-tests-manifest.json
+++ b/test/turbopack-tests-manifest.json
@@ -7283,7 +7283,10 @@
"runtimeError": false
},
"test/integration/custom-error/test/index.test.js": {
- "passed": [
+ "passed": [],
+ "failed": [],
+ "pending": [],
+ "flakey": [
"Custom _error dev mode 1 should not warn with /_error and /404 when rendering error first",
"Custom _error dev mode 2 should not warn with /_error and /404",
"Custom _error dev mode 2 should warn on custom /_error without custom /404"
@@ -11784,10 +11787,13 @@
"runtimeError": false
},
"test/integration/import-assertion/test/index.test.js": {
- "passed": ["import-assertion dev should handle json assertions"],
- "failed": ["import-assertion prod should handle json assertions"],
+ "passed": [],
+ "failed": [],
"pending": [],
- "flakey": [],
+ "flakey": [
+ "import-assertion dev should handle json assertions",
+ "import-assertion prod should handle json assertions"
+ ],
"runtimeError": false
},
"test/integration/index-index/test/index.test.js": {