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 + + Next.js 13 and app template Router-ready Supabase starter kit. +

Supabase starter kit

+
-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. +

-## Deploy your own +

+ Features · + Demo · + Deploy to Vercel · + Clone and run locally · + How to use · + Feedback and issues +

+
-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": {