From 5415811037e970c34600bb71d64a4416d7ad1ac1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 29 Sep 2023 00:48:16 +0200 Subject: [PATCH 1/2] Implement list of config options for Turbopack (#56188) This adds the define env for listed options below: - `crossOrigin` - `devIndicators` - `output` - `analyticsId` - `optimizeFonts` - `experimental.useDeploymentId` - `experimental.useDeploymentIdServerActions` - `experimental.deploymentId` - `experimental.manualClientBasePath` - `experimental.optimisticClientCache` - `experimental.middlewarePrefetch` - `experimental.optimizeCss` - `experimental.nextScriptWorkers` - `experimental.webVitalsAttribution` For some there might still be missing pieces, for example `crossOrigin` needs something in Turbopack's script injection but most others will "just work" after this PR. Added the few ones that did not come directly from config as todos, this PR can be landed without those. --- packages/next-swc/crates/next-core/src/env.rs | 191 +++++++++++++++++- .../crates/next-core/src/next_config.rs | 44 ++-- 2 files changed, 212 insertions(+), 23 deletions(-) diff --git a/packages/next-swc/crates/next-core/src/env.rs b/packages/next-swc/crates/next-core/src/env.rs index ccc8d6a42b60f..e020e8773ff1e 100644 --- a/packages/next-swc/crates/next-core/src/env.rs +++ b/packages/next-swc/crates/next-core/src/env.rs @@ -141,7 +141,6 @@ pub async fn env_for_js( map.insert( "__NEXT_I18N_SUPPORT".to_string(), - // How do I check if i18n exists in the config? if next_config.i18n.is_none() { "false".to_string() } else { @@ -161,6 +160,196 @@ pub async fn env_for_js( }, ); + map.insert( + "NEXT_MINIMAL".to_string(), + // Don't stringify undefined + "\"\"".to_string(), + ); + + map.insert( + "__NEXT_ACTIONS_DEPLOYMENT_ID".to_string(), + if next_config + .experimental + .use_deployment_id_server_actions + .unwrap_or(false) + { + "true".to_string() + } else { + "false".to_string() + }, + ); + + map.insert( + "NEXT_DEPLOYMENT_ID".to_string(), + // Don't stringify undefined + if let Some(deployment_id) = next_config.experimental.deployment_id.as_ref() { + serde_json::to_string(deployment_id)? + } else { + "undefined".to_string() + }, + ); + + map.insert( + "__NEXT_MANUAL_CLIENT_BASE_PATH".to_string(), + if next_config + .experimental + .manual_client_base_path + .unwrap_or(false) + { + "true".to_string() + } else { + "false".to_string() + }, + ); + + map.insert( + "__NEXT_OPTIMISTIC_CLIENT_CACHE".to_string(), + if next_config + .experimental + .optimistic_client_cache + .unwrap_or(false) + { + "true".to_string() + } else { + "false".to_string() + }, + ); + + map.insert( + "__NEXT_MIDDLEWARE_PREFETCH".to_string(), + // Don't stringify undefined + if let Some(middleware_prefetch) = next_config.experimental.middleware_prefetch.as_ref() { + serde_json::to_string(middleware_prefetch)? + } else { + "undefined".to_string() + }, + ); + + // TODO: Implement crossOrigin in Turbopack script injection + map.insert( + "__NEXT_CROSS_ORIGIN".to_string(), + // Don't stringify undefined + if let Some(cross_origin) = next_config.cross_origin.as_ref() { + serde_json::to_string(cross_origin)? + } else { + "undefined".to_string() + }, + ); + + map.insert( + "__NEXT_BUILD_INDICATOR".to_string(), + // Don't stringify undefined + match next_config.dev_indicators.as_ref() { + Some(dev_indicators) => match dev_indicators.build_activity.as_ref() { + Some(build_activity) => serde_json::to_string(build_activity)?, + None => "false".to_string(), + }, + None => "false".to_string(), + }, + ); + + map.insert( + "__NEXT_BUILD_INDICATOR_POSITION".to_string(), + // Don't stringify undefined + match next_config.dev_indicators.as_ref() { + Some(dev_indicators) => match dev_indicators.build_activity_position.as_ref() { + Some(build_activity_position) => serde_json::to_string(build_activity_position)?, + None => "undefined".to_string(), + }, + None => "undefined".to_string(), + }, + ); + + map.insert( + "__NEXT_OPTIMIZE_FONTS".to_string(), + if next_config.optimize_fonts.unwrap_or(true) { + "true".to_string() + } else { + "false".to_string() + }, + ); + + map.insert( + "__NEXT_OPTIMIZE_CSS".to_string(), + // Don't stringify undefined + if let Some(optimize_css) = next_config.experimental.optimize_css.as_ref() { + serde_json::to_string(optimize_css)? + } else { + "false".to_string() + }, + ); + + map.insert( + "__NEXT_SCRIPT_WORKERS".to_string(), + // TODO: This should be true in production mode + // if next_config + // .experimental + // .next_script_workers + // .unwrap_or(false) + // { + // "false".to_string() + // } else { + // "false".to_string() + // }, + "false".to_string(), + ); + + map.insert( + "__NEXT_CONFIG_OUTPUT".to_string(), + // Don't stringify undefined + if let Some(output) = next_config.output.as_ref() { + serde_json::to_string(output)? + } else { + "undefined".to_string() + }, + ); + + map.insert( + "__NEXT_ANALYTICS_ID".to_string(), + // Don't stringify undefined + if let Some(analytics_id) = next_config.analytics_id.as_ref() { + serde_json::to_string(analytics_id)? + } else { + "undefined".to_string() + }, + ); + + map.insert( + "__NEXT_HAS_WEB_VITALS_ATTRIBUTION".to_string(), + if next_config.experimental.web_vitals_attribution.is_none() { + "false".to_string() + } else { + "true".to_string() + }, + ); + + map.insert( + "__NEXT_WEB_VITALS_ATTRIBUTION".to_string(), + // Don't stringify undefined + if let Some(web_vitals_attribution) = + next_config.experimental.web_vitals_attribution.as_ref() + { + serde_json::to_string(web_vitals_attribution)? + } else { + "undefined".to_string() + }, + ); + + // TODO: Implement + // map.insert( + // "__NEXT_FETCH_CACHE_KEY_PREFIX".to_string(), + // ); + + // TODO: Implement + // map.insert( + // "__NEXT_HAS_REWRITES".to_string(), + // ); + + // TODO: Implement for node server only? + // map.insert( + // "__NEXT_EXPERIMENTAL_REACT".to_string(), + // ); + if !test_mode.is_empty() { map.insert("__NEXT_TEST_MODE".to_string(), "true".to_string()); } 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 6f503af420d9a..20de9047f6788 100644 --- a/packages/next-swc/crates/next-core/src/next_config.rs +++ b/packages/next-swc/crates/next-core/src/next_config.rs @@ -91,6 +91,10 @@ pub struct NextConfig { pub skip_middleware_url_normalize: Option, pub skip_trailing_slash_redirect: Option, pub i18n: Option, + pub cross_origin: Option, + pub dev_indicators: Option, + pub output: Option, + pub analytics_id: Option, /// #[serde(rename = "_originalRedirects")] @@ -99,15 +103,12 @@ pub struct NextConfig { // Partially supported pub compiler: Option, - pub output: Option, + pub optimize_fonts: Option, // unsupported - cross_origin: Option, amp: AmpConfig, - analytics_id: String, clean_dist_dir: bool, compress: bool, - dev_indicators: DevIndicatorsConfig, eslint: EslintConfig, exclude_default_moment_locales: bool, // this can be a function in js land @@ -117,7 +118,6 @@ pub struct NextConfig { generate_etags: bool, http_agent_options: HttpAgentConfig, on_demand_entries: OnDemandEntriesConfig, - optimize_fonts: bool, output_file_tracing: bool, powered_by_header: bool, production_browser_source_maps: bool, @@ -146,7 +146,7 @@ struct EslintConfig { #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "kebab-case")] -enum BuildActivityPositions { +pub enum BuildActivityPositions { #[default] BottomRight, BottomLeft, @@ -156,9 +156,9 @@ enum BuildActivityPositions { #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] -struct DevIndicatorsConfig { - build_activity: bool, - build_activity_position: BuildActivityPositions, +pub struct DevIndicatorsConfig { + pub build_activity: Option, + pub build_activity_position: Option, } #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] @@ -431,6 +431,18 @@ pub struct ExperimentalConfig { pub turbotrace: Option, pub external_middleware_rewrites_resolve: Option, pub scroll_restoration: Option, + pub use_deployment_id: Option, + pub use_deployment_id_server_actions: Option, + pub deployment_id: Option, + pub manual_client_base_path: Option, + pub optimistic_client_cache: Option, + pub middleware_prefetch: 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 + pub optimize_css: Option, + pub next_script_workers: Option, + pub web_vitals_attribution: Option>, // --- // UNSUPPORTED @@ -442,7 +454,6 @@ pub struct ExperimentalConfig { case_sensitive_routes: Option, cpus: Option, cra_compat: Option, - deployment_id: Option, disable_optimized_loading: Option, disable_postcss_preset_env: Option, esm_externals: Option, @@ -460,17 +471,9 @@ pub struct ExperimentalConfig { 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>, @@ -502,9 +505,6 @@ pub struct ExperimentalConfig { /// @see https://nextjs.org/docs/app/api-reference/next-config-js/typedRoutes typed_routes: Option, url_imports: 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, @@ -520,7 +520,7 @@ enum SizeLimit { #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "kebab-case")] -enum MiddlewarePrefetchType { +pub enum MiddlewarePrefetchType { Strict, Flexible, } From 769d27aaccf34a6a32158725211b51f869b3ea2f Mon Sep 17 00:00:00 2001 From: boylett Date: Fri, 29 Sep 2023 00:11:33 +0100 Subject: [PATCH 2/2] correcting link to useSearchParams ref (#56169) The link to the useSearchParams ref within the File Conventions > layout.js page currently links to the useParams ref, which is wrong and may lead to confusion as the useParams and useSearchParams APIs operate differently. --- docs/02-app/02-api-reference/02-file-conventions/layout.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/02-app/02-api-reference/02-file-conventions/layout.mdx b/docs/02-app/02-api-reference/02-file-conventions/layout.mdx index 737d4baf1aac8..91e7805948f64 100644 --- a/docs/02-app/02-api-reference/02-file-conventions/layout.mdx +++ b/docs/02-app/02-api-reference/02-file-conventions/layout.mdx @@ -116,7 +116,7 @@ This performance optimization allows navigation between pages that share a layou Because `dashboard/layout.tsx` doesn't re-render, the `searchParams` prop in the layout Server Component might become **stale** after navigation. -- Instead, use the Page [`searchParams`](/docs/app/api-reference/file-conventions/page) prop or the [`useSearchParams`](/docs/app/api-reference/functions/use-params) hook in a Client Component, which is re-rendered on the client with the latest `searchParams`. +- Instead, use the Page [`searchParams`](/docs/app/api-reference/file-conventions/page#searchparams-optional) prop or the [`useSearchParams`](/docs/app/api-reference/functions/use-search-params) hook in a Client Component, which is re-rendered on the client with the latest `searchParams`. ### Root Layouts