Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix tree shaking for image generation module #51950

Merged
merged 5 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion packages/next/src/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2022,6 +2022,16 @@ export default async function getBaseWebpackConfig(
} as any,
]
: []),
...(hasAppDir
? [
{
resourceQuery: new RegExp(
WEBPACK_RESOURCE_QUERIES.metadataRoute
),
layer: WEBPACK_LAYERS.metadataImage,
},
]
: []),
...(hasAppDir && isEdgeServer
? [
// The Edge bundle includes the server in its entrypoint, so it has to
Expand Down Expand Up @@ -2181,7 +2191,11 @@ export default async function getBaseWebpackConfig(
issuer: { not: regexLikeCss },
dependency: { not: ['url'] },
resourceQuery: {
not: [new RegExp(WEBPACK_RESOURCE_QUERIES.metadata)],
not: [
new RegExp(WEBPACK_RESOURCE_QUERIES.metadata),
new RegExp(WEBPACK_RESOURCE_QUERIES.metadataRoute),
new RegExp(WEBPACK_RESOURCE_QUERIES.metadataImageMeta),
],
},
options: {
isDev: dev,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export async function createStaticMetadataFromRoute(
basePath,
pageExtensions,
}
// WEBPACK_RESOURCE_QUERIES.metadata query here only for filtering out applying to image loader
)}!${filepath}?${WEBPACK_RESOURCE_QUERIES.metadata}`

const imageModule = `(async (props) => (await import(/* webpackMode: "eager" */ ${JSON.stringify(
Expand Down
8 changes: 6 additions & 2 deletions packages/next/src/build/webpack/loaders/next-app-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { RouteKind } from '../../../server/future/route-kind'
import { AppRouteRouteModuleOptions } from '../../../server/future/route-modules/app-route/module'
import { AppBundlePathNormalizer } from '../../../server/future/normalizers/built/app/app-bundle-path-normalizer'
import { MiddlewareConfig } from '../../analysis/get-page-static-info'
import { getFilenameAndExtension } from './next-metadata-route-loader'

export type AppLoaderOptions = {
name: string
Expand Down Expand Up @@ -105,10 +106,13 @@ async function createAppRouteCode({
// the route to ensure that the route is generated.
const filename = path.parse(resolvedPagePath).name
if (isMetadataRoute(name) && filename !== 'route') {
const { ext } = getFilenameAndExtension(resolvedPagePath)
const isDynamic = pageExtensions.includes(ext)

resolvedPagePath = `next-metadata-route-loader?${stringify({
page,
pageExtensions,
})}!${resolvedPagePath + '?' + WEBPACK_RESOURCE_QUERIES.metadata}`
isDynamic: isDynamic ? '1' : '0',
})}!${resolvedPagePath}${`?${WEBPACK_RESOURCE_QUERIES.metadataRoute}`}`
}

// References the route handler file to load found in `./routes/${kind}.ts`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ const EdgeAppRouteLoader: webpack.LoaderDefinitionFunction<EdgeAppRouteLoaderQue
const modulePath = `${appDirLoader}${stringifiedPagePath.substring(
1,
stringifiedPagePath.length - 1
)}?${WEBPACK_RESOURCE_QUERIES.edgeSSREntry}&${
WEBPACK_RESOURCE_QUERIES.metadata
}`
)}?${WEBPACK_RESOURCE_QUERIES.edgeSSREntry}`

return `
import { EdgeRouteModuleWrapper } from 'next/dist/esm/server/web/edge-route-module-wrapper'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ async function nextMetadataImageLoader(this: any, content: Buffer) {
.map((dep: any) => {
return dep.name
}) || []

// re-export and spread as `exportedImageData` to avoid non-exported error
return `\
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type webpack from 'webpack'
import fs from 'fs'
import path from 'path'
import { imageExtMimeTypeMap } from '../../../lib/mime-type'
import { WEBPACK_RESOURCE_QUERIES } from '../../../lib/constants'

const cacheHeader = {
none: 'no-cache, no-store',
Expand All @@ -12,10 +11,10 @@ const cacheHeader = {

type MetadataRouteLoaderOptions = {
page: string
pageExtensions: string[]
isDynamic: '1' | '0'
}

function getFilenameAndExtension(resourcePath: string) {
export function getFilenameAndExtension(resourcePath: string) {
const filename = path.basename(resourcePath)
const [name, ext] = filename.split('.')
return { name, ext }
Expand Down Expand Up @@ -49,11 +48,7 @@ import { NextResponse } from 'next/server'

const contentType = ${JSON.stringify(getContentType(resourcePath))}
const buffer = Buffer.from(${JSON.stringify(
(
await fs.promises.readFile(
resourcePath.replace('?' + WEBPACK_RESOURCE_QUERIES.metadata, '')
)
).toString('base64')
(await fs.promises.readFile(resourcePath)).toString('base64')
)}, 'base64'
)

Expand Down Expand Up @@ -205,13 +200,11 @@ ${staticGenerationCode}
const nextMetadataRouterLoader: webpack.LoaderDefinitionFunction<MetadataRouteLoaderOptions> =
async function () {
const { resourcePath } = this
const { pageExtensions, page } = this.getOptions()

const { name: fileBaseName, ext } = getFilenameAndExtension(resourcePath)
const isDynamic = pageExtensions.includes(ext)
const { page, isDynamic } = this.getOptions()
const { name: fileBaseName } = getFilenameAndExtension(resourcePath)

let code = ''
if (isDynamic) {
if (isDynamic === '1') {
if (fileBaseName === 'robots' || fileBaseName === 'manifest') {
code = getDynamicTextRouteCode(resourcePath)
} else if (fileBaseName === 'sitemap') {
Expand Down
2 changes: 2 additions & 0 deletions packages/next/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,12 @@ export const WEBPACK_LAYERS = {
middleware: 'middleware',
edgeAsset: 'edge-asset',
appClient: 'app-client',
metadataImage: 'app-metadata-image',
}

export const WEBPACK_RESOURCE_QUERIES = {
edgeSSREntry: '__next_edge_ssr_entry__',
metadata: '__next_metadata__',
metadataRoute: '__next_metadata_route__',
metadataImageMeta: '__next_metadata_image_meta__',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const alt = 'Open Graph Edge'

export const runtime = 'edge'

export { default } from '../og'
11 changes: 11 additions & 0 deletions test/e2e/app-dir/metadata-edge/app/another/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'

export default function Page() {
return <>hello another</>
}

export const metadata = {
title: 'another page',
}

export const runtime = 'edge'
21 changes: 21 additions & 0 deletions test/e2e/app-dir/metadata-edge/app/og.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ImageResponse } from 'next/server'

export default function og() {
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: 128,
background: 'lavender',
}}
>
Open Graph
</div>
)
)
}
22 changes: 1 addition & 21 deletions test/e2e/app-dir/metadata-edge/app/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
import { ImageResponse } from 'next/server'

export const alt = 'Open Graph'

export default function og() {
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: 128,
background: 'lavender',
}}
>
Open Graph
</div>
)
)
}
export { default } from './og'
9 changes: 6 additions & 3 deletions test/e2e/app-dir/metadata-edge/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ createNextDescribe(
describe('OG image route', () => {
if (isNextStart) {
it('should not bundle `ImageResponse` into the page worker', async () => {
const pageBundle = await next.readFile(
'.next/server/middleware-manifest.json'
)
const pageBundle = await next.readFile('.next/server/app/page.js')
expect(pageBundle).not.toContain('ImageResponse')

const sharedPageBundle = await next.readFile(
'.next/server/app/another/page.js'
)
expect(sharedPageBundle).not.toContain('ImageResponse')
})
}
})
Expand Down