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

Component Module Types #56454

Merged
merged 2 commits into from Oct 5, 2023
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
12 changes: 6 additions & 6 deletions packages/next/src/build/templates/app-page.ts
@@ -1,13 +1,14 @@
import type { LoaderTree } from '../../server/lib/app-dir-module'

// @ts-ignore this need to be imported from next/dist to be external
import * as module from 'next/dist/server/future/route-modules/app-page/module.compiled'
import { AppPageRouteModule } from '../../server/future/route-modules/app-page/module.compiled'
import { RouteKind } from '../../server/future/route-kind'

const AppPageRouteModule =
module.AppPageRouteModule as unknown as typeof import('../../server/future/route-modules/app-page/module').AppPageRouteModule

// These are injected by the loader afterwards.

/**
* The tree created in next-app-loader that holds component segments and modules
* and I've updated it.
*/
declare const tree: LoaderTree
declare const pages: any

Expand All @@ -18,7 +19,6 @@ declare const pages: any

export { tree, pages }

// @ts-expect-error - replaced by webpack/turbopack loader
export { default as GlobalError } from 'VAR_MODULE_GLOBAL_ERROR'

// These are injected by the loader afterwards.
Expand Down
12 changes: 4 additions & 8 deletions packages/next/src/build/templates/app-route.ts
@@ -1,17 +1,13 @@
import '../../server/node-polyfill-headers'

// @ts-ignore this need to be imported from next/dist to be external
import * as module from 'next/dist/server/future/route-modules/app-route/module.compiled'

import type { AppRouteRouteModuleOptions } from '../../server/future/route-modules/app-route/module'
import {
AppRouteRouteModule,
type AppRouteRouteModuleOptions,
} from '../../server/future/route-modules/app-route/module.compiled'
import { RouteKind } from '../../server/future/route-kind'

// @ts-expect-error - replaced by webpack/turbopack loader
import * as userland from 'VAR_USERLAND'

const AppRouteRouteModule =
module.AppRouteRouteModule as unknown as typeof import('../../server/future/route-modules/app-route/module').AppRouteRouteModule

// These are injected by the loader afterwards. This is injected as a variable
// instead of a replacement because this could also be `undefined` instead of
// an empty string.
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/build/templates/edge-app-route.ts
@@ -1,7 +1,6 @@
import { EdgeRouteModuleWrapper } from '../../server/web/edge-route-module-wrapper'

// Import the userland code.
// @ts-expect-error - replaced by webpack/turbopack loader
import * as module from 'VAR_USERLAND'

export const ComponentMod = module
Expand Down
5 changes: 3 additions & 2 deletions packages/next/src/build/templates/middleware.ts
@@ -1,9 +1,10 @@
import '../../server/web/globals'
import type { AdapterOptions } from '../../server/web/adapter'

import '../../server/web/globals'

import { adapter } from '../../server/web/adapter'

// Import the userland code.
// @ts-expect-error - replaced by webpack/turbopack loader
import * as _mod from 'VAR_USERLAND'

const mod = { ..._mod }
Expand Down
9 changes: 2 additions & 7 deletions packages/next/src/build/templates/pages-api.ts
@@ -1,14 +1,9 @@
// @ts-ignore this need to be imported from next/dist to be external
import * as module from 'next/dist/server/future/route-modules/pages-api/module.compiled'

import { PagesAPIRouteModule } from '../../server/future/route-modules/pages-api/module.compiled'
import { RouteKind } from '../../server/future/route-kind'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relative imports are possible because the .js file references the compiled dist runtime, thereby ensuring it remains external

import { hoist } from './helpers'

const PagesAPIRouteModule =
module.PagesAPIRouteModule as unknown as typeof import('../../server/future/route-modules/pages-api/module').PagesAPIRouteModule
import { hoist } from './helpers'

// Import the userland code.
// @ts-expect-error - replaced by webpack/turbopack loader
import * as userland from 'VAR_USERLAND'

// Re-export the handler (should be the default export).
Expand Down
5 changes: 3 additions & 2 deletions packages/next/src/build/templates/pages-edge-api.ts
@@ -1,10 +1,11 @@
import '../../server/web/globals'
import type { AdapterOptions } from '../../server/web/adapter'

import '../../server/web/globals'

import { adapter } from '../../server/web/adapter'
import { IncrementalCache } from '../../server/lib/incremental-cache'

// Import the userland code.
// @ts-expect-error - replaced by webpack/turbopack loader
import handler from 'VAR_USERLAND'

const page = 'VAR_DEFINITION_PAGE'
Expand Down
9 changes: 1 addition & 8 deletions packages/next/src/build/templates/pages.ts
@@ -1,21 +1,14 @@
// @ts-ignore this need to be imported from next/dist to be external
import * as module from 'next/dist/server/future/route-modules/pages/module.compiled'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this not valid anymore?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the import hits the ".js" .module.compiled file which does import via next/dist, it seems like this was able to allow them to remain external while enabling us to use the relative import 😌

import { PagesRouteModule } from '../../server/future/route-modules/pages/module.compiled'
import { RouteKind } from '../../server/future/route-kind'
import { hoist } from './helpers'

// Import the app and document modules.
// @ts-expect-error - replaced by webpack/turbopack loader
import Document from 'VAR_MODULE_DOCUMENT'
// @ts-expect-error - replaced by webpack/turbopack loader
import App from 'VAR_MODULE_APP'

// Import the userland code.
// @ts-expect-error - replaced by webpack/turbopack loader
import * as userland from 'VAR_USERLAND'

const PagesRouteModule =
module.PagesRouteModule as unknown as typeof import('../../server/future/route-modules/pages/module').PagesRouteModule

// Re-export the component (should be the default export).
Comment on lines -16 to -18
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can go away now 😌

export default hoist(userland, 'default')

Expand Down
27 changes: 6 additions & 21 deletions packages/next/src/build/utils.ts
Expand Up @@ -14,8 +14,8 @@ import type {
EdgeFunctionDefinition,
MiddlewareManifest,
} from './webpack/plugins/middleware-plugin'
import type { StaticGenerationAsyncStorage } from '../client/components/static-generation-async-storage.external'
import type { WebpackLayerName } from '../lib/constants'
import type { AppPageModule } from '../server/future/route-modules/app-page/module'

import '../server/require-hook'
import '../server/node-polyfill-fetch'
Expand Down Expand Up @@ -68,9 +68,7 @@ import { nodeFs } from '../server/lib/node-fs-methods'
import * as ciEnvironment from '../telemetry/ci-info'
import { normalizeAppPath } from '../shared/lib/router/utils/app-paths'
import { denormalizeAppPagePath } from '../shared/lib/page-path/denormalize-app-path'

const { AppRouteRouteModule } =
require('../server/future/route-modules/app-route/module.compiled') as typeof import('../server/future/route-modules/app-route/module')
import { AppRouteRouteModule } from '../server/future/route-modules/app-route/module.compiled'

export type ROUTER_TYPE = 'pages' | 'app'

Expand Down Expand Up @@ -1469,25 +1467,12 @@ export async function isPageStatic({
| undefined

if (pageType === 'app') {
isClientComponent = isClientReference(componentsResult.ComponentMod)
const tree = componentsResult.ComponentMod.tree

const staticGenerationAsyncStorage: StaticGenerationAsyncStorage =
componentsResult.ComponentMod.staticGenerationAsyncStorage
if (!staticGenerationAsyncStorage) {
throw new Error(
'Invariant: staticGenerationAsyncStorage should be defined on the module'
)
}
const ComponentMod: AppPageModule = componentsResult.ComponentMod

const serverHooks = componentsResult.ComponentMod.serverHooks
if (!serverHooks) {
throw new Error(
'Invariant: serverHooks should be defined on the module'
)
}
isClientComponent = isClientReference(componentsResult.ComponentMod)

const { routeModule } = componentsResult
const { tree, staticGenerationAsyncStorage, serverHooks, routeModule } =
ComponentMod

const generateParams: GenerateParams =
routeModule && AppRouteRouteModule.is(routeModule)
Expand Down
@@ -1,4 +1,4 @@
import type webpack from 'webpack'
import type webpack from 'next/dist/compiled/webpack/webpack'
import type { ValueOf } from '../../../shared/lib/constants'
import type { ModuleReference, CollectedMetadata } from './metadata/types'

Expand Down
68 changes: 25 additions & 43 deletions packages/next/src/server/app-render/app-render.tsx
Expand Up @@ -10,9 +10,6 @@ import type {
RenderOpts,
Segment,
} from './types'
import type { StaticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage.external'
import type { StaticGenerationBailout } from '../../client/components/static-generation-bailout'
import type { RequestAsyncStorage } from '../../client/components/request-async-storage.external'

import React from 'react'
import { createServerComponentRenderer } from './create-server-components-renderer'
Expand Down Expand Up @@ -237,6 +234,7 @@ export const renderToHTMLOrFlight: AppPageRender = (
})

patchFetch(ComponentMod)

/**
* Rules of Static & Dynamic HTML:
*
Expand All @@ -252,12 +250,25 @@ export const renderToHTMLOrFlight: AppPageRender = (
*/
const generateStaticHTML = supportsDynamicHTML !== true

const staticGenerationAsyncStorage: StaticGenerationAsyncStorage =
ComponentMod.staticGenerationAsyncStorage
const requestAsyncStorage: RequestAsyncStorage =
ComponentMod.requestAsyncStorage
const staticGenerationBailout: StaticGenerationBailout =
ComponentMod.staticGenerationBailout
// Pull out the hooks/references from the component.
const {
staticGenerationAsyncStorage,
requestAsyncStorage,
staticGenerationBailout,
LayoutRouter,
RenderFromTemplateContext,
createSearchParamsBailoutProxy,
StaticGenerationSearchParamsBailoutProvider,
serverHooks: { DynamicServerError },
NotFoundBoundary,
renderToReadableStream,
AppRouter,
GlobalError,
tree: loaderTree,
preloadFont,
preconnect,
preloadStyle,
} = ComponentMod

// we wrap the render in an AsyncLocalStorage context
const wrappedRender = async () => {
Expand Down Expand Up @@ -294,11 +305,6 @@ export const renderToHTMLOrFlight: AppPageRender = (
)
: undefined

/**
* The tree created in next-app-loader that holds component segments and modules
*/
const loaderTree: LoaderTree = ComponentMod.tree

/**
* The metadata items array created in next-app-loader with all relevant information
* that we need to resolve the final metadata.
Expand All @@ -312,15 +318,6 @@ export const renderToHTMLOrFlight: AppPageRender = (
requestId = require('next/dist/compiled/nanoid').nanoid()
}

const LayoutRouter =
ComponentMod.LayoutRouter as typeof import('../../client/components/layout-router').default
const RenderFromTemplateContext =
ComponentMod.RenderFromTemplateContext as typeof import('../../client/components/render-from-template-context').default
const createSearchParamsBailoutProxy =
ComponentMod.createSearchParamsBailoutProxy as typeof import('../../client/components/searchparams-bailout-proxy').createSearchParamsBailoutProxy
const StaticGenerationSearchParamsBailoutProvider =
ComponentMod.StaticGenerationSearchParamsBailoutProvider as typeof import('../../client/components/static-generation-searchparams-bailout-provider').default

Comment on lines -315 to -323
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes mean that we don't need to do type assertions anymore 😎

const isStaticGeneration = staticGenerationStore.isStaticGeneration
// During static generation we need to call the static generation bailout when reading searchParams
const providedSearchParams = isStaticGeneration
Expand Down Expand Up @@ -511,16 +508,16 @@ export const renderToHTMLOrFlight: AppPageRender = (
const ext = /\.(woff|woff2|eot|ttf|otf)$/.exec(fontFilename)![1]
const type = `font/${ext}`
const href = `${assetPrefix}/_next/${fontFilename}`
ComponentMod.preloadFont(href, type, renderOpts.crossOrigin)
preloadFont(href, type, renderOpts.crossOrigin)
}
} else {
try {
let url = new URL(assetPrefix)
ComponentMod.preconnect(url.origin, 'anonymous')
preconnect(url.origin, 'anonymous')
} catch (error) {
// assetPrefix must not be a fully qualified domain name. We assume
// we should preconnect to same origin instead
ComponentMod.preconnect('/', 'anonymous')
preconnect('/', 'anonymous')
}
}
}
Expand All @@ -546,7 +543,7 @@ export const renderToHTMLOrFlight: AppPageRender = (
const precedence =
process.env.NODE_ENV === 'development' ? 'next_' + href : 'next'

ComponentMod.preloadStyle(fullHref, renderOpts.crossOrigin)
preloadStyle(fullHref, renderOpts.crossOrigin)

return (
<link
Expand Down Expand Up @@ -732,9 +729,6 @@ export const renderToHTMLOrFlight: AppPageRender = (
staticGenerationStore.isStaticGeneration &&
defaultRevalidate === 0
) {
const { DynamicServerError } =
ComponentMod.serverHooks as typeof import('../../client/components/hooks-server-context')

const dynamicUsageDescription = `revalidate: 0 configured ${segment}`
staticGenerationStore.dynamicUsageDescription =
dynamicUsageDescription
Expand All @@ -759,8 +753,6 @@ export const renderToHTMLOrFlight: AppPageRender = (
const hasSlotKey = parallelKeys.length > 1

if (hasSlotKey && rootLayoutAtThisLevel) {
const NotFoundBoundary =
ComponentMod.NotFoundBoundary as typeof import('../../client/components/not-found-boundary').NotFoundBoundary
Component = (componentProps: any) => {
const NotFoundComponent = NotFound
const RootLayoutComponent = LayoutOrPage
Expand Down Expand Up @@ -1287,7 +1279,7 @@ export const renderToHTMLOrFlight: AppPageRender = (

// For app dir, use the bundled version of Flight server renderer (renderToReadableStream)
// which contains the subset React.
const flightReadableStream = ComponentMod.renderToReadableStream(
const flightReadableStream = renderToReadableStream(
options
? [options.actionResult, buildIdFlightDataPair]
: buildIdFlightDataPair,
Expand All @@ -1305,16 +1297,6 @@ export const renderToHTMLOrFlight: AppPageRender = (
return generateFlight()
}

// Below this line is handling for rendering to HTML.

// AppRouter is provided by next-app-loader
const AppRouter =
ComponentMod.AppRouter as typeof import('../../client/components/app-router').default

const GlobalError =
/** GlobalError can be either the default error boundary or the overwritten app/global-error.js **/
ComponentMod.GlobalError as typeof import('../../client/components/error-boundary').GlobalError

// Get the nonce from the incoming request if it has one.
const csp = req.headers['content-security-policy']
let nonce: string | undefined
Expand Down
@@ -1,5 +1,6 @@
import type { RenderOpts } from './types'
import type { FlightResponseRef } from './flight-response-ref'
import type { AppPageModule } from '../future/route-modules/app-page/module'

import React, { use } from 'react'
import { createErrorHandler } from './create-error-handler'
Expand All @@ -11,13 +12,7 @@ import { useFlightResponse } from './use-flight-response'
*/
export function createServerComponentRenderer<Props>(
ComponentToRender: (props: Props) => any,
ComponentMod: {
renderToReadableStream: any
__next_app__?: {
require: any
loadChunk: any
}
},
ComponentMod: AppPageModule,
{
inlinedDataTransformStream,
clientReferenceManifest,
Expand Down
8 changes: 2 additions & 6 deletions packages/next/src/server/app-render/entry-base.ts
@@ -1,10 +1,10 @@
const {
export {
renderToReadableStream,
decodeReply,
decodeAction,
decodeFormState,
// eslint-disable-next-line import/no-extraneous-dependencies
} = require('react-server-dom-webpack/server.edge')
} from 'react-server-dom-webpack/server.edge'

import AppRouter from '../../client/components/app-router'
import LayoutRouter from '../../client/components/layout-router'
Expand Down Expand Up @@ -36,10 +36,6 @@ export {
staticGenerationBailout,
createSearchParamsBailoutProxy,
serverHooks,
renderToReadableStream,
decodeReply,
decodeAction,
decodeFormState,
preloadStyle,
preloadFont,
preconnect,
Expand Down
6 changes: 4 additions & 2 deletions packages/next/src/server/app-render/types.ts
@@ -1,9 +1,10 @@
import type { LoadComponentsReturnType } from '../load-components'
import type { ServerRuntime, SizeLimit } from '../../../types'
import { NextConfigComplete } from '../../server/config-shared'
import type { NextConfigComplete } from '../../server/config-shared'
import type { ClientReferenceManifest } from '../../build/webpack/plugins/flight-manifest-plugin'
import type { NextFontManifest } from '../../build/webpack/plugins/next-font-manifest-plugin'
import type { ParsedUrlQuery } from 'querystring'
import type { AppPageModule } from '../future/route-modules/app-page/module'

import s from 'next/dist/compiled/superstruct'

Expand Down Expand Up @@ -135,4 +136,5 @@ export interface RenderOptsPartial {
isPrefetch?: boolean
}

export type RenderOpts = LoadComponentsReturnType & RenderOptsPartial
export type RenderOpts = LoadComponentsReturnType<AppPageModule> &
RenderOptsPartial