rsnext/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts
Shu Ding 99d4d6c5a4
Implement web server as the request handler for edge SSR (#33635)
(#31506 for context)

This PR implements the minimum viable web server on top of the Next.js base server, and integrates it into our middleware (edge) SSR runtime to handle all the requests.

This also addresses problems like missing dynamic routes support in our current handler.

Note that this is the initial implementation with the assumption that the web server is running under minimal mode. Also later we can refactor the `__server_context` environment to properly passing the context via the constructor or methods.
2022-01-26 06:22:11 +00:00

89 lines
2.5 KiB
TypeScript

import { stringifyRequest } from '../../stringify-request'
export default async function middlewareSSRLoader(this: any) {
const {
dev,
page,
buildId,
absolutePagePath,
absoluteAppPath,
absoluteDocumentPath,
absolute500Path,
absoluteErrorPath,
isServerComponent,
stringifiedConfig,
} = this.getOptions()
const stringifiedAbsolutePagePath = stringifyRequest(this, absolutePagePath)
const stringifiedAbsoluteAppPath = stringifyRequest(this, absoluteAppPath)
const stringifiedAbsolute500PagePath = stringifyRequest(
this,
absolute500Path || absoluteErrorPath
)
const stringifiedAbsoluteDocumentPath = stringifyRequest(
this,
absoluteDocumentPath
)
const transformed = `
import { adapter } from 'next/dist/server/web/adapter'
import { RouterContext } from 'next/dist/shared/lib/router-context'
import App from ${stringifiedAbsoluteAppPath}
import Document from ${stringifiedAbsoluteDocumentPath}
import { getRender } from 'next/dist/build/webpack/loaders/next-middleware-ssr-loader/render'
const pageMod = require(${stringifiedAbsolutePagePath})
const errorMod = require(${stringifiedAbsolute500PagePath})
const buildManifest = self.__BUILD_MANIFEST
const reactLoadableManifest = self.__REACT_LOADABLE_MANIFEST
const rscManifest = self.__RSC_MANIFEST
if (typeof pageMod.default !== 'function') {
throw new Error('Your page must export a \`default\` component')
}
// Set server context
self.__current_route = ${JSON.stringify(page)}
self.__server_context = {
Component: pageMod.default,
pageConfig: pageMod.config || {},
buildManifest,
reactLoadableManifest,
Document,
App,
getStaticProps: pageMod.getStaticProps,
getServerSideProps: pageMod.getServerSideProps,
getStaticPaths: pageMod.getStaticPaths,
ComponentMod: undefined,
serverComponentManifest: ${isServerComponent} ? rscManifest : null,
// components
errorMod,
// renderOpts
buildId: ${JSON.stringify(buildId)},
dev: ${dev},
env: process.env,
supportsDynamicHTML: true,
concurrentFeatures: true,
disableOptimizedLoading: true,
}
const render = getRender({
Document,
isServerComponent: ${isServerComponent},
config: ${stringifiedConfig},
})
export default function rscMiddleware(opts) {
return adapter({
...opts,
handler: render
})
}`
return transformed
}