From ec5ba3184b69e2f6c6bdcc722464537449b9bd5b Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 6 Jun 2023 10:51:00 +0200 Subject: [PATCH] Shrink the react key size in metadata RSC payload (#50739) Follow up for #50678 as @gnoff commented in https://github.com/vercel/next.js/pull/50678#pullrequestreview-1457858336 Now metadata is shorter with the shorter key with just numbers ``` self.__next_f.push([1,"5:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"]) ``` --- .../next/src/lib/metadata/generate/basic.tsx | 29 +++++++---------- .../next/src/lib/metadata/generate/icons.tsx | 2 +- .../next/src/lib/metadata/generate/meta.tsx | 32 ++++++++++--------- .../src/lib/metadata/generate/opengraph.tsx | 4 +-- packages/next/src/lib/metadata/metadata.tsx | 9 ++++-- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/packages/next/src/lib/metadata/generate/basic.tsx b/packages/next/src/lib/metadata/generate/basic.tsx index 0360d246a9179..4456826ae2cf2 100644 --- a/packages/next/src/lib/metadata/generate/basic.tsx +++ b/packages/next/src/lib/metadata/generate/basic.tsx @@ -5,26 +5,22 @@ import { Meta, MetaFilter, MultiMeta } from './meta' export function BasicMetadata({ metadata }: { metadata: ResolvedMetadata }) { return MetaFilter([ - , + , metadata.title !== null && metadata.title.absolute ? ( - {metadata.title.absolute} + {metadata.title.absolute} ) : null, Meta({ name: 'description', content: metadata.description }), Meta({ name: 'application-name', content: metadata.applicationName }), ...(metadata.authors - ? metadata.authors.map((author, index) => [ + ? metadata.authors.map((author) => [ author.url ? ( - + ) : null, Meta({ name: 'author', content: author.name }), ]) : []), metadata.manifest ? ( - + ) : null, Meta({ name: 'generator', content: metadata.generator }), Meta({ name: 'keywords', content: metadata.keywords?.join(',') }), @@ -47,17 +43,15 @@ export function BasicMetadata({ metadata }: { metadata: ResolvedMetadata }) { Meta({ name: 'abstract', content: metadata.abstract }), ...(metadata.archives ? metadata.archives.map((archive) => ( - + )) : []), ...(metadata.assets - ? metadata.assets.map((asset) => ( - - )) + ? metadata.assets.map((asset) => ) : []), ...(metadata.bookmarks ? metadata.bookmarks.map((bookmark) => ( - + )) : []), Meta({ name: 'category', content: metadata.category }), @@ -120,16 +114,15 @@ export function AppleWebAppMeta({ ? Meta({ name: 'apple-mobile-web-app-capable', content: 'yes' }) : null, Meta({ name: 'apple-mobile-web-app-title', content: title }), - ...(startupImage - ? startupImage.map((image, index) => ( + startupImage + ? startupImage.map((image) => ( )) - : []), + : null, statusBarStyle ? Meta({ name: 'apple-mobile-web-app-status-bar-style', diff --git a/packages/next/src/lib/metadata/generate/icons.tsx b/packages/next/src/lib/metadata/generate/icons.tsx index 3d854dc4eb491..788698ebca8fa 100644 --- a/packages/next/src/lib/metadata/generate/icons.tsx +++ b/packages/next/src/lib/metadata/generate/icons.tsx @@ -13,7 +13,7 @@ function IconDescriptorLink({ icon }: { icon: IconDescriptor }) { function IconLink({ rel, icon }: { rel?: string; icon: Icon }) { if (typeof icon === 'object' && !(icon instanceof URL)) { if (!icon.rel && rel) icon.rel = rel - return + return IconDescriptorLink({ icon }) } else { const href = icon.toString() return diff --git a/packages/next/src/lib/metadata/generate/meta.tsx b/packages/next/src/lib/metadata/generate/meta.tsx index c234e058fc6b1..96394bc7b008a 100644 --- a/packages/next/src/lib/metadata/generate/meta.tsx +++ b/packages/next/src/lib/metadata/generate/meta.tsx @@ -15,7 +15,6 @@ export function Meta({ if (typeof content !== 'undefined' && content !== null && content !== '') { return ( ( items: (T | null)[] ): NonNullable[] { - return items.filter( - (item): item is NonNullable => - nonNullable(item) && !(Array.isArray(item) && item.length === 0) - ) + const acc: NonNullable[] = [] + for (const item of items) { + if (Array.isArray(item)) { + acc.push(...item.filter(nonNullable)) + } else if (nonNullable(item)) { + acc.push(item) + } + } + return acc } type ExtendMetaContent = Record< @@ -70,18 +74,16 @@ function ExtendMeta({ namePrefix?: string propertyPrefix?: string }) { - const keyPrefix = namePrefix || propertyPrefix if (!content) return null return MetaFilter( - Object.entries(content).map(([k, v], index) => { - return typeof v === 'undefined' ? null : ( - - ) + Object.entries(content).map(([k, v]) => { + return typeof v === 'undefined' + ? null + : Meta({ + ...(propertyPrefix && { property: getMetaKey(propertyPrefix, k) }), + ...(namePrefix && { name: getMetaKey(namePrefix, k) }), + content: typeof v === 'string' ? v : v?.toString(), + }) }) ) } diff --git a/packages/next/src/lib/metadata/generate/opengraph.tsx b/packages/next/src/lib/metadata/generate/opengraph.tsx index 0a2e660681d44..2a081bf2dd447 100644 --- a/packages/next/src/lib/metadata/generate/opengraph.tsx +++ b/packages/next/src/lib/metadata/generate/opengraph.tsx @@ -225,14 +225,14 @@ function TwitterAppItem({ app: TwitterAppDescriptor type: 'iphone' | 'ipad' | 'googleplay' }) { - return MetaFilter([ + return [ Meta({ name: `twitter:app:name:${type}`, content: app.name }), Meta({ name: `twitter:app:id:${type}`, content: app.id[type] }), Meta({ name: `twitter:app:url:${type}`, content: app.url?.[type]?.toString(), }), - ]) + ] } export function TwitterMetadata({ diff --git a/packages/next/src/lib/metadata/metadata.tsx b/packages/next/src/lib/metadata/metadata.tsx index 6ac790b30a728..2f086e24e9427 100644 --- a/packages/next/src/lib/metadata/metadata.tsx +++ b/packages/next/src/lib/metadata/metadata.tsx @@ -56,6 +56,11 @@ export async function MetadataTree({ IconsMetadata({ icons: metadata.icons }), ]) - // Wrap with fragment and key to skip react array-key warnings. - return <>{elements} + return ( + <> + {elements.map((el, index) => { + return React.cloneElement(el as React.ReactElement, { key: index }) + })} + + ) }