rsnext/packages
Shu Ding 0dd0ef226c
Fix tree-shaking for metadata image functions on the Edge runtime (#51762)
This PR fixes tree-shaking for the metadata image generation module
(e.g. `opengraph-image.js` and other conventions) when the page has
`runtime = 'edge'`.

## Details

The first step of this fix is to change this from the loader:

```js
import * as exported from "./opengraph-image.js"
```

to be necessary fields only (so the `default` export can potentially be
removed):

```js
import { alt, size } from "./opengraph-image.js"
```

To know which fields are exported, we need to load the module first via
Webpack loader's `loadModule` API and check its
`HarmonyExportSpecifierDependency` dependencies.

This is the first step to make it tree-shakable. Since we have
`./opengraph-image.js` used in another entry, the actual image API route
`opengraph-image/route.js`:

```js
import * as image from "./opengraph-image.js"
```

Webpack still treats both as the same module and generates one chunk for
it. We want to "fork" it into two modules. The technique here is to add
a noop resource query and make it:

```js
import { alt, size } from "./opengraph-image.js?__next_metadata_image_meta__"
```

So it won't be shared in the chunk (as it's a different request), and
can be concatenated inline.

However that's not enough, the inlined result will still have all
imports from our `opengraph-image.js`, including `import { ImageResponse
} from 'next/server'`. Because we can't simply add `"sideEffects":
false` in Next.js' package.json, we need a way to mark this import as
side-effect free. I went through
https://github.com/webpack/webpack/blob/main/lib/optimize/SideEffectsFlagPlugin.js
and used the same method to mark that module with
`module.factoryMeta.sideEffectFree = true`.

With all these added, the page bundle will no longer contain the
`ImageResponse` instance.

## Result

The difference is quite amazing, for the new added test (an empty Edge
runtime page with an opengrah image file) here're the before/after
metrics for the `page.js` server bundle:

Edge bundle size: 892kB → 500kB.
Build time: 26.792s → 8.830s.
2023-06-26 13:44:29 +02:00
..
create-next-app v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
eslint-config-next v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
eslint-plugin-next v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
font v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next Fix tree-shaking for metadata image functions on the Edge runtime (#51762) 2023-06-26 13:44:29 +02:00
next-bundle-analyzer v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next-codemod v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next-env v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next-mdx v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next-plugin-storybook v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next-polyfill-module v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next-polyfill-nomodule v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
next-swc revalidate should be more than a boolean (#51627) 2023-06-24 07:38:39 +00:00
react-dev-overlay v13.4.8-canary.2 2023-06-24 02:20:39 +00:00
react-refresh-utils v13.4.8-canary.2 2023-06-24 02:20:39 +00:00