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

Alias next public api to esm on edge runtime #42709

Merged
merged 4 commits into from Nov 10, 2022
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
2 changes: 1 addition & 1 deletion packages/next/build/entries.ts
Expand Up @@ -207,7 +207,7 @@ export function getEdgeServerEntry(opts: {
// The Edge bundle includes the server in its entrypoint, so it has to
// be in the SSR layer — we later convert the page request to the RSC layer
// via a webpack rule.
layer: WEBPACK_LAYERS.client,
layer: opts.appDirLoader ? WEBPACK_LAYERS.client : undefined,
}
}

Expand Down
21 changes: 19 additions & 2 deletions packages/next/build/webpack-config.ts
Expand Up @@ -887,6 +887,21 @@ export default async function getBaseWebpackConfig(
'next/dist/client': 'next/dist/esm/client',
'next/dist/shared': 'next/dist/esm/shared',
'next/dist/pages': 'next/dist/esm/pages',
'next/dist/lib': 'next/dist/esm/lib',

// Alias the usage of next public APIs
[require.resolve('next/dist/client/link')]:
'next/dist/esm/client/link',
[require.resolve('next/dist/client/image')]:
'next/dist/esm/client/image',
[require.resolve('next/dist/client/script')]:
'next/dist/esm/client/script',
[require.resolve('next/dist/client/router')]:
'next/dist/esm/client/router',
[require.resolve('next/dist/shared/lib/head')]:
'next/dist/esm/shared/lib/head',
[require.resolve('next/dist/shared/lib/dynamic')]:
'next/dist/esm/shared/lib/dynamic',
}
: undefined),

Expand Down Expand Up @@ -1128,7 +1143,7 @@ export default async function getBaseWebpackConfig(
// Treat next internals as non-external for server layer
layer === WEBPACK_LAYERS.server
? false
: /next[/\\]dist[/\\](shared|server)[/\\](?!lib[/\\](router[/\\]router|dynamic))/.test(
: /next[/\\]dist[/\\](esm[\\/])?(shared|server)[/\\](?!lib[/\\](router[/\\]router|dynamic))/.test(
localRes
)

Expand Down Expand Up @@ -1194,7 +1209,9 @@ export default async function getBaseWebpackConfig(
const externalType = isEsm ? 'module' : 'commonjs'

if (
/next[/\\]dist[/\\]shared[/\\](?!lib[/\\]router[/\\]router)/.test(res) ||
/next[/\\]dist[/\\](esm[\\/])?shared[/\\](?!lib[/\\]router[/\\]router)/.test(
res
) ||
/next[/\\]dist[/\\]compiled[/\\].*\.[mc]?js$/.test(res)
) {
return `${externalType} ${request}`
Expand Down
23 changes: 12 additions & 11 deletions packages/next/build/webpack/loaders/next-edge-ssr-loader/index.ts
Expand Up @@ -97,28 +97,29 @@ export default async function edgeSSRLoader(this: any) {
${
isAppDir
? `
import { renderToHTMLOrFlight as appRenderToHTML } from 'next/dist/esm/server/app-render'
import * as pageMod from ${JSON.stringify(pageModPath)}
const Document = null
const appRenderToHTML = require('next/dist/esm/server/app-render').renderToHTMLOrFlight
const pagesRenderToHTML = null
const pageMod = require(${JSON.stringify(pageModPath)})
const appMod = null
const errorMod = null
const error500Mod = null
`
: `
const Document = require(${stringifiedDocumentPath}).default
const appRenderToHTML = null
const pagesRenderToHTML = require('next/dist/esm/server/render').renderToHTML
const pageMod = require(${stringifiedPagePath})
const appMod = require(${stringifiedAppPath})
const errorMod = require(${stringifiedErrorPath})
const error500Mod = ${
stringified500Path ? `require(${stringified500Path})` : 'null'
import Document from ${stringifiedDocumentPath}
import { renderToHTML as pagesRenderToHTML } from 'next/dist/esm/server/render'
import * as pageMod from ${stringifiedPagePath}
import * as appMod from ${stringifiedAppPath}
import * as errorMod from ${stringifiedErrorPath}
${
stringified500Path
? `import * as error500Mod from ${stringified500Path}`
: `const error500Mod = null`
}
const appRenderToHTML = null
`
}


const buildManifest = self.__BUILD_MANIFEST
const reactLoadableManifest = self.__REACT_LOADABLE_MANIFEST
const rscManifest = self.__RSC_MANIFEST
Expand Down
2 changes: 1 addition & 1 deletion packages/next/client/dev/error-overlay/hot-dev-client.js
Expand Up @@ -119,7 +119,7 @@ function handleWarnings(warnings) {
})

if (typeof console !== 'undefined' && typeof console.warn === 'function') {
for (let i = 0; i < formatted.warnings.length; i++) {
for (let i = 0; i < formatted.warnings?.length; i++) {
if (i === 5) {
console.warn(
'There were more warnings in other files.\n' +
Expand Down
6 changes: 3 additions & 3 deletions packages/next/client/image.tsx
Expand Up @@ -10,12 +10,12 @@ import React, {
} from 'react'
import Head from '../shared/lib/head'
import { getImageBlurSvg } from '../shared/lib/image-blur-svg'
import {
import type {
ImageConfigComplete,
imageConfigDefault,
ImageLoaderProps,
ImageLoaderPropsWithConfig,
} from '../shared/lib/image-config'
import { imageConfigDefault } from '../shared/lib/image-config'
import { ImageConfigContext } from '../shared/lib/image-config-context'
import { warnOnce } from '../shared/lib/utils/warn-once'
// @ts-ignore - This is replaced by webpack alias
Expand All @@ -36,7 +36,7 @@ const VALID_LOADING_VALUES = ['lazy', 'eager', undefined] as const
type LoadingValue = typeof VALID_LOADING_VALUES[number]
type ImageConfig = ImageConfigComplete & { allSizes: number[] }

export { ImageLoaderProps }
export type { ImageLoaderProps }
export type ImageLoader = (p: ImageLoaderProps) => string

// Do not export - this is an internal type only
Expand Down
5 changes: 1 addition & 4 deletions packages/next/script.js
@@ -1,4 +1 @@
module.exports =
process.env.NEXT_RUNTIME === 'edge'
? require('./dist/esm/client/script')
: require('./dist/client/script')
module.exports = require('./dist/client/script')
3 changes: 3 additions & 0 deletions test/e2e/prerender.test.ts
Expand Up @@ -2072,6 +2072,9 @@ describe('Prerender', () => {
const { version, files } = JSON.parse(contents)
expect(version).toBe(1)

console.log(
check.tests.map((item) => files.some((file) => item.test(file)))
)
expect(
check.tests.every((item) => files.some((file) => item.test(file)))
).toBe(true)
Expand Down
5 changes: 5 additions & 0 deletions test/e2e/streaming-ssr/index.test.ts
Expand Up @@ -65,6 +65,11 @@ describe('react 18 streaming SSR with custom next configs', () => {
expect(html).toContain('home')
})

it('should render next/router correctly in edge runtime', async () => {
const html = await renderViaHTTP(next.url, '/router')
expect(html).toContain('link')
})

it('should render multi-byte characters correctly in streaming', async () => {
const html = await renderViaHTTP(next.url, '/multi-byte')
expect(html).toContain('マルチバイト'.repeat(28))
Expand Down
11 changes: 11 additions & 0 deletions test/e2e/streaming-ssr/streaming-ssr/pages/router.js
@@ -0,0 +1,11 @@
import { useRouter } from 'next/router'
import Link from 'next/link'

export default () => {
useRouter()
return <Link href="/">link</Link>
}

export const config = {
runtime: 'experimental-edge',
}