refactor: move HtmlContext (#34482)

The shared utils file included an import from `react` (because it was using `createContext`) which seems to be unnecessary in the Middleware bundle.

With this PR and steps #34425 laid out, the bundle size did decrease without breaking functionality.

![image](https://user-images.githubusercontent.com/18369201/154508389-0a813e3e-1e07-4c45-8b71-444cc54a7f9e.png)

Fixes #34425

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`
This commit is contained in:
Balázs Orbán 2022-02-17 19:21:40 +01:00 committed by GitHub
parent d4eea7593a
commit eddabd98f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 85 additions and 81 deletions

View file

@ -1,11 +1,9 @@
import React, { Component, ReactElement, ReactNode, useContext } from 'react'
import { OPTIMIZED_FONT_PROVIDERS } from '../shared/lib/constants'
import {
import type {
DocumentContext,
DocumentInitialProps,
DocumentProps,
HtmlContext,
HtmlProps,
} from '../shared/lib/utils'
import { BuildManifest, getPageFiles } from '../server/get-page-files'
import { cleanAmpPath } from '../server/utils'
@ -13,6 +11,9 @@ import { htmlEscapeJsonString } from '../server/htmlescape'
import Script, { ScriptProps } from '../client/script'
import isError from '../lib/is-error'
import { HtmlContext } from '../shared/lib/html-context'
import type { HtmlProps } from '../shared/lib/html-context'
export { DocumentContext, DocumentInitialProps, DocumentProps }
export type OriginProps = {

View file

@ -37,8 +37,6 @@ import {
DocumentInitialProps,
DocumentProps,
DocumentContext,
HtmlContext,
HtmlProps,
getDisplayName,
isResSent,
loadGetInitialProps,
@ -46,6 +44,10 @@ import {
RenderPage,
RenderPageResult,
} from '../shared/lib/utils'
import { HtmlContext } from '../shared/lib/html-context'
import type { HtmlProps } from '../shared/lib/html-context'
import type { NextApiRequestCookies, __ApiPreviewProps } from './api-utils'
import { denormalizePagePath } from './denormalize-page-path'
import type { FontManifest } from './font-utils'

View file

@ -0,0 +1,42 @@
import type { BuildManifest } from '../../server/get-page-files'
import type { NEXT_DATA, MaybeDeferContentHook } from './utils'
import { createContext } from 'react'
export type HtmlProps = {
__NEXT_DATA__: NEXT_DATA
dangerousAsPath: string
docComponentsRendered: {
Html?: boolean
Main?: boolean
Head?: boolean
NextScript?: boolean
}
buildManifest: BuildManifest
ampPath: string
inAmpMode: boolean
hybridAmp: boolean
isDevelopment: boolean
dynamicImports: string[]
assetPrefix?: string
canonicalBase: string
headTags: any[]
unstable_runtimeJS?: false
unstable_JsPreload?: false
devOnlyCacheBusterQueryString: string
scriptLoader: { afterInteractive?: string[]; beforeInteractive?: any[] }
locale?: string
disableOptimizedLoading?: boolean
styles?: React.ReactElement[] | React.ReactFragment
head?: Array<JSX.Element | null>
useMaybeDeferContent: MaybeDeferContentHook
crossOrigin?: string
optimizeCss?: boolean
optimizeFonts?: boolean
runtime?: 'edge' | 'nodejs'
}
export const HtmlContext = createContext<HtmlProps>(null as any)
if (process.env.NODE_ENV !== 'production') {
HtmlContext.displayName = 'HtmlContext'
}

View file

@ -22,7 +22,6 @@ import { normalizeLocalePath } from '../i18n/normalize-locale-path'
import mitt from '../mitt'
import {
AppContextType,
formatWithValidation,
getLocationOrigin,
getURL,
loadGetInitialProps,
@ -38,6 +37,7 @@ import resolveRewrites from './utils/resolve-rewrites'
import { getRouteMatcher } from './utils/route-matcher'
import { getRouteRegex } from './utils/route-regex'
import { getMiddlewareRegex } from './utils/get-middleware-regex'
import { formatWithValidation } from './utils/format-url'
declare global {
interface Window {

View file

@ -20,8 +20,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
import { UrlObject } from 'url'
import { ParsedUrlQuery } from 'querystring'
import type { UrlObject } from 'url'
import type { ParsedUrlQuery } from 'querystring'
import * as querystring from './querystring'
const slashedProtocols = /https?|ftp|gopher|file/
@ -71,3 +71,34 @@ export function formatUrl(urlObj: UrlObject) {
return `${protocol}${host}${pathname}${search}${hash}`
}
export const urlObjectKeys = [
'auth',
'hash',
'host',
'hostname',
'href',
'path',
'pathname',
'port',
'protocol',
'query',
'search',
'slashes',
]
export function formatWithValidation(url: UrlObject): string {
if (process.env.NODE_ENV === 'development') {
if (url !== null && typeof url === 'object') {
Object.keys(url).forEach((key) => {
if (urlObjectKeys.indexOf(key) === -1) {
console.warn(
`Unknown key passed via urlObject into url.format: ${key}`
)
}
})
}
}
return formatUrl(url)
}

View file

@ -1,4 +1,4 @@
import type { BuildManifest } from '../../server/get-page-files'
import type { HtmlProps } from './html-context'
import type { ComponentType } from 'react'
import type { DomainLocale } from '../../server/config'
import type { Env } from '@next/env'
@ -6,9 +6,6 @@ import type { IncomingMessage, ServerResponse } from 'http'
import type { NextRouter } from './router/router'
import type { ParsedUrlQuery } from 'querystring'
import type { PreviewData } from 'next/types'
import type { UrlObject } from 'url'
import { createContext } from 'react'
import { formatUrl } from './router/utils/format-url'
export type NextComponentType<
C extends BaseContext = NextPageContext,
@ -195,39 +192,6 @@ export type MaybeDeferContentHook = (
contentFn: () => JSX.Element
) => [boolean, JSX.Element]
export type HtmlProps = {
__NEXT_DATA__: NEXT_DATA
dangerousAsPath: string
docComponentsRendered: {
Html?: boolean
Main?: boolean
Head?: boolean
NextScript?: boolean
}
buildManifest: BuildManifest
ampPath: string
inAmpMode: boolean
hybridAmp: boolean
isDevelopment: boolean
dynamicImports: string[]
assetPrefix?: string
canonicalBase: string
headTags: any[]
unstable_runtimeJS?: false
unstable_JsPreload?: false
devOnlyCacheBusterQueryString: string
scriptLoader: { afterInteractive?: string[]; beforeInteractive?: any[] }
locale?: string
disableOptimizedLoading?: boolean
styles?: React.ReactElement[] | React.ReactFragment
head?: Array<JSX.Element | null>
useMaybeDeferContent: MaybeDeferContentHook
crossOrigin?: string
optimizeCss?: boolean
optimizeFonts?: boolean
runtime?: 'edge' | 'nodejs'
}
/**
* Next `API` route request
*/
@ -410,37 +374,6 @@ export async function loadGetInitialProps<
return props
}
export const urlObjectKeys = [
'auth',
'hash',
'host',
'hostname',
'href',
'path',
'pathname',
'port',
'protocol',
'query',
'search',
'slashes',
]
export function formatWithValidation(url: UrlObject): string {
if (process.env.NODE_ENV === 'development') {
if (url !== null && typeof url === 'object') {
Object.keys(url).forEach((key) => {
if (urlObjectKeys.indexOf(key) === -1) {
console.warn(
`Unknown key passed via urlObject into url.format: ${key}`
)
}
})
}
}
return formatUrl(url)
}
export const SP = typeof performance !== 'undefined'
export const ST =
SP &&
@ -449,11 +382,6 @@ export const ST =
export class DecodeError extends Error {}
export const HtmlContext = createContext<HtmlProps>(null as any)
if (process.env.NODE_ENV !== 'production') {
HtmlContext.displayName = 'HtmlContext'
}
export interface CacheFs {
readFile(f: string): Promise<string>
readFileSync(f: string): string