Skip to content

Commit

Permalink
refactor: move HtmlContext (vercel#34482)
Browse files Browse the repository at this point in the history
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 vercel#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 vercel#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`
  • Loading branch information
balazsorban44 authored Feb 17, 2022
1 parent d4eea75 commit eddabd9
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 81 deletions.
7 changes: 4 additions & 3 deletions packages/next/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
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'
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 = {
Expand Down
6 changes: 4 additions & 2 deletions packages/next/server/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,17 @@ import {
DocumentInitialProps,
DocumentProps,
DocumentContext,
HtmlContext,
HtmlProps,
getDisplayName,
isResSent,
loadGetInitialProps,
NextComponentType,
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'
Expand Down
42 changes: 42 additions & 0 deletions packages/next/shared/lib/html-context.ts
Original file line number Diff line number Diff line change
@@ -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'
}
2 changes: 1 addition & 1 deletion packages/next/shared/lib/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { normalizeLocalePath } from '../i18n/normalize-locale-path'
import mitt from '../mitt'
import {
AppContextType,
formatWithValidation,
getLocationOrigin,
getURL,
loadGetInitialProps,
Expand All @@ -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 {
Expand Down
35 changes: 33 additions & 2 deletions packages/next/shared/lib/router/utils/format-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down Expand Up @@ -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)
}
74 changes: 1 addition & 73 deletions packages/next/shared/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
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'
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,
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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 &&
Expand All @@ -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
Expand Down

0 comments on commit eddabd9

Please sign in to comment.