Skip to content

Commit 6f565dd

Browse files
committed
refactor rsc export marks
1 parent b6b5250 commit 6f565dd

9 files changed

Lines changed: 71 additions & 72 deletions

File tree

packages/next/build/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ export async function isPageStatic(
881881
throw new Error('INVALID_DEFAULT_EXPORT')
882882
}
883883

884-
const hasFlightData = !!(Comp as any).__next_rsc__
884+
const hasFlightData = !!(mod as any).__next_rsc__
885885
const hasGetInitialProps = !!(Comp as any).getInitialProps
886886
const hasStaticProps = !!mod.getStaticProps
887887
const hasStaticPaths = !!mod.getStaticPaths

packages/next/build/webpack/loaders/next-flight-server-loader.ts

Lines changed: 24 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -42,30 +42,30 @@ function isImageImport(importSource: string) {
4242
async function parseImportsInfo({
4343
resourcePath,
4444
source,
45-
imports,
4645
isClientCompilation,
4746
isServerComponent,
4847
isClientComponent,
4948
}: {
5049
resourcePath: string
5150
source: string
52-
imports: Array<string>
5351
isClientCompilation: boolean
5452
isServerComponent: (name: string) => boolean
5553
isClientComponent: (name: string) => boolean
5654
}): Promise<{
5755
source: string
58-
defaultExportName: string
56+
imports: string
5957
}> {
6058
const opts = getBaseSWCOptions({
6159
filename: resourcePath,
6260
globalWindow: isClientCompilation,
6361
})
6462
const ast = await parse(source, { ...opts.jsc.parser, isModule: true })
6563
const { body } = ast
64+
6665
let transformedSource = ''
6766
let lastIndex = 0
68-
let defaultExportName
67+
let imports = ''
68+
6969
for (let i = 0; i < body.length; i++) {
7070
const node = body[i]
7171
switch (node.type) {
@@ -86,7 +86,7 @@ async function parseImportsInfo({
8686
// A client component. It should be loaded as module reference.
8787
transformedSource += importDeclarations
8888
transformedSource += JSON.stringify(`${importSource}?__sc_client__`)
89-
imports.push(`require(${JSON.stringify(importSource)})`)
89+
imports += `require(${JSON.stringify(importSource)});`
9090
} else {
9191
// This is a special case to avoid the Duplicate React error.
9292
// Since we already include React in the SSR runtime,
@@ -116,27 +116,12 @@ async function parseImportsInfo({
116116
continue
117117
}
118118

119-
imports.push(`require(${JSON.stringify(importSource)})`)
119+
imports += `require(${JSON.stringify(importSource)});`
120120
}
121121

122122
lastIndex = node.source.span.end
123123
break
124124
}
125-
case 'ExportDefaultDeclaration': {
126-
const def = node.decl
127-
if (def.type === 'Identifier') {
128-
defaultExportName = def.name
129-
} else if (def.type === 'FunctionExpression') {
130-
defaultExportName = def.identifier.value
131-
}
132-
break
133-
}
134-
case 'ExportDefaultExpression':
135-
const exp = node.expression
136-
if (exp.type === 'Identifier') {
137-
defaultExportName = exp.value
138-
}
139-
break
140125
default:
141126
break
142127
}
@@ -146,7 +131,7 @@ async function parseImportsInfo({
146131
transformedSource += source.substring(lastIndex)
147132
}
148133

149-
return { source: transformedSource, defaultExportName }
134+
return { source: transformedSource, imports }
150135
}
151136

152137
export default async function transformSource(
@@ -181,44 +166,34 @@ export default async function transformSource(
181166
}
182167
}
183168

184-
const imports: string[] = []
185-
const { source: transformedSource, defaultExportName } =
186-
await parseImportsInfo({
187-
resourcePath,
188-
source,
189-
imports,
190-
isClientCompilation,
191-
isServerComponent,
192-
isClientComponent,
193-
})
169+
const { source: transformedSource, imports } = await parseImportsInfo({
170+
resourcePath,
171+
source,
172+
isClientCompilation,
173+
isServerComponent,
174+
isClientComponent,
175+
})
194176

195177
/**
196178
* For .server.js files, we handle this loader differently.
197179
*
198180
* Server compilation output:
199-
* export default function ServerComponent() { ... }
200-
* export const __rsc_noop__ = () => { ... }
201-
* ServerComponent.__next_rsc__ = 1
202-
* ServerComponent.__webpack_require__ = __webpack_require__
181+
* (The content of the Server Component module will be kept.)
182+
* export const __next_rsc__ = { __webpack_require__, _: () => { ... } }
203183
*
204184
* Client compilation output:
205-
* The function body of Server Component will be removed
185+
* (The content of the Server Component module will be removed.)
186+
* export const __next_rsc__ = { __webpack_require__, _: () => { ... } }
206187
*/
207188

208-
const noop = `export const __rsc_noop__=()=>{${imports.join(';')}}`
189+
let rscExports = `export const __next_rsc__={
190+
__webpack_require__,
191+
_: () => {${imports}}
192+
}`
209193

210-
let defaultExportNoop = ''
211194
if (isClientCompilation) {
212-
defaultExportNoop = `export default function ${
213-
defaultExportName || 'ServerComponent'
214-
}(){}\n${defaultExportName || 'ServerComponent'}.__next_rsc__=1;`
215-
} else {
216-
if (defaultExportName) {
217-
// It's required to have the default export for pages. For other components, it's fine to leave it as is.
218-
defaultExportNoop = `${defaultExportName}.__next_rsc__=1;${defaultExportName}.__webpack_require__=__webpack_require__;`
219-
}
195+
rscExports += '\nexport default function RSC () {}'
220196
}
221197

222-
const transformed = transformedSource + '\n' + noop + '\n' + defaultExportNoop
223-
return transformed
198+
return transformedSource + '\n' + rscExports
224199
}

packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ export default async function middlewareSSRLoader(this: any) {
2828
2929
import { getRender } from 'next/dist/build/webpack/loaders/next-middleware-ssr-loader/render'
3030
31-
import App from ${stringifiedAppPath}
3231
import Document from ${stringifiedDocumentPath}
3332
33+
const appMod = require(${stringifiedAppPath})
3434
const pageMod = require(${stringifiedPagePath})
3535
const errorMod = require(${stringifiedErrorPath})
3636
const error500Mod = ${stringified500Path} ? require(${stringified500Path}) : null
@@ -48,10 +48,10 @@ export default async function middlewareSSRLoader(this: any) {
4848
const render = getRender({
4949
dev: ${dev},
5050
page: ${JSON.stringify(page)},
51+
appMod,
5152
pageMod,
5253
errorMod,
5354
error500Mod,
54-
App,
5555
Document,
5656
buildManifest,
5757
reactLoadableManifest,

packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ process.cwd = () => ''
1717
export function getRender({
1818
dev,
1919
page,
20+
appMod,
2021
pageMod,
2122
errorMod,
2223
error500Mod,
2324
Document,
24-
App,
2525
buildManifest,
2626
reactLoadableManifest,
2727
serverComponentManifest,
@@ -31,11 +31,11 @@ export function getRender({
3131
}: {
3232
dev: boolean
3333
page: string
34+
appMod: any
3435
pageMod: any
3536
errorMod: any
3637
error500Mod: any
3738
Document: DocumentType
38-
App: AppType
3939
buildManifest: BuildManifest
4040
reactLoadableManifest: ReactLoadableManifest
4141
serverComponentManifest: any | null
@@ -48,7 +48,8 @@ export function getRender({
4848
buildManifest,
4949
reactLoadableManifest,
5050
Document,
51-
App,
51+
App: appMod.default as AppType,
52+
AppMod: appMod,
5253
}
5354

5455
const server = new WebServer({

packages/next/client/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ const appElement: HTMLElement | null = document.getElementById('__next')
179179
let lastRenderReject: (() => void) | null
180180
let webpackHMR: any
181181
export let router: Router
182+
182183
let CachedApp: AppComponent, onPerfEntry: (metric: any) => void
184+
let isAppRSC: boolean
185+
183186
headManager.getIsSsr = () => {
184187
return router.isSsr
185188
}
@@ -291,6 +294,7 @@ export async function initNext(
291294

292295
const { component: app, exports: mod } = appEntrypoint
293296
CachedApp = app as AppComponent
297+
isAppRSC = !!mod.__next_rsc__
294298
const exportedReportWebVitals = mod && mod.reportWebVitals
295299
onPerfEntry = ({
296300
id,
@@ -419,6 +423,7 @@ export async function initNext(
419423
defaultLocale,
420424
domainLocales,
421425
isPreview,
426+
isRsc: rsc,
422427
})
423428

424429
const renderCtx: RenderRouteInfo = {
@@ -640,7 +645,7 @@ function AppContainer({
640645
}
641646

642647
function renderApp(App: AppComponent, appProps: AppProps) {
643-
if (process.env.__NEXT_RSC && (App as any).__next_rsc__) {
648+
if (process.env.__NEXT_RSC && isAppRSC) {
644649
const { Component, err: _, router: __, ...props } = appProps
645650
return <Component {...props} />
646651
} else {

packages/next/server/load-components.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type LoadComponentsReturnType = {
3636
getStaticPaths?: GetStaticPaths
3737
getServerSideProps?: GetServerSideProps
3838
ComponentMod: any
39+
AppMod: any
3940
}
4041

4142
export async function loadDefaultErrorComponents(
@@ -46,7 +47,8 @@ export async function loadDefaultErrorComponents(
4647
require(`next/dist/pages/_document` +
4748
(hasConcurrentFeatures ? '-concurrent' : ''))
4849
)
49-
const App = interopDefault(require('next/dist/pages/_app'))
50+
const AppMod = require('next/dist/pages/_app')
51+
const App = interopDefault(AppMod)
5052
const ComponentMod = require('next/dist/pages/_error')
5153
const Component = interopDefault(ComponentMod)
5254

@@ -58,6 +60,7 @@ export async function loadDefaultErrorComponents(
5860
buildManifest: require(join(distDir, `fallback-${BUILD_MANIFEST}`)),
5961
reactLoadableManifest: {},
6062
ComponentMod,
63+
AppMod,
6164
}
6265
}
6366

@@ -124,6 +127,7 @@ export async function loadComponents(
124127
reactLoadableManifest,
125128
pageConfig: ComponentMod.config || {},
126129
ComponentMod,
130+
AppMod,
127131
getServerSideProps,
128132
getStaticProps,
129133
getStaticPaths,

packages/next/server/render.tsx

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,12 @@ function enhanceComponents(
184184
}
185185

186186
function renderFlight(
187+
AppMod: any,
187188
App: AppType,
188189
Component: React.ComponentType,
189190
props: any
190191
) {
191-
const AppServer = (App as any).__next_rsc__
192+
const AppServer = AppMod.__next_rsc__
192193
? (App as React.ComponentType)
193194
: React.Fragment
194195
return (
@@ -357,6 +358,8 @@ const useRSCResponse = createRSCHook()
357358
function createServerComponentRenderer(
358359
App: AppType,
359360
OriginalComponent: React.ComponentType,
361+
AppMod: any,
362+
ComponentMod: any,
360363
{
361364
cachePrefix,
362365
transformStream,
@@ -374,14 +377,15 @@ function createServerComponentRenderer(
374377
// globally for react-server-dom-webpack.
375378
// This is a hack until we find a better way.
376379
// @ts-ignore
377-
globalThis.__webpack_require__ = OriginalComponent.__webpack_require__
380+
globalThis.__webpack_require__ =
381+
ComponentMod.__next_rsc__.__webpack_require__
378382
}
379383

380384
const writable = transformStream.writable
381385
const ServerComponentWrapper = (props: any) => {
382386
const id = (React as any).useId()
383387
const reqStream: ReadableStream<Uint8Array> = renderToReadableStream(
384-
renderFlight(App, OriginalComponent, props),
388+
renderFlight(AppMod, App, OriginalComponent, props),
385389
serverComponentManifest
386390
)
387391

@@ -463,6 +467,8 @@ export async function renderToHTML(
463467
images,
464468
reactRoot,
465469
runtime,
470+
ComponentMod,
471+
AppMod,
466472
} = renderOpts
467473

468474
const hasConcurrentFeatures = !!runtime
@@ -473,7 +479,7 @@ export async function renderToHTML(
473479
const isServerComponent =
474480
!!serverComponentManifest &&
475481
hasConcurrentFeatures &&
476-
(OriginalComponent as any).__next_rsc__
482+
ComponentMod.__next_rsc__
477483

478484
let Component: React.ComponentType<{}> | ((props: any) => JSX.Element) =
479485
renderOpts.Component
@@ -485,12 +491,18 @@ export async function renderToHTML(
485491
if (isServerComponent) {
486492
serverComponentsInlinedTransformStream = new TransformStream()
487493
const search = stringifyQuery(query)
488-
Component = createServerComponentRenderer(App, OriginalComponent, {
489-
cachePrefix: pathname + (search ? `?${search}` : ''),
490-
transformStream: serverComponentsInlinedTransformStream,
491-
serverComponentManifest,
492-
runtime,
493-
})
494+
Component = createServerComponentRenderer(
495+
App,
496+
AppMod,
497+
OriginalComponent,
498+
ComponentMod,
499+
{
500+
cachePrefix: pathname + (search ? `?${search}` : ''),
501+
transformStream: serverComponentsInlinedTransformStream,
502+
serverComponentManifest,
503+
runtime,
504+
}
505+
)
494506
}
495507

496508
const getFontDefinition = (url: string): string => {
@@ -1178,7 +1190,7 @@ export async function renderToHTML(
11781190

11791191
if (renderServerComponentData) {
11801192
const stream: ReadableStream<Uint8Array> = renderToReadableStream(
1181-
renderFlight(App, OriginalComponent, {
1193+
renderFlight(AppMod, App, OriginalComponent, {
11821194
...props.pageProps,
11831195
...serverComponentProps,
11841196
}),
@@ -1318,7 +1330,7 @@ export async function renderToHTML(
13181330
) : (
13191331
<Body>
13201332
<AppContainerWithIsomorphicFiberStructure>
1321-
{renderOpts.serverComponents && (App as any).__next_rsc__ ? (
1333+
{renderOpts.serverComponents && AppMod.__next_rsc__ ? (
13221334
<Component {...props.pageProps} router={router} />
13231335
) : (
13241336
<App {...props} Component={Component} router={router} />

0 commit comments

Comments
 (0)