From cd8cbb3959346c411c83fb1b8766312404076b75 Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Fri, 22 Aug 2025 16:30:43 +0200 Subject: [PATCH 1/2] Turbopack: throw large static metadata error earlier f --- .../next-core/src/next_app/metadata/route.rs | 111 ++++++++++++++---- .../opengraph-image/index.test.ts | 4 +- .../twitter-image/index.test.ts | 4 +- 3 files changed, 92 insertions(+), 27 deletions(-) diff --git a/crates/next-core/src/next_app/metadata/route.rs b/crates/next-core/src/next_app/metadata/route.rs index e52ff26aed634..e1cca66da1751 100644 --- a/crates/next-core/src/next_app/metadata/route.rs +++ b/crates/next-core/src/next_app/metadata/route.rs @@ -5,12 +5,16 @@ use anyhow::{Ok, Result, bail}; use base64::{display::Base64Display, engine::general_purpose::STANDARD}; use indoc::{formatdoc, indoc}; -use turbo_rcstr::rcstr; +use turbo_rcstr::{RcStr, rcstr}; use turbo_tasks::Vc; use turbo_tasks_fs::{self, File, FileContent, FileSystemPath}; use turbopack::ModuleAssetContext; use turbopack_core::{ - asset::AssetContent, file_source::FileSource, source::Source, virtual_source::VirtualSource, + asset::AssetContent, + file_source::FileSource, + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + source::Source, + virtual_source::VirtualSource, }; use turbopack_ecmascript::utils::StringifyJs; @@ -133,8 +137,6 @@ async fn static_route_source(mode: NextMode, path: FileSystemPath) -> Result Result file_size_limit_mb + { + StaticMetadataFileSizeIssue { + img_name: if is_twitter { + rcstr!("Twitter") + } else { + rcstr!("Open Graph") + }, + path: path.clone(), + file_size_limit_mb, + file_size_mb, + } + .resolved_cell() + .emit(); + + // Don't inline huge string, just insert placeholder + original_file_content_b64 = "".to_string(); + } else { + original_file_content_b64 = get_base64_file_content(path.clone()).await? + } let code = formatdoc! { r#" @@ -162,16 +188,6 @@ async fn static_route_source(mode: NextMode, path: FileSystemPath) -> Result {file_size_limit}) {{ - throw new Error('File size for {img_name} image {path} exceeds {file_size_limit}MB. ' + - `(Current: ${{fileSizeInMB.toFixed(2)}}MB)\n` + - 'Read more: https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image#image-files-jpg-png-gif' - ) - }} - }} - export function GET() {{ return new NextResponse(buffer, {{ headers: {{ @@ -186,11 +202,6 @@ async fn static_route_source(mode: NextMode, path: FileSystemPath) -> Result Result IssueSeverity { + IssueSeverity::Error + } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text(rcstr!("Static metadata file size exceeded")).cell() + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { + IssueStage::ProcessModule.into() + } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { + self.path.clone().cell() + } + + #[turbo_tasks::function] + async fn description(&self) -> Result> { + Ok(Vc::cell(Some( + StyledString::Text( + format!( + "File size for {} image {} exceeds {}MB. (Current: {}MB)", + self.img_name, + self.path.value_to_string().await?, + self.file_size_limit_mb, + self.file_size_mb, + ) + .into(), + ) + .resolved_cell(), + ))) + } + + #[turbo_tasks::function] + fn documentation_link(&self) -> Vc { + Vc::cell(rcstr!( + "https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image#image-files-jpg-png-gif" + )) + } +} diff --git a/test/production/app-dir/metadata-img-too-large/opengraph-image/index.test.ts b/test/production/app-dir/metadata-img-too-large/opengraph-image/index.test.ts index 5005f734c8905..f940b64d569a8 100644 --- a/test/production/app-dir/metadata-img-too-large/opengraph-image/index.test.ts +++ b/test/production/app-dir/metadata-img-too-large/opengraph-image/index.test.ts @@ -14,8 +14,8 @@ describe('app-dir - metadata-img-too-large opengraph-image', () => { await next.build() const regex = isTurbopack - ? // in Turbopack, the path is simplified as [project]/... - /Error: File size for Open Graph image "\[project\]\/app\/opengraph-image\.png" exceeds 8MB/ + ? // in Turbopack, the path is simplified as [project]/.... It's also thrown earlier, so the prefix is slightly different. + /File size for Open Graph image "\[project\]\/app\/opengraph-image\.png" exceeds 8MB/ : /Error: File size for Open Graph image ".*\/app\/opengraph-image\.png" exceeds 8MB/ expect(next.cliOutput).toMatch(regex) diff --git a/test/production/app-dir/metadata-img-too-large/twitter-image/index.test.ts b/test/production/app-dir/metadata-img-too-large/twitter-image/index.test.ts index 6484a2437c5d2..07dc470a5c628 100644 --- a/test/production/app-dir/metadata-img-too-large/twitter-image/index.test.ts +++ b/test/production/app-dir/metadata-img-too-large/twitter-image/index.test.ts @@ -14,8 +14,8 @@ describe('app-dir - metadata-img-too-large twitter-image', () => { await next.build() const regex = isTurbopack - ? // in Turbopack, the path is simplified as [project]/... - /Error: File size for Twitter image "\[project\]\/app\/twitter-image\.png" exceeds 5MB/ + ? // in Turbopack, the path is simplified as [project]/.... It's also thrown earlier, so the prefix is slightly different. + /File size for Twitter image "\[project\]\/app\/twitter-image\.png" exceeds 5MB/ : /Error: File size for Twitter image ".*\/app\/twitter-image\.png" exceeds 5MB/ expect(next.cliOutput).toMatch(regex) From 257675e853a18139b40762b8895b4620763aae14 Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Fri, 22 Aug 2025 17:28:18 +0200 Subject: [PATCH 2/2] better unit handling --- crates/next-core/src/next_app/metadata/route.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/next-core/src/next_app/metadata/route.rs b/crates/next-core/src/next_app/metadata/route.rs index e1cca66da1751..9b9796de75334 100644 --- a/crates/next-core/src/next_app/metadata/route.rs +++ b/crates/next-core/src/next_app/metadata/route.rs @@ -158,8 +158,8 @@ async fn static_route_source(mode: NextMode, path: FileSystemPath) -> Result file_size_limit_mb + && let file_size = content.content().to_bytes().len() + && file_size > (file_size_limit_mb * 1024 * 1024) { StaticMetadataFileSizeIssue { img_name: if is_twitter { @@ -169,7 +169,7 @@ async fn static_route_source(mode: NextMode, path: FileSystemPath) -> Result Result