Skip to content

Commit

Permalink
Add @vercel/og to external server packages (vercel#49944)
Browse files Browse the repository at this point in the history
`@vercel/og` should also be treated as external package as precompiled one (x-ref: vercel#48844)

As it's ESModule, it could escalate the importee modules to become ESM as well, then `require()` won't be able to load the proper module, we need to switch to await the require result (just like **dynamic import**) for node module loader

[slack thread](https://vercel.slack.com/archives/C03KAR5DCKC/p1683577269970609?thread_ts=1683569728.697039&cid=C03KAR5DCKC)
  • Loading branch information
huozhi authored and hydRAnger committed Jun 12, 2023
1 parent c60dfb0 commit 7e0f4e4
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 9 deletions.
4 changes: 3 additions & 1 deletion packages/next/src/export/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,9 @@ export default async function exportPage({
const filename = posix.join(distDir, 'server', 'app', page)

// Load the module for the route.
const module = RouteModuleLoader.load<AppRouteRouteModule>(filename)
const module = await RouteModuleLoader.load<AppRouteRouteModule>(
filename
)

// Call the handler with the request and context from the module.
const response = await module.handle(request, context)
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/lib/server-external-packages.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[
"@prisma/client",
"@vercel/og",
"@sentry/nextjs",
"@sentry/node",
"@swc/core",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
* Loads a given module for a given ID.
*/
export interface ModuleLoader {
load<M = any>(id: string): M
load<M = any>(id: string): Promise<M>
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ModuleLoader } from './module-loader'

/**
* Loads a module using `require(id)`.
* Loads a module using `await require(id)`.
*/
export class NodeModuleLoader implements ModuleLoader {
public load<M>(id: string): M {
public async load<M>(id: string): Promise<M> {
if (process.env.NEXT_RUNTIME !== 'edge') {
return require(id)
// Need to `await` to cover the case that route is marked ESM modules by ESM escalation.
return await require(id)
}

throw new Error('NodeModuleLoader is not supported in edge runtime.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ export interface AppLoaderModule<M extends RouteModule = RouteModule> {
}

export class RouteModuleLoader {
static load<M extends RouteModule>(
static async load<M extends RouteModule>(
id: string,
loader: ModuleLoader = new NodeModuleLoader()
): M {
): Promise<M> {
if (process.env.NEXT_RUNTIME !== 'edge') {
const { routeModule }: AppLoaderModule<M> = loader.load(id)
const { routeModule }: AppLoaderModule<M> = await loader.load(id)

return routeModule
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class RouteHandlerManager {
context: RouteHandlerManagerContext
): Promise<Response | undefined> {
// The module supports minimal mode, load the minimal module.
const module = RouteModuleLoader.load<RouteModule>(
const module = await RouteModuleLoader.load<RouteModule>(
match.definition.filename,
this.moduleLoader
)
Expand Down

0 comments on commit 7e0f4e4

Please sign in to comment.