After 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.05 to 1 or more. I mean even without dynamically loading any component, things are worst otherwise.
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) })
...
Notes :
- According to PageSpeed and LightHouse, it's the whole HTML
<main>
section of the code (filled with components routed withReact Router
) that is shifted, as if the SSR page was fully rerendered dispite usinghydrate
. - The exact same code doesn't lead to layout shift without Loadable Components.