-
We recently upgraded our next.js stack from 9.1.4 to 9.2.2, and everything was looking great until we noticed a meaningful dip in our page speed score and our First Contentful Paint metric. Last September (represented by the yellow line) we enabled the According to #10143 (comment) it was after investigations and recommendation of the Chrome team, but I'd love to better understand what that investigation yielded and why Could we get the |
Beta Was this translation helpful? Give feedback.
Replies: 17 comments 8 replies
-
@Timer any updates on getting the deferScripts experiment back? People are also asking for it on the PR |
Beta Was this translation helpful? Give feedback.
-
Need the defer option for scripts. |
Beta Was this translation helpful? Give feedback.
-
@Timer any thoughts? |
Beta Was this translation helpful? Give feedback.
-
@jgubman Have you done any tests after PSI updated to lighthouse v6 and see if defer vs async has an effect on it? |
Beta Was this translation helpful? Give feedback.
-
We are seeing the same thing. We are currently pinned to 9.1.7 and see our scores drop dramatically when upgrading to 9.4.4. All metrics are about the same except for FCP which doubled as well. It went from 2.1s to 4.7s. I compared the generated source and the only difference is the number of JS files being referenced. Because version 9.2 changed the way chunks are generated, our page is now seeing an additional 19 JS files. Our next app has 11 different pages. If I delete all the pages except for the one I'm testing, Next generates much less JS files, and our scores are back to normal. I wonder if there's a way to customize how these chunks are generated. |
Beta Was this translation helpful? Give feedback.
-
Since we haven't heard back, we went ahead and extended
After replacing |
Beta Was this translation helpful? Give feedback.
-
@jgubman we're amidst data collection phase to move to defer scripts. I would be very interested to experiment with you app as well. |
Beta Was this translation helpful? Give feedback.
-
@prateekbh We've been collecting the timing data that drives these graphs for awhile. Unfortunately we haven't been keeping track of every metric on the lighthouse page, but we do have desktop and mobile metrics for speed score, FCP, TTI and FMP. A sample that also shows which URLs the timings are associated with is here: the 8/31 run was pretty much the default Next.js |
Beta Was this translation helpful? Give feedback.
-
Hi Prateek, we made the change, if you tag https://www.ign.com/articles/marvels-avengers-review-2?defaultNextScript=1 -- Mobile score 9, Desktop score 34 |
Beta Was this translation helpful? Give feedback.
-
This is weird, I am getting very similar results for both. Are those results consistent for you? |
Beta Was this translation helpful? Give feedback.
-
@jgubman, in your screenshots the only major difference is FCP which shouldn't be dependent on scripts anyway but only on TTFB. Doing a few runs on webpage test to see whats going on |
Beta Was this translation helpful? Give feedback.
-
The problem here is the coexistence of Using both at the same time is what is causing the problems in the FCP. So, we have two ways of address this problem:
This is my TypeScript code for each case: import { NextScript } from 'next/document'
import React from 'react'
type DocumentFiles = {
sharedFiles: readonly string[]
pageFiles: readonly string[]
allFiles: readonly string[]
}
function dedupe<T extends { file: string }>(bundles: T[]): T[] {
const files = new Set<string>()
const kept: T[] = []
for (const bundle of bundles) {
if (files.has(bundle.file)) {continue}
files.add(bundle.file)
kept.push(bundle)
}
return kept
}
export class DeferredNextScript extends NextScript {
getScripts(files: DocumentFiles) {
return super.getScripts(files).map((script: JSX.Element) => {
return React.cloneElement((script), {
// eslint-disable-next-line @typescript-eslint/tslint/config
key: script.props.src,
defer: true,
async: false,
})
})
}
getDynamicChunks(files: DocumentFiles) {
const {
dynamicImports,
assetPrefix,
devOnlyCacheBusterQueryString,
} = this.context
return dedupe(dynamicImports).map((bundle) => {
let modernProps = {}
if (process.env.__NEXT_MODERN_BUILD) {
modernProps = bundle.file.endsWith('.module.js')
? { type: 'module' }
: { noModule: true }
}
if (!bundle.file.endsWith('.js') || files.allFiles.includes(bundle.file))
{return null}
return (
<script
defer={true}
key={bundle.file}
src={`${assetPrefix}/_next/${encodeURI(
bundle.file
)}${devOnlyCacheBusterQueryString}`}
nonce={this.props.nonce}
crossOrigin={
this.props.crossOrigin || process.env.__NEXT_CROSS_ORIGIN
}
{...modernProps}
/>
)
})
}
} HeadWithoutPreload is easier, since is just override this two methods to return an empty array. import { Head } from 'next/document'
export class HeadWithoutPreload extends Head {
getPreloadDynamicChunks () {
return []
}
getPreloadMainLinks () {
return []
}
} |
Beta Was this translation helpful? Give feedback.
-
Google is rolling out the usage of the page experience signals in ranking in May 2021. Improving LCP will directly improve the site's ranking in Google Search. Deferring the load of these scripts seem to make obvious improvements in that metric, are there any updates around why was that option removed or whether there are any plans to add it again? |
Beta Was this translation helpful? Give feedback.
-
Has there been an update to this anywhere? |
Beta Was this translation helpful? Give feedback.
-
Is there any official way to enable defer option for next scripts? It improved our score as well and I wonder if those workarounds are fine long term. We would love to see official support for deferred scripts. |
Beta Was this translation helpful? Give feedback.
-
Since #26021 (June 11th) scripts are loaded with |
Beta Was this translation helpful? Give feedback.
-
Is there a way to make |
Beta Was this translation helpful? Give feedback.
Since #26021 (June 11th) scripts are loaded with
defer
as default again.