Skip to content

Commit 5ec3715

Browse files
committed
refactor metadata loaders
1 parent 79c16cb commit 5ec3715

File tree

2 files changed

+87
-59
lines changed

2 files changed

+87
-59
lines changed

packages/next/src/build/webpack/loaders/next-metadata-image-loader.ts

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,41 +83,40 @@ async function nextMetadataImageLoader(
8383
.join(',')}
8484
}
8585
86-
export default async function (props) {
87-
const { __metadata_id__: _, ...params } = await props.params
86+
async function getImageMetadata(imageMetadata, idParam, resolvedParams) {
8887
const imageUrl = fillMetadataSegment(${JSON.stringify(
8988
pathnamePrefix
90-
)}, params, ${JSON.stringify(pageSegment)})
91-
92-
const { generateImageMetadata } = imageModule
93-
94-
function getImageMetadata(imageMetadata, idParam) {
95-
const data = {
96-
alt: imageMetadata.alt,
97-
type: imageMetadata.contentType || 'image/png',
98-
url: imageUrl + (idParam ? ('/' + idParam) : '') + ${JSON.stringify(
99-
hashQuery
100-
)},
101-
}
102-
const { size } = imageMetadata
103-
if (size) {
104-
${
105-
type === 'twitter' || type === 'openGraph'
106-
? 'data.width = size.width; data.height = size.height;'
107-
: 'data.sizes = size.width + "x" + size.height;'
108-
}
89+
)}, resolvedParams, ${JSON.stringify(pageSegment)})
90+
const data = {
91+
alt: imageMetadata.alt,
92+
type: imageMetadata.contentType || 'image/png',
93+
url: imageUrl + (idParam ? ('/' + idParam) : '') + ${JSON.stringify(
94+
hashQuery
95+
)},
96+
}
97+
const { size } = imageMetadata
98+
if (size) {
99+
${
100+
type === 'twitter' || type === 'openGraph'
101+
? 'data.width = size.width; data.height = size.height;'
102+
: 'data.sizes = size.width + "x" + size.height;'
109103
}
110-
return data
111104
}
105+
return data
106+
}
107+
108+
export default async function (props) {
109+
const { generateImageMetadata } = imageModule
110+
const resolvedParams = await props.params
112111
113112
if (generateImageMetadata) {
114-
const imageMetadataArray = await generateImageMetadata({ params })
115-
return imageMetadataArray.map((imageMetadata, index) => {
116-
const idParam = (imageMetadata.id || index) + ''
117-
return getImageMetadata(imageMetadata, idParam)
118-
})
113+
const imageMetadataArray = await generateImageMetadata({ params: resolvedParams })
114+
return Promise.all(imageMetadataArray.map(async (imageMetadata, index) => {
115+
const idParam = imageMetadata.id || index.toString()
116+
return await getImageMetadata(imageMetadata, idParam, resolvedParams)
117+
}))
119118
} else {
120-
return [getImageMetadata(imageModule, '')]
119+
return [await getImageMetadata(imageModule, '', resolvedParams)]
121120
}
122121
}`
123122
}

packages/next/src/build/webpack/loaders/next-metadata-route-loader.ts

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,12 @@ export async function GET() {
153153
`
154154
}
155155

156-
// <metadata-image>/[id]/route.js
157156
async function getDynamicImageRouteCode(
158157
resourcePath: string,
159158
loaderContext: webpack.LoaderContext<any>
160159
) {
161160
return `\
162-
/* dynamic image route */
161+
/* dynamic image route with generateImageMetadata */
163162
import { NextResponse } from 'next/server'
164163
import * as userland from ${JSON.stringify(resourcePath)}
165164
@@ -175,31 +174,63 @@ export async function GET(_, ctx) {
175174
const params = await ctx.params
176175
const { __metadata_id__, ...rest } = params || {}
177176
const restParams = params ? rest : undefined
178-
const targetId = __metadata_id__
179-
let id = undefined
180-
181-
if (generateImageMetadata) {
182-
const imageMetadata = await generateImageMetadata({ params: restParams })
183-
id = imageMetadata.find((item) => {
184-
if (process.env.NODE_ENV !== 'production') {
185-
if (item?.id == null) {
186-
throw new Error('id property is required for every item returned from generateImageMetadata')
187-
}
177+
const imageMetadata = await generateImageMetadata({ params: restParams })
178+
const id = imageMetadata.find((item) => {
179+
if (process.env.NODE_ENV !== 'production') {
180+
if (item?.id == null) {
181+
throw new Error('id property is required for every item returned from generateImageMetadata')
188182
}
189-
return item.id.toString() === targetId
190-
})?.id
191-
if (id == null) {
192-
return new NextResponse('Not Found', {
193-
status: 404,
194-
})
195183
}
184+
return item.id.toString() === __metadata_id__
185+
})?.id
186+
if (id == null) {
187+
return new NextResponse('Not Found', {
188+
status: 404,
189+
})
196190
}
197191
198-
return handler({ params: restParams, id })
192+
return handler({ params: ctx.params })
199193
}
200194
`
201195
}
202196

197+
async function getSingleImageRouteCode(
198+
resourcePath: string,
199+
loaderContext: webpack.LoaderContext<any>
200+
) {
201+
return `\
202+
/* dynamic image route without generateImageMetadata */
203+
import { NextResponse } from 'next/server'
204+
import { default as handler } from ${JSON.stringify(resourcePath)}
205+
206+
${errorOnBadHandler(resourcePath)}
207+
${await createReExportsCode(resourcePath, loaderContext)}
208+
209+
export async function GET(_, ctx) {
210+
return handler({ params: await ctx.params })
211+
}
212+
`
213+
}
214+
215+
// <metadata-image>/[id]/route.js
216+
async function getImageRouteCode(
217+
resourcePath: string,
218+
loaderContext: webpack.LoaderContext<any>
219+
) {
220+
const exportNames = await getLoaderModuleNamedExports(
221+
resourcePath,
222+
loaderContext
223+
)
224+
225+
const hasGenerateImageMetadata = exportNames.includes('generateImageMetadata')
226+
227+
if (hasGenerateImageMetadata) {
228+
return getDynamicImageRouteCode(resourcePath, loaderContext)
229+
} else {
230+
return getSingleImageRouteCode(resourcePath, loaderContext)
231+
}
232+
}
233+
203234
async function getDynamicSitemapRouteCode(
204235
resourcePath: string,
205236
loaderContext: webpack.LoaderContext<any>
@@ -242,16 +273,16 @@ ${errorOnBadHandler(resourcePath)}
242273
${await createReExportsCode(resourcePath, loaderContext)}
243274
244275
export async function GET(_, ctx) {
245-
const { __metadata_id__: id, ...params } = await ctx.params || {}
246-
const hasXmlExtension = id ? id.endsWith('.xml') : false
247-
248-
if (id && !hasXmlExtension) {
249-
return new NextResponse('Not Found', {
250-
status: 404,
251-
})
252-
}
253-
276+
let targetId
254277
if (process.env.NODE_ENV !== 'production' && sitemapModule.generateSitemaps) {
278+
const { __metadata_id__: id, ...params } = await ctx.params || {}
279+
const hasXmlExtension = id ? id.endsWith('.xml') : false
280+
if (id && !hasXmlExtension) {
281+
return new NextResponse('Not Found', {
282+
status: 404,
283+
})
284+
}
285+
targetId = id && hasXmlExtension ? id.slice(0, -4) : undefined
255286
const sitemaps = await sitemapModule.generateSitemaps()
256287
for (const item of sitemaps) {
257288
if (item?.id == null) {
@@ -260,8 +291,6 @@ export async function GET(_, ctx) {
260291
}
261292
}
262293
263-
const targetId = id && hasXmlExtension ? id.slice(0, -4) : undefined
264-
265294
const data = await handler({ id: targetId })
266295
const content = resolveRouteData(data, fileType)
267296
@@ -293,7 +322,7 @@ const nextMetadataRouterLoader: webpack.LoaderDefinitionFunction<MetadataRouteLo
293322
} else if (fileBaseName === 'sitemap') {
294323
code = await getDynamicSitemapRouteCode(filePath, this)
295324
} else {
296-
code = await getDynamicImageRouteCode(filePath, this)
325+
code = await getImageRouteCode(filePath, this)
297326
}
298327
} else {
299328
code = await getStaticAssetRouteCode(filePath, fileBaseName)

0 commit comments

Comments
 (0)