import React, { Component, ReactElement, ReactNode, useContext } from 'react' import { OPTIMIZED_FONT_PROVIDERS } from '../shared/lib/constants' import { DocumentContext, DocumentInitialProps, DocumentProps, HtmlContext, HtmlProps, } from '../shared/lib/utils' import { BuildManifest, getPageFiles } from '../server/get-page-files' import { cleanAmpPath } from '../server/utils' import { htmlEscapeJsonString } from '../server/htmlescape' import Script, { ScriptProps } from '../client/script' import isError from '../lib/is-error' export { DocumentContext, DocumentInitialProps, DocumentProps } export type OriginProps = { nonce?: string crossOrigin?: string } type DocumentFiles = { sharedFiles: readonly string[] pageFiles: readonly string[] allFiles: readonly string[] } function getDocumentFiles( buildManifest: BuildManifest, pathname: string, inAmpMode: boolean ): DocumentFiles { const sharedFiles: readonly string[] = getPageFiles(buildManifest, '/_app') const pageFiles: readonly string[] = inAmpMode ? [] : getPageFiles(buildManifest, pathname) return { sharedFiles, pageFiles, allFiles: [...new Set([...sharedFiles, ...pageFiles])], } } function getPolyfillScripts(context: HtmlProps, props: OriginProps) { // polyfills.js has to be rendered as nomodule without async // It also has to be the first script to load const { assetPrefix, buildManifest, devOnlyCacheBusterQueryString, disableOptimizedLoading, crossOrigin, } = context return buildManifest.polyfillFiles .filter( (polyfill) => polyfill.endsWith('.js') && !polyfill.endsWith('.module.js') ) .map((polyfill) => ( )) } function getPreNextScripts(context: HtmlProps, props: OriginProps) { const { scriptLoader, disableOptimizedLoading, crossOrigin } = context return (scriptLoader.beforeInteractive || []).map( (file: ScriptProps, index: number) => { const { strategy, ...scriptProps } = file return ( ) } ) } function getDynamicChunks( context: HtmlProps, props: OriginProps, files: DocumentFiles ) { const { dynamicImports, assetPrefix, isDevelopment, devOnlyCacheBusterQueryString, disableOptimizedLoading, crossOrigin, } = context return dynamicImports.map((file) => { if (!file.endsWith('.js') || files.allFiles.includes(file)) return null return ( ) }) } function getScripts( context: HtmlProps, props: OriginProps, files: DocumentFiles ) { const { assetPrefix, buildManifest, isDevelopment, devOnlyCacheBusterQueryString, disableOptimizedLoading, crossOrigin, } = context const normalScripts = files.allFiles.filter((file) => file.endsWith('.js')) const lowPriorityScripts = buildManifest.lowPriorityFiles?.filter((file) => file.endsWith('.js') ) return [...normalScripts, ...lowPriorityScripts].map((file) => { return ( ) }) } /** * `Document` component handles the initial `document` markup and renders only on the server side. * Commonly used for implementing server side rendering for `css-in-js` libraries. */ export default class Document
extends Component