Skip to content

Commit

Permalink
fix: added support for edge rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
wyattjoh committed Sep 7, 2022
1 parent a0dfe29 commit 2f7769a
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 110 deletions.
1 change: 1 addition & 0 deletions packages/next/build/entries.ts
Expand Up @@ -212,6 +212,7 @@ export function getEdgeServerEntry(opts: {
stringifiedConfig: JSON.stringify(opts.config),
pagesType: opts.pagesType,
appDirLoader: Buffer.from(opts.appDirLoader || '').toString('base64'),
sriEnabled: !opts.isDev && !!opts.config.experimental.sri?.algorithm,
}

return {
Expand Down
34 changes: 17 additions & 17 deletions packages/next/build/utils.ts
Expand Up @@ -1082,13 +1082,13 @@ export async function isPageStatic({
getStaticProps: mod.getStaticProps,
}
} else {
componentsResult = await loadComponents(
componentsResult = await loadComponents({
distDir,
page,
pathname: page,
serverless,
false,
false
)
hasServerComponents: false,
isAppPath: false,
})
}
const Comp = componentsResult.Component

Expand Down Expand Up @@ -1214,13 +1214,13 @@ export async function hasCustomGetInitialProps(
): Promise<boolean> {
require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig)

const components = await loadComponents(
const components = await loadComponents({
distDir,
page,
isLikeServerless,
false,
false
)
pathname: page,
serverless: isLikeServerless,
hasServerComponents: false,
isAppPath: false,
})
let mod = components.ComponentMod

if (checkingApp) {
Expand All @@ -1239,13 +1239,13 @@ export async function getNamedExports(
runtimeEnvConfig: any
): Promise<Array<string>> {
require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig)
const components = await loadComponents(
const components = await loadComponents({
distDir,
page,
isLikeServerless,
false,
false
)
pathname: page,
serverless: isLikeServerless,
hasServerComponents: false,
isAppPath: false,
})
let mod = components.ComponentMod

return Object.keys(mod)
Expand Down
8 changes: 6 additions & 2 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1751,7 +1751,11 @@ export default async function getBaseWebpackConfig(
}),
// MiddlewarePlugin should be after DefinePlugin so NEXT_PUBLIC_*
// replacement is done before its process.env.* handling
isEdgeServer && new MiddlewarePlugin({ dev }),
isEdgeServer &&
new MiddlewarePlugin({
dev,
sriEnabled: !dev && !!config.experimental.sri?.algorithm,
}),
isClient &&
new BuildManifestPlugin({
buildId,
Expand Down Expand Up @@ -1803,7 +1807,7 @@ export default async function getBaseWebpackConfig(
})),
!dev &&
isClient &&
config.experimental.sri?.algorithm &&
!!config.experimental.sri?.algorithm &&
new SubresourceIntegrityPlugin(config.experimental.sri.algorithm),
!dev &&
isClient &&
Expand Down
Expand Up @@ -14,6 +14,7 @@ export type EdgeSSRLoaderQuery = {
stringifiedConfig: string
appDirLoader?: string
pagesType?: 'app' | 'pages' | 'root'
sriEnabled: boolean
}

export default async function edgeSSRLoader(this: any) {
Expand All @@ -30,6 +31,7 @@ export default async function edgeSSRLoader(this: any) {
stringifiedConfig,
appDirLoader: appDirLoaderBase64,
pagesType,
sriEnabled,
} = this.getOptions()

const appDirLoader = Buffer.from(
Expand Down Expand Up @@ -94,6 +96,9 @@ export default async function edgeSSRLoader(this: any) {
const reactLoadableManifest = self.__REACT_LOADABLE_MANIFEST
const rscManifest = self.__RSC_MANIFEST
const rscCssManifest = self.__RSC_CSS_MANIFEST
const subresourceIntegrityManifest = ${
sriEnabled ? 'self.__SUBRESOURCE_INTEGRITY_MANIFEST' : 'undefined'
}
const render = getRender({
dev: ${dev},
Expand All @@ -109,6 +114,7 @@ export default async function edgeSSRLoader(this: any) {
reactLoadableManifest,
serverComponentManifest: ${isServerComponent} ? rscManifest : null,
serverCSSManifest: ${isServerComponent} ? rscCssManifest : null,
subresourceIntegrityManifest,
config: ${stringifiedConfig},
buildId: ${JSON.stringify(buildId)},
})
Expand Down
Expand Up @@ -23,6 +23,7 @@ export function getRender({
appRenderToHTML,
pagesRenderToHTML,
serverComponentManifest,
subresourceIntegrityManifest,
serverCSSManifest,
config,
buildId,
Expand All @@ -38,6 +39,7 @@ export function getRender({
Document: DocumentType
buildManifest: BuildManifest
reactLoadableManifest: ReactLoadableManifest
subresourceIntegrityManifest?: Record<string, string>
serverComponentManifest: any
serverCSSManifest: any
appServerMod: any
Expand All @@ -48,6 +50,7 @@ export function getRender({
dev,
buildManifest,
reactLoadableManifest,
subresourceIntegrityManifest,
Document,
App: appMod.default as AppType,
}
Expand Down
29 changes: 22 additions & 7 deletions packages/next/build/webpack/plugins/middleware-plugin.ts
Expand Up @@ -17,6 +17,7 @@ import {
MIDDLEWARE_REACT_LOADABLE_MANIFEST,
NEXT_CLIENT_SSR_ENTRY_SUFFIX,
FLIGHT_SERVER_CSS_MANIFEST,
SUBRESOURCE_INTEGRITY_MANIFEST,
} from '../../../shared/lib/constants'

export interface EdgeFunctionDefinition {
Expand Down Expand Up @@ -80,12 +81,19 @@ function isUsingIndirectEvalAndUsedByExports(args: {
return false
}

function getEntryFiles(entryFiles: string[], meta: EntryMetadata) {
function getEntryFiles(
entryFiles: string[],
meta: EntryMetadata,
opts: { sriEnabled: boolean }
) {
const files: string[] = []
if (meta.edgeSSR) {
if (meta.edgeSSR.isServerComponent) {
files.push(`server/${FLIGHT_MANIFEST}.js`)
files.push(`server/${FLIGHT_SERVER_CSS_MANIFEST}.js`)
if (opts.sriEnabled) {
files.push(`server/${SUBRESOURCE_INTEGRITY_MANIFEST}.js`)
}
files.push(
...entryFiles
.filter(
Expand Down Expand Up @@ -118,8 +126,9 @@ function getEntryFiles(entryFiles: string[], meta: EntryMetadata) {
function getCreateAssets(params: {
compilation: webpack.Compilation
metadataByEntry: Map<string, EntryMetadata>
opts: { sriEnabled: boolean }
}) {
const { compilation, metadataByEntry } = params
const { compilation, metadataByEntry, opts } = params
return (assets: any) => {
for (const entrypoint of compilation.entrypoints.values()) {
if (!entrypoint.name) {
Expand All @@ -145,7 +154,7 @@ function getCreateAssets(params: {

const edgeFunctionDefinition: EdgeFunctionDefinition = {
env: Array.from(metadata.env),
files: getEntryFiles(entrypoint.getFiles(), metadata),
files: getEntryFiles(entrypoint.getFiles(), metadata, opts),
name: entrypoint.name,
page: page,
matchers,
Expand Down Expand Up @@ -708,13 +717,15 @@ function getExtractMetadata(params: {
}

export default class MiddlewarePlugin {
dev: boolean
private readonly dev: boolean
private readonly sriEnabled: boolean

constructor({ dev }: { dev: boolean }) {
constructor({ dev, sriEnabled }: { dev: boolean; sriEnabled: boolean }) {
this.dev = dev
this.sriEnabled = sriEnabled
}

apply(compiler: webpack.Compiler) {
public apply(compiler: webpack.Compiler) {
compiler.hooks.compilation.tap(NAME, (compilation, params) => {
const { hooks } = params.normalModuleFactory
/**
Expand Down Expand Up @@ -751,7 +762,11 @@ export default class MiddlewarePlugin {
name: 'NextJsMiddlewareManifest',
stage: (webpack as any).Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
},
getCreateAssets({ compilation, metadataByEntry })
getCreateAssets({
compilation,
metadataByEntry,
opts: { sriEnabled: this.sriEnabled },
})
)
})
}
Expand Down
Expand Up @@ -53,9 +53,17 @@ export class SubresourceIntegrityPlugin {
}

const json = JSON.stringify(hashes, null, 2)
assets[SUBRESOURCE_INTEGRITY_MANIFEST] = new sources.RawSource(
const file = 'server/' + SUBRESOURCE_INTEGRITY_MANIFEST
assets[file + '.js'] = new sources.RawSource(
'self.__SUBRESOURCE_INTEGRITY_MANIFEST=' + json
// Work around webpack 4 type of RawSource being used
// TODO: use webpack 5 type by default
) as unknown as webpack.sources.RawSource
assets[file + '.json'] = new sources.RawSource(
json
) as any
// Work around webpack 4 type of RawSource being used
// TODO: use webpack 5 type by default
) as unknown as webpack.sources.RawSource
}
)
})
Expand Down
20 changes: 10 additions & 10 deletions packages/next/export/worker.ts
Expand Up @@ -290,13 +290,13 @@ export default async function exportPage({
getServerSideProps,
getStaticProps,
pageConfig,
} = await loadComponents(
} = await loadComponents({
distDir,
page,
pathname: page,
serverless,
!!serverComponents,
isAppPath
)
hasServerComponents: !!serverComponents,
isAppPath,
})
const ampState = {
ampFirst: pageConfig?.amp === true,
hasQuery: Boolean(query.amp),
Expand Down Expand Up @@ -357,13 +357,13 @@ export default async function exportPage({
throw new Error(`Failed to render serverless page`)
}
} else {
const components = await loadComponents(
const components = await loadComponents({
distDir,
page,
pathname: page,
serverless,
!!serverComponents,
isAppPath
)
hasServerComponents: !!serverComponents,
isAppPath,
})
const ampState = {
ampFirst: components.pageConfig?.amp === true,
hasQuery: Boolean(query.amp),
Expand Down
9 changes: 3 additions & 6 deletions packages/next/server/app-render.tsx
Expand Up @@ -421,18 +421,15 @@ function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined {

// First try to find the directive for the 'script-src', otherwise try to
// fallback to the 'default-src'.
let directive = directives.find((dir) => dir.startsWith('script-src'))
if (!directive) {
directive = directives.find((dir) => dir.startsWith('default-src'))
}
const directive =
directives.find((dir) => dir.startsWith('script-src')) ||
directives.find((dir) => dir.startsWith('default-src'))

// If no directive could be found, then we're done.
if (!directive) {
return
}

debugger

// Extract the nonce from the directive
const nonce = directive
.split(' ')
Expand Down
8 changes: 4 additions & 4 deletions packages/next/server/dev/static-paths-worker.ts
Expand Up @@ -38,13 +38,13 @@ export async function loadStaticPaths(
require('../../shared/lib/runtime-config').setConfig(config)
setHttpAgentOptions(httpAgentOptions)

const components = await loadComponents(
const components = await loadComponents({
distDir,
pathname,
serverless,
false,
false
)
hasServerComponents: false,
isAppPath: false,
})

if (!components.getStaticPaths) {
// we shouldn't get to this point since the worker should
Expand Down
46 changes: 21 additions & 25 deletions packages/next/server/load-components.ts
Expand Up @@ -13,7 +13,6 @@ import {
BUILD_MANIFEST,
REACT_LOADABLE_MANIFEST,
FLIGHT_MANIFEST,
SUBRESOURCE_INTEGRITY_MANIFEST,
} from '../shared/lib/constants'
import { join } from 'path'
import { requirePage } from './require'
Expand Down Expand Up @@ -61,14 +60,19 @@ export async function loadDefaultErrorComponents(distDir: string) {
}
}

export async function loadComponents(
distDir: string,
pathname: string,
serverless: boolean,
hasServerComponents: boolean,
isAppPath: boolean,
sriEnabled?: boolean
): Promise<LoadComponentsReturnType> {
export async function loadComponents({
distDir,
pathname,
serverless,
hasServerComponents,
isAppPath,
}: {
distDir: string
pathname: string
serverless: boolean
hasServerComponents: boolean
isAppPath: boolean
}): Promise<LoadComponentsReturnType> {
if (serverless) {
const ComponentMod = await requirePage(pathname, distDir, serverless)
if (typeof ComponentMod === 'string') {
Expand Down Expand Up @@ -118,21 +122,14 @@ export async function loadComponents(
requirePage(pathname, distDir, serverless, isAppPath)
)

const [
buildManifest,
reactLoadableManifest,
serverComponentManifest,
subresourceIntegrityManifest,
] = await Promise.all([
require(join(distDir, BUILD_MANIFEST)),
require(join(distDir, REACT_LOADABLE_MANIFEST)),
hasServerComponents
? require(join(distDir, 'server', FLIGHT_MANIFEST + '.json'))
: null,
sriEnabled
? require(join(distDir, SUBRESOURCE_INTEGRITY_MANIFEST))
: undefined,
])
const [buildManifest, reactLoadableManifest, serverComponentManifest] =
await Promise.all([
require(join(distDir, BUILD_MANIFEST)),
require(join(distDir, REACT_LOADABLE_MANIFEST)),
hasServerComponents
? require(join(distDir, 'server', FLIGHT_MANIFEST + '.json'))
: null,
])

const Component = interopDefault(ComponentMod)
const Document = interopDefault(DocumentMod)
Expand All @@ -145,7 +142,6 @@ export async function loadComponents(
Document,
Component,
buildManifest,
subresourceIntegrityManifest,
reactLoadableManifest,
pageConfig: ComponentMod.config || {},
ComponentMod,
Expand Down

0 comments on commit 2f7769a

Please sign in to comment.