From eddabd98f8e4e5a82f4341bc1d8926959327919a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?= Date: Thu, 17 Feb 2022 19:21:40 +0100 Subject: [PATCH] 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` --- packages/next/pages/_document.tsx | 7 +- packages/next/server/render.tsx | 6 +- packages/next/shared/lib/html-context.ts | 42 +++++++++++ packages/next/shared/lib/router/router.ts | 2 +- .../shared/lib/router/utils/format-url.ts | 35 ++++++++- packages/next/shared/lib/utils.ts | 74 +------------------ 6 files changed, 85 insertions(+), 81 deletions(-) create mode 100644 packages/next/shared/lib/html-context.ts diff --git a/packages/next/pages/_document.tsx b/packages/next/pages/_document.tsx index 91b0b526fea9..6af1f81fc86a 100644 --- a/packages/next/pages/_document.tsx +++ b/packages/next/pages/_document.tsx @@ -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 = { diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index 4c00eb0b92fc..573fdf5d268f 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -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' diff --git a/packages/next/shared/lib/html-context.ts b/packages/next/shared/lib/html-context.ts new file mode 100644 index 000000000000..25baecbd7bd0 --- /dev/null +++ b/packages/next/shared/lib/html-context.ts @@ -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 + useMaybeDeferContent: MaybeDeferContentHook + crossOrigin?: string + optimizeCss?: boolean + optimizeFonts?: boolean + runtime?: 'edge' | 'nodejs' +} + +export const HtmlContext = createContext(null as any) +if (process.env.NODE_ENV !== 'production') { + HtmlContext.displayName = 'HtmlContext' +} diff --git a/packages/next/shared/lib/router/router.ts b/packages/next/shared/lib/router/router.ts index d6ca2f98fba8..d3e172431880 100644 --- a/packages/next/shared/lib/router/router.ts +++ b/packages/next/shared/lib/router/router.ts @@ -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 { diff --git a/packages/next/shared/lib/router/utils/format-url.ts b/packages/next/shared/lib/router/utils/format-url.ts index bef24b4e3e7d..205ab30a7142 100644 --- a/packages/next/shared/lib/router/utils/format-url.ts +++ b/packages/next/shared/lib/router/utils/format-url.ts @@ -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) +} diff --git a/packages/next/shared/lib/utils.ts b/packages/next/shared/lib/utils.ts index 94196af4f597..f18e19f6cf45 100644 --- a/packages/next/shared/lib/utils.ts +++ b/packages/next/shared/lib/utils.ts @@ -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 - 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(null as any) -if (process.env.NODE_ENV !== 'production') { - HtmlContext.displayName = 'HtmlContext' -} - export interface CacheFs { readFile(f: string): Promise readFileSync(f: string): string