React Loadable Components increase Cumulative Layout Shift (CLS)
See original GitHub issueAfter migrating a server side rendering React application to Loadable Components for code splitting and lazy loading, the initial bundle size, thus its download time, reduced as expected. However after replacing the classical React rendering method by the Loadable Components one, with the rest of the application code unchanged, my Cumulative Layout Shift score in PageSpeed / LightHouse raised to the sky, from 0.01 to 0.6 or more. What I am doing wrong?
SSR code before Loadable Components (good CLS score) :
Server-side :
...
import React from 'react'
import { renderToString } from 'react-dom/server'
import { StaticRouter } from 'react-router-dom'
...
const ssrApp = renderToString(
<StaticRouter location={`/${this.requestedPage.uri}`} context={{}}>
<App />
</StaticRouter>
)
Client-side :
...
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import { hydrate } from 'react-dom'
...
hydrate(<BrowserRouter><App /></BrowserRouter>, appRoot)
...
SSR after Loadable Components (bad CLS score) :
Server-side :
...
import React from 'react'
import { renderToString } from 'react-dom/server'
import { StaticRouter } from 'react-router-dom'
import { ChunkExtractor } from '@loadable/server'
import path from 'path'
...
const statsFile = path.resolve(`${process.env.APP_ROOT}${path.sep}public${path.sep}js${path.sep}loadable-stats.json`)
const extractor = new ChunkExtractor({ statsFile, publicPath: '/js' })
const jsx = extractor.collectChunks(
<StaticRouter location={`/${this.requestedPage.uri}`} context={{}}>
<App user={currentUser} requestedPage={this.requestedPage} />
</StaticRouter>
)
const scriptTags = extractor.getScriptTags()
const ssrApp = renderToString(jsx)
...
Client-side :
...
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import { hydrate } from 'react-dom'
import { loadableReady } from '@loadable/component'
...
loadableReady(() => { hydrate(<BrowserRouter><App /></BrowserRouter>, appRoot) })
...
Highlights:
- Even with throttling to slow 3G, I don’t see any visible CLS with Loadable Components enabled.
- According to PageSpeed and LightHouse, it’s the whole
<main>
section that is shifted, like if the SSR page is fully rendered dispite usinghydrate
. - The exact same code doesn’t lead to layout shift without Loadable Components.
Config:
"dependencies": {
"@loadable/component": "^5.14.1",
"@loadable/server": "^5.14.2",
"bnc-libs": "^0.2.33",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"isomorphic-fetch": "^3.0.0",
"lazysizes": "^5.3.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"@babel/cli": "^7.13.10",
"@babel/core": "^7.13.13",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/preset-react": "^7.13.13",
"@babel/preset-typescript": "^7.13.0",
"@loadable/babel-plugin": "^5.13.2",
"@loadable/webpack-plugin": "^5.14.2",
"@types/express": "^4.17.11",
"@types/isomorphic-fetch": "0.0.35",
"@types/loadable__component": "^5.13.3",
"@types/loadable__server": "^5.12.3",
"@types/node": "^14.14.37",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"@types/react-router-dom": "^5.1.7",
"babel-loader": "^8.2.2",
"jshint": "^2.12.0",
"ts-node": "^9.1.1",
"ts-node-dev": "^1.1.6",
"typescript": "^4.2.3",
"webpack": "^5.28.0",
"webpack-cli": "^4.5.0",
"webpack-node-externals": "^2.5.2"
}
}
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:11
Top Results From Across the Web
Loadable Components increase Cumulative Layout Shift (CLS ...
I am seeing the issue with React.lazy() & CLS. Removing React.lazy() improves CLS, but penalises with higher FCP, Speed Index & LCP. Adding...
Read more >Optimize Cumulative Layout Shift - web.dev
Cumulative Layout Shift (CLS) is a metric that quantifies how often users experience sudden shifts in page content.
Read more >The Duality of CLS with Lazy Loading Components
But caution: The same web app can cause Cumulative Layout Shift (CLS) on slower connections but runs without CLS on faster connection.
Read more >How To Fix Cumulative Layout Shift (CLS) Issues
Cumulative Layout Shift (CLS) attempts to measure those jarring movements of the page as new content — be it images, advertisements, or ...
Read more >How To Fix Cumulative Layout Shift (Examples & Best Practices)
The Cumulative Layout Shift (CLS) metric measures how much unexpected layout shifts affect the user experience on a page.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
It takes 3 minutes to switch SSR from Loadable-components to a standard React.
I don’t have extra time even to go and merge a few awesome PRs here, so no, I have not. And you are the first one who reported the issue, so there is still a chance that it is somehow bound to your particular usecase.