chore: show large data warning once per page on prod (#46323)
<!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change(s) that you're making: --> ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Related * Closes https://github.com/vercel/next.js/pull/39146 - PR abandoned. ## Details I was having the same issue at work, as a workaround, we've changed the `largePageDataBytes` setting as advised but we'd like to keep the warning ideally. It's something we need to address, but just don't want to spam our log aggregators while the large data issue isn't resolved. I believe I've more or less copied what was in the original PR, some small differences: * I use `Set` instead of `Map`, please let me know if there is an advantage to using Map! * Just to keep code a bit tidier (subjective) put an early return instead of nesting all the code in an if. * Added a test to verify only one log appears even when the page is accessed twice [as requested here](https://github.com/vercel/next.js/pull/39146#pullrequestreview-1064486985).
This commit is contained in:
parent
d9776ccc17
commit
adefdd2aaa
3 changed files with 76 additions and 0 deletions
|
@ -41,6 +41,9 @@ type HeadHTMLProps = React.DetailedHTMLProps<
|
||||||
|
|
||||||
type HeadProps = OriginProps & HeadHTMLProps
|
type HeadProps = OriginProps & HeadHTMLProps
|
||||||
|
|
||||||
|
/** Set of pages that have triggered a large data warning on production mode. */
|
||||||
|
const largePageDataWarnings = new Set<string>()
|
||||||
|
|
||||||
function getDocumentFiles(
|
function getDocumentFiles(
|
||||||
buildManifest: BuildManifest,
|
buildManifest: BuildManifest,
|
||||||
pathname: string,
|
pathname: string,
|
||||||
|
@ -998,6 +1001,11 @@ export class NextScript extends React.Component<OriginProps> {
|
||||||
const { __NEXT_DATA__, largePageDataBytes } = context
|
const { __NEXT_DATA__, largePageDataBytes } = context
|
||||||
try {
|
try {
|
||||||
const data = JSON.stringify(__NEXT_DATA__)
|
const data = JSON.stringify(__NEXT_DATA__)
|
||||||
|
|
||||||
|
if (largePageDataWarnings.has(__NEXT_DATA__.page)) {
|
||||||
|
return htmlEscapeJsonString(data)
|
||||||
|
}
|
||||||
|
|
||||||
const bytes =
|
const bytes =
|
||||||
process.env.NEXT_RUNTIME === 'edge'
|
process.env.NEXT_RUNTIME === 'edge'
|
||||||
? new TextEncoder().encode(data).buffer.byteLength
|
? new TextEncoder().encode(data).buffer.byteLength
|
||||||
|
@ -1005,6 +1013,10 @@ export class NextScript extends React.Component<OriginProps> {
|
||||||
const prettyBytes = require('../lib/pretty-bytes').default
|
const prettyBytes = require('../lib/pretty-bytes').default
|
||||||
|
|
||||||
if (largePageDataBytes && bytes > largePageDataBytes) {
|
if (largePageDataBytes && bytes > largePageDataBytes) {
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
largePageDataWarnings.add(__NEXT_DATA__.page)
|
||||||
|
}
|
||||||
|
|
||||||
console.warn(
|
console.warn(
|
||||||
`Warning: data for page "${__NEXT_DATA__.page}"${
|
`Warning: data for page "${__NEXT_DATA__.page}"${
|
||||||
__NEXT_DATA__.page === context.dangerousAsPath
|
__NEXT_DATA__.page === context.dangerousAsPath
|
||||||
|
|
|
@ -967,6 +967,39 @@ describe('Prerender', () => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if ((global as any).isNextDev) {
|
||||||
|
it('should show warning every time page with large amount of page data is returned', async () => {
|
||||||
|
await renderViaHTTP(next.url, '/large-page-data-ssr')
|
||||||
|
await check(
|
||||||
|
() => next.cliOutput,
|
||||||
|
/Warning: data for page "\/large-page-data-ssr" is 256 kB which exceeds the threshold of 128 kB, this amount of data can reduce performance/
|
||||||
|
)
|
||||||
|
|
||||||
|
const outputIndex = next.cliOutput.length
|
||||||
|
await renderViaHTTP(next.url, '/large-page-data-ssr')
|
||||||
|
await check(
|
||||||
|
() => next.cliOutput.slice(outputIndex),
|
||||||
|
/Warning: data for page "\/large-page-data-ssr" is 256 kB which exceeds the threshold of 128 kB, this amount of data can reduce performance/
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((global as any).isNextStart) {
|
||||||
|
it('should only show warning once per page when large amount of page data is returned', async () => {
|
||||||
|
await renderViaHTTP(next.url, '/large-page-data-ssr')
|
||||||
|
await check(
|
||||||
|
() => next.cliOutput,
|
||||||
|
/Warning: data for page "\/large-page-data-ssr" is 256 kB which exceeds the threshold of 128 kB, this amount of data can reduce performance/
|
||||||
|
)
|
||||||
|
|
||||||
|
const outputIndex = next.cliOutput.length
|
||||||
|
await renderViaHTTP(next.url, '/large-page-data-ssr')
|
||||||
|
expect(next.cliOutput.slice(outputIndex)).not.toInclude(
|
||||||
|
'Warning: data for page'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if ((global as any).isNextDev) {
|
if ((global as any).isNextDev) {
|
||||||
it('should not show warning from url prop being returned', async () => {
|
it('should not show warning from url prop being returned', async () => {
|
||||||
const urlPropPage = 'pages/url-prop.js'
|
const urlPropPage = 'pages/url-prop.js'
|
||||||
|
@ -1483,6 +1516,12 @@ describe('Prerender', () => {
|
||||||
)}\\/large-page-data.json$`,
|
)}\\/large-page-data.json$`,
|
||||||
page: '/large-page-data',
|
page: '/large-page-data',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
dataRouteRegex: `^\\/_next\\/data\\/${escapeRegex(
|
||||||
|
next.buildId
|
||||||
|
)}\\/large-page-data-ssr.json$`,
|
||||||
|
page: '/large-page-data-ssr',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
namedDataRouteRegex: `^/_next/data/${escapeRegex(
|
namedDataRouteRegex: `^/_next/data/${escapeRegex(
|
||||||
next.buildId
|
next.buildId
|
||||||
|
|
25
test/e2e/prerender/pages/large-page-data-ssr.js
Normal file
25
test/e2e/prerender/pages/large-page-data-ssr.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
export function getServerSideProps() {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
lotsOfData: new Array(256 * 1000).fill('a').join(''),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (props) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>lots of data returned</p>
|
||||||
|
<Link href="/" id="home">
|
||||||
|
to home
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/another" id="another">
|
||||||
|
to another
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in a new issue