From ed4d009841d133211440b4479d36e85813af0584 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sat, 14 May 2022 23:20:24 +0200 Subject: [PATCH] Drop the unstable web vital hook and remove exports of flush effects (#36912) * remove the experimental web vital hook api * remove the exported flush effects api and only error on development, keep only usage to styled-jsx for web vital hook API: The usage is not widly adopted since the existing exported vital api could do the same work. In the future we'll deprecate the `_app.server` in favor of `_app` in server component pages. so that this api won't be required. for flush effects api: other css-in-js libs are not using the same approach like styled-jsx which holding a style registry and could flush it during streaming. emotion-js and styled-components are still relying on `Document.getInitialProps` atm and we have supported it in latest canary --- docs/api-reference/next/streaming.md | 48 ---------- errors/client-flush-effects.md | 24 ----- errors/manifest.json | 8 -- errors/multiple-flush-effects.md | 9 -- packages/next/client/index.tsx | 66 ++++++------- packages/next/client/streaming/index.ts | 2 - packages/next/client/streaming/vitals.ts | 50 ---------- packages/next/server/render.tsx | 92 ++++++------------- packages/next/server/view-render.tsx | 41 +-------- packages/next/shared/lib/flush-effects.ts | 21 ----- .../app/pages/use-flush-effect/client.js | 36 -------- .../app/pages/use-flush-effect/custom.js | 12 --- .../pages/use-flush-effect/multiple-calls.js | 23 ----- test/integration/react-18/test/concurrent.js | 29 ------ .../relay-analytics-disabled/pages/index.js | 3 - .../test/index.test.js | 2 - .../integration/relay-analytics/pages/_app.js | 3 - .../relay-analytics/pages/index.js | 17 ---- .../relay-analytics/test/index.test.js | 40 +------- 19 files changed, 61 insertions(+), 465 deletions(-) delete mode 100644 errors/client-flush-effects.md delete mode 100644 errors/multiple-flush-effects.md delete mode 100644 packages/next/client/streaming/vitals.ts delete mode 100644 packages/next/shared/lib/flush-effects.ts delete mode 100644 test/integration/react-18/app/pages/use-flush-effect/client.js delete mode 100644 test/integration/react-18/app/pages/use-flush-effect/custom.js delete mode 100644 test/integration/react-18/app/pages/use-flush-effect/multiple-calls.js diff --git a/docs/api-reference/next/streaming.md b/docs/api-reference/next/streaming.md index 90b651435677..86a6ade3c4fd 100644 --- a/docs/api-reference/next/streaming.md +++ b/docs/api-reference/next/streaming.md @@ -6,54 +6,6 @@ description: Streaming related APIs to build Next.js apps in streaming SSR or wi The experimental `next/streaming` module provides streaming related APIs to port the existing functionality of Next.js apps to streaming scenarios and facilitate the usage of React Server Components. -## unstable_useWebVitalsReport - -Next.js provides an `_app` component-level function, [`reportWebVitals`](docs/advanced-features/measuring-performance), for tracking performance metrics. With Server Components, you may have a pure server-side custom `_app` component (which doesn't run client effects) so the existing API won't work. - -With the new `unstable_useWebVitalsReport` API, you're able to track [Core Web Vitals](https://nextjs.org/learn/seo/web-performance) in client components: - -```jsx -// pages/_app.js -import { unstable_useWebVitalsReport } from 'next/streaming' - -export default function Home() { - unstable_useWebVitalsReport((data) => { - console.log(data) - }) - - return
Home Page
-} -``` - -This method could also be used to replace statically exported `reportWebVitals` functions in your existing `_app`: - -```jsx -// pages/_app.server.js -import Layout from '../components/layout.client.js' - -export default function App({ children }) { - return {children} -} -``` - -```jsx -// components/layout.client.js -import { unstable_useWebVitalsReport } from 'next/streaming' - -export default function Layout() { - unstable_useWebVitalsReport((data) => { - console.log(data) - }) - - return ( -
-

Hello

-
{children}
-
- ) -} -``` - ## unstable_useRefreshRoot Since Server Components are rendered on the server-side, in some cases you might need to partially refresh content from the server. diff --git a/errors/client-flush-effects.md b/errors/client-flush-effects.md deleted file mode 100644 index 18ca8dd126cc..000000000000 --- a/errors/client-flush-effects.md +++ /dev/null @@ -1,24 +0,0 @@ -# `unstable_useFlushEffects` can not be called on the client - -#### Why This Error Occurred - -The `unstable_useFlushEffects` hook was executed while rendering a component on the client, or in another unsupported environment. - -#### Possible Ways to Fix It - -The `unstable_useFlushEffects` hook can only be called while _server rendering a client component_. As a best practice, we recommend creating a wrapper hook: - -```jsx -// lib/use-style-libraries.js -import { unstable_useFlushEffects as useFlushEffects } from 'next/streaming' - -export default function useStyleLibraries() { - if (typeof window === 'undefined') { - // eslint-disable-next-line react-hooks/rules-of-hooks - useFlushEffects([ - /* ... */ - ]) - } - /* ... */ -} -``` diff --git a/errors/manifest.json b/errors/manifest.json index 8e5375a6d5a1..00ec91db0c7f 100644 --- a/errors/manifest.json +++ b/errors/manifest.json @@ -638,14 +638,6 @@ "title": "opening-an-issue", "path": "/errors/opening-an-issue.md" }, - { - "title": "multiple-flush-effects", - "path": "/errors/multiple-flush-effects.md" - }, - { - "title": "client-flush-effects", - "path": "/errors/client-flush-effects.md" - }, { "title": "import-next", "path": "/errors/import-next.md" diff --git a/errors/multiple-flush-effects.md b/errors/multiple-flush-effects.md deleted file mode 100644 index b19e88edd04b..000000000000 --- a/errors/multiple-flush-effects.md +++ /dev/null @@ -1,9 +0,0 @@ -# The `unstable_useFlushEffects` hook cannot be used more than once. - -#### Why This Error Occurred - -The `unstable_useFlushEffects` hook is being used more than once while a page is being rendered. - -#### Possible Ways to Fix It - -The `unstable_useFlushEffects` hook should only be called inside the body of the `pages/_app` component, before returning any `` boundaries. Restructure your application to prevent extraneous calls. diff --git a/packages/next/client/index.tsx b/packages/next/client/index.tsx index f966b50224db..662ba6b8bd14 100644 --- a/packages/next/client/index.tsx +++ b/packages/next/client/index.tsx @@ -32,10 +32,6 @@ import measureWebVitals from './performance-relayer' import { RouteAnnouncer } from './route-announcer' import { createRouter, makePublicRouterInstance } from './router' import { getProperError } from '../lib/is-error' -import { - flushBufferedVitalsMetrics, - trackWebVitalMetric, -} from './streaming/vitals' import { RefreshContext } from './streaming/refresh' import { ImageConfigContext } from '../shared/lib/image-config-context' import { ImageConfigComplete } from '../shared/lib/image-config' @@ -291,38 +287,38 @@ export async function hydrate(opts?: { beforeRender?: () => Promise }) { const { component: app, exports: mod } = appEntrypoint CachedApp = app as AppComponent - const exportedReportWebVitals = mod && mod.reportWebVitals - onPerfEntry = ({ - id, - name, - startTime, - value, - duration, - entryType, - entries, - }: any): void => { - // Combines timestamp with random number for unique ID - const uniqueID: string = `${Date.now()}-${ - Math.floor(Math.random() * (9e12 - 1)) + 1e12 - }` - let perfStartEntry: string | undefined - - if (entries && entries.length) { - perfStartEntry = entries[0].startTime - } - - const webVitals: NextWebVitalsMetric = { - id: id || uniqueID, + if (mod && mod.reportWebVitals) { + onPerfEntry = ({ + id, name, - startTime: startTime || perfStartEntry, - value: value == null ? duration : value, - label: - entryType === 'mark' || entryType === 'measure' - ? 'custom' - : 'web-vital', + startTime, + value, + duration, + entryType, + entries, + }: any): void => { + // Combines timestamp with random number for unique ID + const uniqueID: string = `${Date.now()}-${ + Math.floor(Math.random() * (9e12 - 1)) + 1e12 + }` + let perfStartEntry: string | undefined + + if (entries && entries.length) { + perfStartEntry = entries[0].startTime + } + + const webVitals: NextWebVitalsMetric = { + id: id || uniqueID, + name, + startTime: startTime || perfStartEntry, + value: value == null ? duration : value, + label: + entryType === 'mark' || entryType === 'measure' + ? 'custom' + : 'web-vital', + } + mod.reportWebVitals(webVitals) } - exportedReportWebVitals?.(webVitals) - trackWebVitalMetric(webVitals) } const pageEntrypoint = @@ -1033,8 +1029,6 @@ function Root({ // don't cause any hydration delay: React.useEffect(() => { measureWebVitals(onPerfEntry) - - flushBufferedVitalsMetrics() }, []) if (process.env.__NEXT_TEST_MODE) { diff --git a/packages/next/client/streaming/index.ts b/packages/next/client/streaming/index.ts index d072e85795ae..566fab06ab74 100644 --- a/packages/next/client/streaming/index.ts +++ b/packages/next/client/streaming/index.ts @@ -1,3 +1 @@ export { useRefreshRoot as unstable_useRefreshRoot } from './refresh' -export { useWebVitalsReport as unstable_useWebVitalsReport } from './vitals' -export { useFlushEffects as unstable_useFlushEffects } from '../../shared/lib/flush-effects' diff --git a/packages/next/client/streaming/vitals.ts b/packages/next/client/streaming/vitals.ts deleted file mode 100644 index e239470457a5..000000000000 --- a/packages/next/client/streaming/vitals.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { useEffect, useRef } from 'react' -import { NextWebVitalsMetric } from '../../pages/_app' - -type ReportWebVitalsCallback = (webVitals: NextWebVitalsMetric) => any -export const webVitalsCallbacks = new Set() - -let flushed = false -const metrics: NextWebVitalsMetric[] = [] - -export function getBufferedVitalsMetrics() { - return metrics -} - -export function flushBufferedVitalsMetrics() { - flushed = true - metrics.length = 0 -} - -export function trackWebVitalMetric(metric: NextWebVitalsMetric) { - metrics.push(metric) - webVitalsCallbacks.forEach((callback) => callback(metric)) -} - -export function useWebVitalsReport(callback: ReportWebVitalsCallback) { - const metricIndexRef = useRef(0) - - if (process.env.NODE_ENV === 'development') { - if (flushed) { - console.error( - 'The `useWebVitalsReport` hook was called too late -- did you use it inside of a boundary?' - ) - } - } - - useEffect(() => { - // Flush calculated metrics - const reportMetric = (metric: NextWebVitalsMetric) => { - callback(metric) - metricIndexRef.current = metrics.length - } - for (let i = metricIndexRef.current; i < metrics.length; i++) { - reportMetric(metrics[i]) - } - - webVitalsCallbacks.add(reportMetric) - return () => { - webVitalsCallbacks.delete(reportMetric) - } - }, [callback]) -} diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index 788cb8571c92..d4935d10b3da 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -79,7 +79,6 @@ import { continueFromInitialStream, } from './node-web-streams-helper' import { ImageConfigContext } from '../shared/lib/image-config-context' -import { FlushEffectsContext } from '../shared/lib/flush-effects' import { interopDefault } from '../lib/interop-default' import stripAnsi from 'next/dist/compiled/strip-ansi' import { urlQueryToSearchParams } from '../shared/lib/router/utils/querystring' @@ -794,62 +793,33 @@ export async function renderToHTML( return <>{styles} } - let flushEffects: Array<() => React.ReactNode> | null = null - function FlushEffectContainer({ children }: { children: JSX.Element }) { - // If the client tree suspends, this component will be rendered multiple - // times before we flush. To ensure we don't call old callbacks corresponding - // to a previous render, we clear any registered callbacks whenever we render. - flushEffects = null - - const flushEffectsImpl = React.useCallback( - (callbacks: Array<() => React.ReactNode>) => { - if (flushEffects) { - throw new Error( - 'The `useFlushEffects` hook cannot be used more than once.' + - '\nRead more: https://nextjs.org/docs/messages/multiple-flush-effects' - ) - } - flushEffects = callbacks - }, - [] - ) - - return ( - - {children} - - ) - } - const AppContainer = ({ children }: { children: JSX.Element }) => ( - - - - { - head = state - }, - updateScripts: (scripts) => { - scriptLoader = scripts - }, - scripts: initialScripts, - mountedInstances: new Set(), - }} + + + { + head = state + }, + updateScripts: (scripts) => { + scriptLoader = scripts + }, + scripts: initialScripts, + mountedInstances: new Set(), + }} + > + reactLoadableModules.push(moduleName)} > - reactLoadableModules.push(moduleName)} - > - - - {children} - - - - - - - + + + {children} + + + + + + ) // The `useId` API uses the path indexes to generate an ID for each node. @@ -1480,17 +1450,7 @@ export async function renderToHTML( // this must be called inside bodyResult so appWrappers is // up to date when `wrapApp` is called const flushEffectHandler = (): string => { - const allFlushEffects = [ - styledJsxFlushEffect, - ...(flushEffects || []), - ] - const flushed = ReactDOMServer.renderToString( - <> - {allFlushEffects.map((flushEffect, i) => ( - {flushEffect()} - ))} - - ) + const flushed = ReactDOMServer.renderToString(styledJsxFlushEffect()) return flushed } diff --git a/packages/next/server/view-render.tsx b/packages/next/server/view-render.tsx index 8127aef1675e..8fbdaafdec75 100644 --- a/packages/next/server/view-render.tsx +++ b/packages/next/server/view-render.tsx @@ -16,7 +16,6 @@ import { createBufferedTransformStream, continueFromInitialStream, } from './node-web-streams-helper' -import { FlushEffectsContext } from '../shared/lib/flush-effects' import { isDynamicRoute } from '../shared/lib/router/utils' import { tryGetPreviewData } from './api-utils/node' @@ -389,37 +388,8 @@ export async function renderToHTML( return <>{styles} } - let flushEffects: Array<() => React.ReactNode> | null = null - function FlushEffectContainer({ children }: { children: JSX.Element }) { - // If the client tree suspends, this component will be rendered multiple - // times before we flush. To ensure we don't call old callbacks corresponding - // to a previous render, we clear any registered callbacks whenever we render. - flushEffects = null - - const flushEffectsImpl = React.useCallback( - (callbacks: Array<() => React.ReactNode>) => { - if (flushEffects) { - throw new Error( - 'The `useFlushEffects` hook cannot be used more than once.' + - '\nRead more: https://nextjs.org/docs/messages/multiple-flush-effects' - ) - } - flushEffects = callbacks - }, - [] - ) - - return ( - - {children} - - ) - } - const AppContainer = ({ children }: { children: JSX.Element }) => ( - - {children} - + {children} ) const renderServerComponentData = isFlight @@ -462,14 +432,7 @@ export async function renderToHTML( }) const flushEffectHandler = (): string => { - const allFlushEffects = [styledJsxFlushEffect, ...(flushEffects || [])] - const flushed = ReactDOMServer.renderToString( - <> - {allFlushEffects.map((flushEffect, i) => ( - {flushEffect()} - ))} - - ) + const flushed = ReactDOMServer.renderToString(styledJsxFlushEffect()) return flushed } diff --git a/packages/next/shared/lib/flush-effects.ts b/packages/next/shared/lib/flush-effects.ts deleted file mode 100644 index 341c126ed9e6..000000000000 --- a/packages/next/shared/lib/flush-effects.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createContext, useContext } from 'react' - -export type FlushEffectsHook = (callbacks: Array<() => React.ReactNode>) => void - -export const FlushEffectsContext: React.Context = - createContext(null as any) - -export function useFlushEffects(callbacks: Array<() => React.ReactNode>): void { - const flushEffectsImpl = useContext(FlushEffectsContext) - if (!flushEffectsImpl) { - throw new Error( - `useFlushEffects can not be called on the client.` + - `\nRead more: https://nextjs.org/docs/messages/client-flush-effects` - ) - } - return flushEffectsImpl(callbacks) -} - -if (process.env.NODE_ENV !== 'production') { - FlushEffectsContext.displayName = 'FlushEffectsContext' -} diff --git a/test/integration/react-18/app/pages/use-flush-effect/client.js b/test/integration/react-18/app/pages/use-flush-effect/client.js deleted file mode 100644 index 884d7f9266ec..000000000000 --- a/test/integration/react-18/app/pages/use-flush-effect/client.js +++ /dev/null @@ -1,36 +0,0 @@ -import { unstable_useFlushEffects } from 'next/streaming' -import React from 'react' - -class ErrorBoundary extends React.Component { - state = {} - - static getDerivedStateFromError(error) { - return { error } - } - - render() { - return this.state.error ? ( - {this.state.error.message} - ) : ( - this.props.children - ) - } -} - -function Component() { - unstable_useFlushEffects([]) - return null -} - -export default function Client() { - return ( - - - - ) -} - -export async function getServerSideProps() { - // disable exporting this page - return { props: {} } -} diff --git a/test/integration/react-18/app/pages/use-flush-effect/custom.js b/test/integration/react-18/app/pages/use-flush-effect/custom.js deleted file mode 100644 index f8d09da3462d..000000000000 --- a/test/integration/react-18/app/pages/use-flush-effect/custom.js +++ /dev/null @@ -1,12 +0,0 @@ -import { unstable_useFlushEffects } from 'next/streaming' - -export default function Custom() { - if (typeof window === 'undefined') { - // eslint-disable-next-line react-hooks/rules-of-hooks - unstable_useFlushEffects([ - () => foo, - () => bar, - ]) - } - return null -} diff --git a/test/integration/react-18/app/pages/use-flush-effect/multiple-calls.js b/test/integration/react-18/app/pages/use-flush-effect/multiple-calls.js deleted file mode 100644 index 5417eac3457a..000000000000 --- a/test/integration/react-18/app/pages/use-flush-effect/multiple-calls.js +++ /dev/null @@ -1,23 +0,0 @@ -import { unstable_useFlushEffects } from 'next/streaming' - -function Component() { - if (typeof window === 'undefined') { - // eslint-disable-next-line react-hooks/rules-of-hooks - unstable_useFlushEffects([]) - } - return null -} - -export default function MultipleCalls() { - return ( - <> - - - - ) -} - -export async function getServerSideProps() { - // disable exporting this page - return { props: {} } -} diff --git a/test/integration/react-18/test/concurrent.js b/test/integration/react-18/test/concurrent.js index f849a0a80c94..a1b3c3a8da71 100644 --- a/test/integration/react-18/test/concurrent.js +++ b/test/integration/react-18/test/concurrent.js @@ -16,22 +16,6 @@ export default (context, _render) => { } } - it('throws if useFlushEffects is used more than once', async () => { - await renderViaHTTP(context.appPort, '/use-flush-effect/multiple-calls') - expect(context.stderr).toContain( - 'Error: The `useFlushEffects` hook cannot be used more than once.' - ) - }) - - it('throws if useFlushEffects is called on the client', async () => { - await withBrowser('/use-flush-effect/client', async (browser) => { - await check( - () => browser.waitForElementByCss('#error').text(), - /useFlushEffects can not be called on the client/ - ) - }) - }) - it('flushes styled-jsx styles as the page renders', async () => { const html = await renderViaHTTP( context.appPort, @@ -51,17 +35,4 @@ export default (context, _render) => { ) }) }) - - it('flushes custom effects', async () => { - await withBrowser('/use-flush-effect/custom', async (browser) => { - await check( - () => browser.waitForElementByCss('#custom-flush-effect-1').text(), - /foo/ - ) - await check( - () => browser.waitForElementByCss('#custom-flush-effect-2').text(), - /bar/ - ) - }) - }) } diff --git a/test/integration/relay-analytics-disabled/pages/index.js b/test/integration/relay-analytics-disabled/pages/index.js index d8064b2d5b1a..46c828a80fd0 100644 --- a/test/integration/relay-analytics-disabled/pages/index.js +++ b/test/integration/relay-analytics-disabled/pages/index.js @@ -1,5 +1,3 @@ -import { getBufferedVitalsMetrics } from 'next/dist/client/streaming/vitals' - if (typeof navigator !== 'undefined') { window.__BEACONS = window.__BEACONS || [] @@ -22,7 +20,6 @@ export default () => {

Foo!

bar!

-

{`buffered metrics: ${getBufferedVitalsMetrics().length}`}

) } diff --git a/test/integration/relay-analytics-disabled/test/index.test.js b/test/integration/relay-analytics-disabled/test/index.test.js index 0994f67ddb15..f7dc28e64799 100644 --- a/test/integration/relay-analytics-disabled/test/index.test.js +++ b/test/integration/relay-analytics-disabled/test/index.test.js @@ -30,13 +30,11 @@ describe('Analytics relayer (disabled)', () => { const browser = await webdriver(appPort, '/') await browser.waitForElementByCss('h1') const h1Text = await browser.elementByCss('h1').text() - const pText = await browser.elementByCss('p').text() const firstContentfulPaint = parseFloat( await browser.eval('localStorage.getItem("FCP")') ) expect(h1Text).toMatch(/Foo!/) - expect(pText).toMatch('buffered metrics: 0') expect(firstContentfulPaint).not.toBeNaN() expect(firstContentfulPaint).toBeGreaterThan(0) diff --git a/test/integration/relay-analytics/pages/_app.js b/test/integration/relay-analytics/pages/_app.js index bbe74d5e1f87..44f936f124f0 100644 --- a/test/integration/relay-analytics/pages/_app.js +++ b/test/integration/relay-analytics/pages/_app.js @@ -8,8 +8,6 @@ export default class MyApp extends App {} Method is experimental and will eventually be handled in a Next.js plugin */ -// Below comment will be used for replacing exported report method with hook based one. -///* reportWebVitals export function reportWebVitals(data) { const name = data.name || data.entryType localStorage.setItem( @@ -19,4 +17,3 @@ export function reportWebVitals(data) { const countMap = window.__BEACONS_COUNT countMap.set(name, (countMap.get(name) || 0) + 1) } -// reportWebVitals */ diff --git a/test/integration/relay-analytics/pages/index.js b/test/integration/relay-analytics/pages/index.js index 82b506fcc7bc..cf1d4664d88a 100644 --- a/test/integration/relay-analytics/pages/index.js +++ b/test/integration/relay-analytics/pages/index.js @@ -1,7 +1,3 @@ -/* global localStorage */ -import { unstable_useWebVitalsReport } from 'next/streaming' -import { getBufferedVitalsMetrics } from 'next/dist/client/streaming/vitals' - if (typeof navigator !== 'undefined') { window.__BEACONS = window.__BEACONS || [] window.__BEACONS_COUNT = new Map() @@ -22,23 +18,10 @@ if (typeof navigator !== 'undefined') { export default () => { // Below comment will be used for replacing exported report method with hook based one. - ///* unstable_useWebVitalsReport - unstable_useWebVitalsReport((data) => { - const name = data.name || data.entryType - localStorage.setItem( - name, - data.value !== undefined ? data.value : data.startTime - ) - const countMap = window.__BEACONS_COUNT - countMap.set(name, (countMap.get(name) || 0) + 1) - }) - // unstable_useWebVitalsReport */ - return (

Foo!

bar!

-

{`buffered metrics: ${getBufferedVitalsMetrics().length}`}

) } diff --git a/test/integration/relay-analytics/test/index.test.js b/test/integration/relay-analytics/test/index.test.js index 4a5f6537a967..d4140e36706d 100644 --- a/test/integration/relay-analytics/test/index.test.js +++ b/test/integration/relay-analytics/test/index.test.js @@ -2,18 +2,9 @@ import { join } from 'path' import webdriver from 'next-webdriver' -import { - File, - killApp, - findPort, - nextBuild, - nextStart, - check, -} from 'next-test-utils' +import { killApp, findPort, nextBuild, nextStart, check } from 'next-test-utils' const appDir = join(__dirname, '../') -const customApp = new File(join(appDir, 'pages/_app.js')) -const indexPage = new File(join(appDir, 'pages/index.js')) let appPort let server @@ -33,31 +24,8 @@ async function killServer() { } describe('Analytics relayer with exported method', () => { - beforeAll(async () => { - // Keep app exported reporting and comment the hook one - indexPage.replace('///* unstable_useWebVitalsReport', '/*') - indexPage.replace('// unstable_useWebVitalsReport */', '*/') - await buildApp() - }) - afterAll(async () => { - indexPage.restore() - await killServer() - }) - runTest() -}) - -describe('Analytics relayer with hook', () => { - beforeAll(async () => { - // Keep hook reporting and comment the app exported one - customApp.replace('///* reportWebVitals', '/*') - customApp.replace('// reportWebVitals */', '*/') - await buildApp() - }) - - afterAll(async () => { - customApp.restore() - await killServer() - }) + beforeAll(async () => await buildApp()) + afterAll(async () => await killServer()) runTest() }) @@ -67,7 +35,6 @@ function runTest() { await browser.waitForElementByCss('h1') const h1Text = await browser.elementByCss('h1').text() - const pText = await browser.elementByCss('p').text() const data = parseFloat( await browser.eval('localStorage.getItem("Next.js-hydration")') ) @@ -82,7 +49,6 @@ function runTest() { ) let cls = await browser.eval('localStorage.getItem("CLS")') expect(h1Text).toMatch(/Foo!/) - expect(pText).toMatch('buffered metrics: 0') expect(data).not.toBeNaN() expect(data).toBeGreaterThan(0) expect(firstByte).not.toBeNaN()