Pick esm main fields and condition names first for RSC server layer (#50548)
For RSC server layer so far we bundle all dependencies, ESM format is the better one rather than CJS to analyze and tree-shake out the unused parts. This PR changes pick the condition names that are in ESM format first for server layer. Also fixes the misorder of condition names of edge runtime, `conditionNames` should only contain either ESM or CJS, previously the main fields are mixed with conditon names which is not expected for webpack, we separate them now. Since we're picking ESM instead CJS now, the error of require `exports * from` doesn't exist anymore, but if you're using a CJS dependency which require a ESM package, it will error. This is the existing behavior for our webpack configuration but could happen on server layer bundling Other related changes: * Imports are hoisted in ESM, so migrate`enhanceGlobals` to a imported module * Use `...` to pick the proper imports by import expression, and prefer the `react-server` / `edge-light` condition names for corresponding cases * Remove edge SSR duplicated `middleware` export checking
This commit is contained in:
parent
ea63e92e87
commit
a035224dc3
29 changed files with 989 additions and 789 deletions
|
@ -224,7 +224,7 @@
|
|||
"semver": "7.3.7",
|
||||
"shell-quote": "1.7.3",
|
||||
"strip-ansi": "6.0.0",
|
||||
"styled-components": "6.0.0-beta.5",
|
||||
"styled-components": "6.0.0-rc.3",
|
||||
"styled-jsx": "5.1.1",
|
||||
"styled-jsx-plugin-postcss": "3.0.2",
|
||||
"swr": "^2.0.0",
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { adapter, enhanceGlobals } from 'next/dist/server/web/adapter'
|
||||
import 'next/dist/server/web/globals'
|
||||
import { adapter } from 'next/dist/server/web/adapter'
|
||||
import { NAME, PAGE } from 'BOOTSTRAP_CONFIG'
|
||||
|
||||
enhanceGlobals()
|
||||
|
||||
var mod = require('ENTRY')
|
||||
var handler = mod.middleware || mod.default
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import crypto from 'crypto'
|
|||
import { webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
import path from 'path'
|
||||
import semver from 'next/dist/compiled/semver'
|
||||
|
||||
import { escapeStringRegexp } from '../shared/lib/escape-regexp'
|
||||
import {
|
||||
DOT_NEXT_ALIAS,
|
||||
|
@ -98,15 +99,23 @@ const reactPackagesRegex = /^(react|react-dom|react-server-dom-webpack)($|\/)/
|
|||
const asyncStoragesRegex =
|
||||
/next[\\/]dist[\\/]client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/
|
||||
|
||||
// exports.<conditionName>
|
||||
const edgeConditionNames = [
|
||||
'edge-light',
|
||||
'worker',
|
||||
// inherits the default conditions
|
||||
'...',
|
||||
]
|
||||
|
||||
// packageJson.<mainField>
|
||||
const mainFieldsPerCompiler: Record<CompilerNameValues, string[]> = {
|
||||
[COMPILER_NAMES.server]: ['main', 'module'],
|
||||
[COMPILER_NAMES.client]: ['browser', 'module', 'main'],
|
||||
[COMPILER_NAMES.edgeServer]: [
|
||||
'edge-light',
|
||||
'worker',
|
||||
'browser',
|
||||
'module',
|
||||
'main',
|
||||
// inherits the default conditions
|
||||
'...',
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -915,12 +924,9 @@ export default async function getBaseWebpackConfig(
|
|||
|
||||
const reactServerCondition = [
|
||||
'react-server',
|
||||
...mainFieldsPerCompiler[
|
||||
isEdgeServer ? COMPILER_NAMES.edgeServer : COMPILER_NAMES.server
|
||||
],
|
||||
'node',
|
||||
'import',
|
||||
'require',
|
||||
...(isEdgeServer ? edgeConditionNames : []),
|
||||
// inherits the default conditions
|
||||
'...',
|
||||
]
|
||||
|
||||
const clientEntries = isClient
|
||||
|
@ -1166,11 +1172,7 @@ export default async function getBaseWebpackConfig(
|
|||
: undefined),
|
||||
mainFields: mainFieldsPerCompiler[compilerType],
|
||||
...(isEdgeServer && {
|
||||
conditionNames: [
|
||||
...mainFieldsPerCompiler[COMPILER_NAMES.edgeServer],
|
||||
'import',
|
||||
'node',
|
||||
],
|
||||
conditionNames: edgeConditionNames,
|
||||
}),
|
||||
plugins: [],
|
||||
}
|
||||
|
|
|
@ -30,13 +30,11 @@ const nextEdgeFunctionLoader: webpack.LoaderDefinitionFunction<EdgeFunctionLoade
|
|||
buildInfo.rootDir = rootDir
|
||||
|
||||
return `
|
||||
import { adapter, enhanceGlobals } from 'next/dist/esm/server/web/adapter'
|
||||
import 'next/dist/esm/server/web/globals'
|
||||
import { adapter } from 'next/dist/esm/server/web/adapter'
|
||||
import { IncrementalCache } from 'next/dist/esm/server/lib/incremental-cache'
|
||||
|
||||
enhanceGlobals()
|
||||
|
||||
const mod = require(${stringifiedPagePath})
|
||||
const handler = mod.middleware || mod.default
|
||||
import handler from ${stringifiedPagePath}
|
||||
|
||||
if (typeof handler !== 'function') {
|
||||
throw new Error('The Edge Function "pages${page}" must export a \`default\` function');
|
||||
|
|
|
@ -99,12 +99,11 @@ const edgeSSRLoader: webpack.LoaderDefinitionFunction<EdgeSSRLoaderQuery> =
|
|||
)}${isAppDir ? `?${WEBPACK_RESOURCE_QUERIES.edgeSSREntry}` : ''}`
|
||||
|
||||
const transformed = `
|
||||
import { adapter, enhanceGlobals } from 'next/dist/esm/server/web/adapter'
|
||||
import 'next/dist/esm/server/web/globals'
|
||||
import { adapter } from 'next/dist/esm/server/web/adapter'
|
||||
import { getRender } from 'next/dist/esm/build/webpack/loaders/next-edge-ssr-loader/render'
|
||||
import { IncrementalCache } from 'next/dist/esm/server/lib/incremental-cache'
|
||||
|
||||
enhanceGlobals()
|
||||
|
||||
const pagesType = ${JSON.stringify(pagesType)}
|
||||
${
|
||||
isAppDir
|
||||
|
@ -132,10 +131,10 @@ const edgeSSRLoader: webpack.LoaderDefinitionFunction<EdgeSSRLoaderQuery> =
|
|||
`
|
||||
}
|
||||
|
||||
const incrementalCacheHandler = ${
|
||||
${
|
||||
incrementalCacheHandlerPath
|
||||
? `require("${incrementalCacheHandlerPath}")`
|
||||
: 'null'
|
||||
? `import incrementalCacheHandler from "${incrementalCacheHandlerPath}"`
|
||||
: 'const incrementalCacheHandler = null'
|
||||
}
|
||||
|
||||
const buildManifest = self.__BUILD_MANIFEST
|
||||
|
|
|
@ -40,12 +40,11 @@ export default function middlewareLoader(this: any) {
|
|||
buildInfo.rootDir = rootDir
|
||||
|
||||
return `
|
||||
import { adapter, enhanceGlobals } from 'next/dist/esm/server/web/adapter'
|
||||
import 'next/dist/esm/server/web/globals'
|
||||
import { adapter } from 'next/dist/esm/server/web/adapter'
|
||||
import * as mod from ${stringifiedPagePath}
|
||||
|
||||
enhanceGlobals()
|
||||
|
||||
var mod = require(${stringifiedPagePath})
|
||||
var handler = mod.middleware || mod.default;
|
||||
const handler = mod.middleware || mod.default
|
||||
|
||||
if (typeof handler !== 'function') {
|
||||
throw new Error('The Middleware "pages${page}" must export a \`middleware\` or a \`default\` function');
|
||||
|
@ -53,9 +52,9 @@ export default function middlewareLoader(this: any) {
|
|||
|
||||
export default function (opts) {
|
||||
return adapter({
|
||||
...opts,
|
||||
page: ${JSON.stringify(page)},
|
||||
handler,
|
||||
...opts,
|
||||
page: ${JSON.stringify(page)},
|
||||
handler,
|
||||
})
|
||||
}
|
||||
`
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1330,10 +1330,12 @@ export default class DevServer extends Server {
|
|||
if (isError(err) && err.stack) {
|
||||
try {
|
||||
const frames = parseStack(err.stack!)
|
||||
// Filter out internal edge related runtime stack
|
||||
const frame = frames.find(
|
||||
({ file }) =>
|
||||
!file?.startsWith('eval') &&
|
||||
!file?.includes('web/adapter') &&
|
||||
!file?.includes('web/globals') &&
|
||||
!file?.includes('sandbox/context') &&
|
||||
!file?.includes('<anonymous>')
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// This module will only be loaded once per process.
|
||||
|
||||
const { dirname } = require('path')
|
||||
const mod = require('module')
|
||||
const resolveFilename = mod._resolveFilename
|
||||
const hookPropertyMap = new Map()
|
||||
|
@ -20,9 +21,9 @@ export function addHookAliases(aliases: [string, string][] = []) {
|
|||
addHookAliases([
|
||||
// Use `require.resolve` explicitly to make them statically analyzable
|
||||
// styled-jsx needs to be resolved as the external dependency.
|
||||
['styled-jsx', require.resolve('styled-jsx')],
|
||||
['styled-jsx/style', require.resolve('styled-jsx/style')],
|
||||
['styled-jsx', dirname(require.resolve('styled-jsx/package.json'))],
|
||||
['styled-jsx/style', require.resolve('styled-jsx/style')],
|
||||
['zod', dirname(require.resolve('zod/package.json'))],
|
||||
])
|
||||
|
||||
// Override built-in React packages if necessary
|
||||
|
|
|
@ -17,8 +17,7 @@ import {
|
|||
RSC,
|
||||
} from '../../client/components/app-router-headers'
|
||||
import { NEXT_QUERY_PARAM_PREFIX } from '../../lib/constants'
|
||||
|
||||
declare const _ENTRIES: any
|
||||
import { ensureInstrumentationRegistered } from './globals'
|
||||
|
||||
class NextRequestHint extends NextRequest {
|
||||
sourcePage: string
|
||||
|
@ -59,29 +58,6 @@ export type AdapterOptions = {
|
|||
IncrementalCache?: typeof import('../lib/incremental-cache').IncrementalCache
|
||||
}
|
||||
|
||||
async function registerInstrumentation() {
|
||||
if (
|
||||
'_ENTRIES' in globalThis &&
|
||||
_ENTRIES.middleware_instrumentation &&
|
||||
_ENTRIES.middleware_instrumentation.register
|
||||
) {
|
||||
try {
|
||||
await _ENTRIES.middleware_instrumentation.register()
|
||||
} catch (err: any) {
|
||||
err.message = `An error occurred while loading instrumentation hook: ${err.message}`
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let registerInstrumentationPromise: Promise<void> | null = null
|
||||
function ensureInstrumentationRegistered() {
|
||||
if (!registerInstrumentationPromise) {
|
||||
registerInstrumentationPromise = registerInstrumentation()
|
||||
}
|
||||
return registerInstrumentationPromise
|
||||
}
|
||||
|
||||
export async function adapter(
|
||||
params: AdapterOptions
|
||||
): Promise<FetchEventResult> {
|
||||
|
@ -318,50 +294,3 @@ export async function adapter(
|
|||
waitUntil: Promise.all(event[waitUntilSymbol]),
|
||||
}
|
||||
}
|
||||
|
||||
function getUnsupportedModuleErrorMessage(module: string) {
|
||||
// warning: if you change these messages, you must adjust how react-dev-overlay's middleware detects modules not found
|
||||
return `The edge runtime does not support Node.js '${module}' module.
|
||||
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`
|
||||
}
|
||||
|
||||
function __import_unsupported(moduleName: string) {
|
||||
const proxy: any = new Proxy(function () {}, {
|
||||
get(_obj, prop) {
|
||||
if (prop === 'then') {
|
||||
return {}
|
||||
}
|
||||
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
|
||||
},
|
||||
construct() {
|
||||
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
|
||||
},
|
||||
apply(_target, _this, args) {
|
||||
if (typeof args[0] === 'function') {
|
||||
return args[0](proxy)
|
||||
}
|
||||
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
|
||||
},
|
||||
})
|
||||
return new Proxy({}, { get: () => proxy })
|
||||
}
|
||||
|
||||
export function enhanceGlobals() {
|
||||
// The condition is true when the "process" module is provided
|
||||
if (process !== global.process) {
|
||||
// prefer local process but global.process has correct "env"
|
||||
process.env = global.process.env
|
||||
global.process = process
|
||||
}
|
||||
|
||||
// to allow building code that import but does not use node.js modules,
|
||||
// webpack will expect this function to exist in global scope
|
||||
Object.defineProperty(globalThis, '__import_unsupported', {
|
||||
value: __import_unsupported,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
})
|
||||
|
||||
// Eagerly fire instrumentation hook to make the startup faster.
|
||||
void ensureInstrumentationRegistered()
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ import type { RouteDefinition } from '../future/route-definitions/route-definiti
|
|||
import type { RouteModule } from '../future/route-modules/route-module'
|
||||
import type { NextRequest } from './spec-extension/request'
|
||||
|
||||
import { adapter, enhanceGlobals, type AdapterOptions } from './adapter'
|
||||
import './globals'
|
||||
import { adapter, type AdapterOptions } from './adapter'
|
||||
import { IncrementalCache } from '../lib/incremental-cache'
|
||||
enhanceGlobals()
|
||||
|
||||
import { removeTrailingSlash } from '../../shared/lib/router/utils/remove-trailing-slash'
|
||||
import { RouteMatcher } from '../future/route-matchers/route-matcher'
|
||||
|
|
73
packages/next/src/server/web/globals.ts
Normal file
73
packages/next/src/server/web/globals.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
declare const _ENTRIES: any
|
||||
|
||||
async function registerInstrumentation() {
|
||||
if (
|
||||
'_ENTRIES' in globalThis &&
|
||||
_ENTRIES.middleware_instrumentation &&
|
||||
_ENTRIES.middleware_instrumentation.register
|
||||
) {
|
||||
try {
|
||||
await _ENTRIES.middleware_instrumentation.register()
|
||||
} catch (err: any) {
|
||||
err.message = `An error occurred while loading instrumentation hook: ${err.message}`
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let registerInstrumentationPromise: Promise<void> | null = null
|
||||
export function ensureInstrumentationRegistered() {
|
||||
if (!registerInstrumentationPromise) {
|
||||
registerInstrumentationPromise = registerInstrumentation()
|
||||
}
|
||||
return registerInstrumentationPromise
|
||||
}
|
||||
|
||||
function getUnsupportedModuleErrorMessage(module: string) {
|
||||
// warning: if you change these messages, you must adjust how react-dev-overlay's middleware detects modules not found
|
||||
return `The edge runtime does not support Node.js '${module}' module.
|
||||
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`
|
||||
}
|
||||
|
||||
function __import_unsupported(moduleName: string) {
|
||||
const proxy: any = new Proxy(function () {}, {
|
||||
get(_obj, prop) {
|
||||
if (prop === 'then') {
|
||||
return {}
|
||||
}
|
||||
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
|
||||
},
|
||||
construct() {
|
||||
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
|
||||
},
|
||||
apply(_target, _this, args) {
|
||||
if (typeof args[0] === 'function') {
|
||||
return args[0](proxy)
|
||||
}
|
||||
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
|
||||
},
|
||||
})
|
||||
return new Proxy({}, { get: () => proxy })
|
||||
}
|
||||
|
||||
function enhanceGlobals() {
|
||||
// The condition is true when the "process" module is provided
|
||||
if (process !== global.process) {
|
||||
// prefer local process but global.process has correct "env"
|
||||
process.env = global.process.env
|
||||
global.process = process
|
||||
}
|
||||
|
||||
// to allow building code that import but does not use node.js modules,
|
||||
// webpack will expect this function to exist in global scope
|
||||
Object.defineProperty(globalThis, '__import_unsupported', {
|
||||
value: __import_unsupported,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
})
|
||||
|
||||
// Eagerly fire instrumentation hook to make the startup faster.
|
||||
void ensureInstrumentationRegistered()
|
||||
}
|
||||
|
||||
enhanceGlobals()
|
|
@ -44,7 +44,7 @@ function withTaggedErrors(fn: RunnerFn): RunnerFn {
|
|||
})
|
||||
}
|
||||
|
||||
export const getRuntimeContext = async (params: {
|
||||
export async function getRuntimeContext(params: {
|
||||
name: string
|
||||
onWarning?: any
|
||||
useCache: boolean
|
||||
|
@ -52,7 +52,7 @@ export const getRuntimeContext = async (params: {
|
|||
distDir: string
|
||||
paths: string[]
|
||||
incrementalCache?: any
|
||||
}): Promise<EdgeRuntime<any>> => {
|
||||
}): Promise<EdgeRuntime<any>> {
|
||||
const { runtime, evaluateInContext } = await getModuleContext({
|
||||
moduleName: params.name,
|
||||
onWarning: params.onWarning ?? (() => {}),
|
||||
|
@ -71,7 +71,7 @@ export const getRuntimeContext = async (params: {
|
|||
return runtime
|
||||
}
|
||||
|
||||
export const run = withTaggedErrors(async (params) => {
|
||||
export const run = withTaggedErrors(async function runWithTaggedErrors(params) {
|
||||
const runtime = await getRuntimeContext(params)
|
||||
const subreq = params.request.headers[`x-middleware-subrequest`]
|
||||
const subrequests = typeof subreq === 'string' ? subreq.split(':') : []
|
||||
|
|
1396
pnpm-lock.yaml
1396
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -159,6 +159,12 @@ createNextDescribe(
|
|||
const v1 = html.match(/App React Version: ([^<]+)</)[1]
|
||||
const v2 = html.match(/External React Version: ([^<]+)</)[1]
|
||||
expect(v1).toBe(v2)
|
||||
|
||||
// Should work with both esm and cjs imports
|
||||
expect(html).toContain(
|
||||
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
|
||||
)
|
||||
expect(html).toContain('CJS package: cjs-lib')
|
||||
})
|
||||
|
||||
it('should use the same react in server app', async () => {
|
||||
|
@ -167,6 +173,26 @@ createNextDescribe(
|
|||
const v1 = html.match(/App React Version: ([^<]+)</)[1]
|
||||
const v2 = html.match(/External React Version: ([^<]+)</)[1]
|
||||
expect(v1).toBe(v2)
|
||||
|
||||
// Should work with both esm and cjs imports
|
||||
expect(html).toContain(
|
||||
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
|
||||
)
|
||||
expect(html).toContain('CJS package: cjs-lib')
|
||||
})
|
||||
|
||||
it('should use the same react in edge server app', async () => {
|
||||
const html = await next.render('/esm/edge-server')
|
||||
|
||||
const v1 = html.match(/App React Version: ([^<]+)</)[1]
|
||||
const v2 = html.match(/External React Version: ([^<]+)</)[1]
|
||||
expect(v1).toBe(v2)
|
||||
|
||||
// Should work with both esm and cjs imports
|
||||
expect(html).toContain(
|
||||
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
|
||||
)
|
||||
expect(html).toContain('CJS package: cjs-lib')
|
||||
})
|
||||
|
||||
it('should use the same react in pages', async () => {
|
||||
|
@ -189,25 +215,26 @@ createNextDescribe(
|
|||
})
|
||||
|
||||
if (isNextDev) {
|
||||
it('should error for wildcard exports of client module references in esm', async () => {
|
||||
const page = 'app/esm-client-ref/page.js'
|
||||
const pageSource = await next.readFile(page)
|
||||
it('should error for require ESM package in CJS package', async () => {
|
||||
const page = 'app/cjs-import-esm/page.js'
|
||||
// reuse esm-client-ref/page.js
|
||||
const pageSource = await next.readFile('app/esm-client-ref/page.js')
|
||||
|
||||
try {
|
||||
await next.patchFile(
|
||||
page,
|
||||
pageSource.replace(
|
||||
"'client-esm-module'",
|
||||
"'client-esm-module-wildcard'"
|
||||
"'client-cjs-import-esm-wildcard'"
|
||||
)
|
||||
)
|
||||
await next.render('/esm-client-ref')
|
||||
await next.render('/cjs-import-esm')
|
||||
} finally {
|
||||
await next.patchFile(page, pageSource)
|
||||
}
|
||||
|
||||
expect(next.cliOutput).toInclude(
|
||||
`It's currently unsupported to use "export *" in a client boundary. Please use named exports instead.`
|
||||
`ESM packages (client-esm-module-wildcard) need to be imported`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
'use client'
|
||||
import { version, useValue } from 'esm-with-react'
|
||||
|
||||
import React from 'react'
|
||||
import { version, useValue } from 'esm-with-react'
|
||||
import { packageEntry as compatPackageEntry } from 'cjs-esm-compat'
|
||||
import { packageName } from 'cjs-lib'
|
||||
|
||||
export default function Index() {
|
||||
const value = useValue()
|
||||
|
@ -10,6 +12,8 @@ export default function Index() {
|
|||
<h2>{'App React Version: ' + React.version}</h2>
|
||||
<h2>{'External React Version: ' + version}</h2>
|
||||
<h2>{'Test: ' + value}</h2>
|
||||
<h2>{`CJS-ESM Compat package: ${compatPackageEntry}`}</h2>
|
||||
<h2>{`CJS package: ${packageName}`}</h2>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
16
test/e2e/app-dir/app-external/app/esm/edge-server/page.js
Normal file
16
test/e2e/app-dir/app-external/app/esm/edge-server/page.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { version } from 'esm-with-react'
|
||||
import { packageEntry as compatPackageEntry } from 'cjs-esm-compat'
|
||||
import { packageName } from 'cjs-lib'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<div>
|
||||
<h2>{'App React Version: ' + React.version}</h2>
|
||||
<h2>{'External React Version: ' + version}</h2>
|
||||
<h2>{`CJS-ESM Compat package: ${compatPackageEntry}`}</h2>
|
||||
<h2>{`CJS package: ${packageName}`}</h2>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import { version } from 'esm-with-react'
|
||||
import { packageEntry as compatPackageEntry } from 'cjs-esm-compat'
|
||||
import { packageName } from 'cjs-lib'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
|
@ -7,6 +9,8 @@ export default function Index() {
|
|||
<div>
|
||||
<h2>{'App React Version: ' + React.version}</h2>
|
||||
<h2>{'External React Version: ' + version}</h2>
|
||||
<h2>{`CJS-ESM Compat package: ${compatPackageEntry}`}</h2>
|
||||
<h2>{`CJS package: ${packageName}`}</h2>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createResponse } from 'cjs-lib'
|
||||
import { createResponse } from 'next-server-cjs-lib'
|
||||
import { respond } from 'compat-next-server-module'
|
||||
|
||||
export async function middleware(request) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
exports.packageEntry = 'cjs-esm-compat/index.cjs'
|
|
@ -0,0 +1 @@
|
|||
export const packageEntry = 'cjs-esm-compat/index.mjs'
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"exports": {
|
||||
"import": "./index.mjs",
|
||||
"require": "./index.cjs",
|
||||
"default": "./index.cjs"
|
||||
}
|
||||
}
|
|
@ -1,8 +1 @@
|
|||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
const server_1 = require('next/server')
|
||||
const createResponse = (...args) => {
|
||||
return new server_1.NextResponse(...args)
|
||||
}
|
||||
exports.createResponse = createResponse
|
||||
|
||||
// Note: this is a CJS library that used the `NextResponse` export from `next/server`.
|
||||
exports.packageName = 'cjs-lib'
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
'use client'
|
||||
|
||||
module.exports = require('client-esm-module-wildcard')
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "client-cjs-import-esm-wildcard",
|
||||
"type": "commonjs",
|
||||
"exports": "./index.js"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
const server_1 = require('next/server')
|
||||
const createResponse = (...args) => {
|
||||
return new server_1.NextResponse(...args)
|
||||
}
|
||||
exports.createResponse = createResponse
|
||||
|
||||
exports.packageName = 'cjs-lib'
|
||||
// Note: this is a CJS library that used the `NextResponse` export from `next/server`.
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "next-server-cjs-lib",
|
||||
"exports": "./index.js"
|
||||
}
|
|
@ -11,8 +11,8 @@ export default function Index() {
|
|||
return (
|
||||
<div>
|
||||
<h1>{`component:index.server`}</h1>
|
||||
<div>{'env:' + envVar}</div>
|
||||
<div>{'header:' + header}</div>
|
||||
<div id="env">{'env:' + envVar}</div>
|
||||
<div id="header">{'header:' + header}</div>
|
||||
<Nav />
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -96,11 +96,11 @@ createNextDescribe(
|
|||
'<meta name="viewport" content="width=device-width, initial-scale=1"/>'
|
||||
)
|
||||
|
||||
expect(homeHTML).toContain('component:index.server')
|
||||
expect(homeHTML).toContain('header:test-util')
|
||||
|
||||
const inlineFlightContents = []
|
||||
const $ = cheerio.load(homeHTML)
|
||||
expect($('h1').text()).toBe('component:index.server')
|
||||
$('script').each((_index, tag) => {
|
||||
const content = $(tag).text()
|
||||
if (content) inlineFlightContents.push(content)
|
||||
|
@ -390,9 +390,7 @@ createNextDescribe(
|
|||
it('should support streaming for flight response', async () => {
|
||||
await next
|
||||
.fetch('/', {
|
||||
headers: {
|
||||
['RSC'.toString()]: '1',
|
||||
},
|
||||
headers: { RSC: '1' },
|
||||
})
|
||||
.then(async (response) => {
|
||||
const result = await resolveStreamResponse(response)
|
||||
|
|
Loading…
Reference in a new issue