Skip to content

Commit

Permalink
Tweak dynamic HTML generation
Browse files Browse the repository at this point in the history
  • Loading branch information
devknoll committed Sep 4, 2021
1 parent 7f83e6d commit fb70d92
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function getPageHandler(ctx: ServerlessHandlerCtx) {
previewProps: encodedPreviewProps,
env: process.env,
basePath,
requireStaticHTML: true, // Serverless target doesn't support streaming
supportsDynamicHTML: false, // Serverless target doesn't support streaming
..._renderOpts,
}
let _nextData = false
Expand Down
4 changes: 2 additions & 2 deletions packages/next/export/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,8 @@ export default async function exportApp(
domainLocales: i18n?.domains,
trailingSlash: nextConfig.trailingSlash,
disableOptimizedLoading: nextConfig.experimental.disableOptimizedLoading,
// TODO: We should support dynamic HTML too
requireStaticHTML: true,
// Exported pages do not currently support dynamic HTML.
supportsDynamicHTML: false,
concurrentFeatures: nextConfig.experimental.concurrentFeatures,
}

Expand Down
25 changes: 15 additions & 10 deletions packages/next/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1250,13 +1250,12 @@ export default class Server {
query: ParsedUrlQuery
}
): Promise<void> {
// TODO: Determine when dynamic HTML is allowed
const requireStaticHTML = true
const ctx = {
...partialContext,
renderOpts: {
...this.renderOpts,
requireStaticHTML,
// TODO: Determine when dynamic HTML is allowed
supportsDynamicHTML: false,
},
} as const
const payload = await fn(ctx)
Expand Down Expand Up @@ -1296,17 +1295,12 @@ export default class Server {
...partialContext,
renderOpts: {
...this.renderOpts,
requireStaticHTML: true,
supportsDynamicHTML: false,
},
})
if (payload === null) {
return null
}
if (payload.body.isDynamic()) {
throw new Error(
'invariant: expected a static result. This is a bug in Next.js'
)
}
return payload.body.toUnchunkedString()
}

Expand Down Expand Up @@ -1490,6 +1484,17 @@ export default class Server {
delete query.amp
}

if (opts.supportsDynamicHTML === true) {
// Disable dynamic HTML in cases that we know it won't be generated,
// so that we can continue generating a cache key when possible.
opts.supportsDynamicHTML =
!isSSG &&
!isLikeServerless &&
!query.amp &&
!this.minimalMode &&
typeof components.Document.getInitialProps !== 'function'
}

const locale = query.__nextLocale as string
const defaultLocale = isSSG
? this.nextConfig.i18n?.defaultLocale
Expand Down Expand Up @@ -1574,7 +1579,7 @@ export default class Server {
}

let ssgCacheKey =
isPreviewMode || !isSSG || this.minimalMode
isPreviewMode || !isSSG || this.minimalMode || opts.supportsDynamicHTML
? null // Preview mode bypasses the cache
: `${locale ? `/${locale}` : ''}${
(pathname === '/' || resolvedUrlPathname === '/') && locale
Expand Down
19 changes: 16 additions & 3 deletions packages/next/server/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export type RenderOptsPartial = {
defaultLocale?: string
domainLocales?: DomainLocale[]
disableOptimizedLoading?: boolean
requireStaticHTML?: boolean
supportsDynamicHTML?: boolean
concurrentFeatures?: boolean
customServer?: boolean
}
Expand Down Expand Up @@ -295,7 +295,7 @@ export async function renderToHTML(
previewProps,
basePath,
devOnlyCacheBusterQueryString,
requireStaticHTML,
supportsDynamicHTML,
concurrentFeatures,
} = renderOpts

Expand Down Expand Up @@ -883,7 +883,20 @@ export async function renderToHTML(
}
}

const generateStaticHTML = requireStaticHTML || inAmpMode
/**
* Rules of Static & Dynamic HTML:
*
* 1.) We must generate static HTML unless the caller explicitly opts
* in to dynamic HTML support.
*
* 2.) If dynamic HTML support is requested, we must honor that request
* or throw an error. It is the sole responsibility of the caller to
* ensure they aren't e.g. requesting dynamic HTML for an AMP page.
*
* These rules help ensure that other existing features like request caching,
* coalescing, and ISR continue working as intended.
*/
const generateStaticHTML = supportsDynamicHTML !== true
const renderToStream = (element: React.ReactElement) =>
new Promise<Observable<string>>((resolve, reject) => {
const stream = new PassThrough()
Expand Down

0 comments on commit fb70d92

Please sign in to comment.