4

I'm working in a project that uses:

  • react/react-dom@16.9.0
  • @loadable/component
  • styled-components
  • react-router-dom

The application renders both server side and client side.

I'm using @loadable/component to dynamically code split this way.

router.tsx

import * as React from 'react'
import loadable from '@loadable/component'
import { Route, Switch } from 'react-router-dom'

const NotFound = loadable(() =>
  import('../components/NotFound/NotFound' /* webpackChunkName: "notfound" */)
)

const routes = (
  <Switch>
    <Route component={NotFound} />
  </Switch>
)

export default routes

When loading the page, this error appear on the console and the page seems to flick for a second.

react-dom.development.js:546 Warning: Did not expect server HTML to contain a <div> in <main>.

When I check the output in both sides (server/client), they are identical.

When I remove @loadable/component like bellow, it works and the error is gone.

router-without-loadable.tsx

import * as React from 'react'
import { Route, Switch } from 'react-router-dom'
import NotFound from '../components/NotFound/NotFound'

const routes = (
  <Switch>
    <Route component={NotFound} />
  </Switch>
)

export default routes

Seems to be something to do with @loadable/component but I'm not 100% sure.

Alejandro Garcia Anglada
  • 2,373
  • 1
  • 25
  • 41

2 Answers2

5

Finally have an answer for this:

  1. For @loadable/component to work properly, you need to put the magic webpack comment (/* webpackChunkName: "notfound" */) before the path of the file this way.
const NotFound = loadable(() =>
  import(/* webpackChunkName: "notfound" */ '../components/NotFound/NotFound')
)

Reference:

https://github.com/smooth-code/loadable-components/issues/23

  1. And more important, in the server side, you need to wrap you app in a ChunkExtractorManager and pass the client extractor (I was passing the server extractor, it's not very clear in the docs).
const statsFile = path.resolve('./wwwroot/dist/loadable-stats.json')
const extractor = new ChunkExtractor({ 
  statsFile, 
  entrypoints: ['client'] // name of the proper webpack endpoint (default: main)
})

<ChunkExtractorManager extractor={extractor}>
  <App />
</ChunkExtractorManager>

Here is a proper clear example on how to implement it:

https://github.com/iamssen/seed

Update 24.09.2019

Added to the official docs

https://www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/#chunkextractor-entrypoints

Alejandro Garcia Anglada
  • 2,373
  • 1
  • 25
  • 41
1

I think the problem is your NotFound component is not loaded and thus Route dont know what to render which is causing the error.

You would need to modify something like below:

<Route path="/404/" exact component={props => <NotFound {...props} />} />
Rikin
  • 5,351
  • 2
  • 15
  • 22
  • The `NotFound` component is rendered perfectly in the server and in the client, as I said, the outputs are identical. That is why I'm wondering why when I add dynamic import doesn't work and when I remove them it does work. It's nothing to do with the router otherwise it wont work with or without dynamic imports, if it makes sense. – Alejandro Garcia Anglada Aug 30 '19 at 12:10