2

I am building a react app and I did code splitting on the client for the bundle. My app properly render on the server as I am using SSR, I have no code Splitting on the server but on the client I do. I am getting the following warning on client with hydrate.

Warning: Did not expect server HTML to contain a <div> in <div>.

I am using @loadable/component for code splitting on the client

I have my App.js file on the client side as:-

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

const AsyncHome = loadable(() =>
  import('./components/Home/Home')  
)
const AsyncPost = loadable(() =>
  import('./components/Post/Post')
)

function App(){
   return(
       <div>
         <Switch>
             <Route path="/" component={AsyncHome}/>
             <Route path="post" component={AsyncPost}/>
           </Switch>
       </div>
    )
}

I have my index.js file on the client as:

import React from 'react'
import { hydrate } from 'react-dom'
import { BrowserRouter} from 'react-router-dom'
import App from './App'

hydrate(
    <BrowserRouter><App/></BrowserRouter>,
    document.getElementById('app')
)

How to get fix that warning with using code-splitting only on the client. I have also tried React.lazy and React.Suspense but i am getting the same error.

user8989
  • 580
  • 2
  • 6
  • 21

1 Answers1

0

You would need to ensure container that you are trying to hydrate on client side i same as the one rendered on server side. Please have a look at the react documentation

Having said that, code splitting is done to achieve smaller JS bundles which means we plan well in advance how to we plan to split our code based on our use cases. We don't do that runtime on client side. Still, I might be missing something so it would help if you could share the reason for trying out to do so. On the server side though, you have the option to do it as follows:

const AsyncHome = loadable(() =>
  import(
    /* webpackChunkName: "home" */
    /* webpackPrefetch: true */
    './components/Home'
  ),
);
const AsyncPost = loadable(() =>
  import(
    /* webpackChunkName: "post" */
    /* webpackPrefetch: true */
    './components/Post'
  ),
);

Another better way to achieve the same thing is by using ChunkExtractor plugin from @loadable/server if you don't want to explicitly keep track of your code split chunks in the app Also, to avoid rendering on server side, you need to ensure component is initialized when mounted which would happen only on client side only

let HomeComponent = () => <div/>
let PostComponent = () => <div/>

function App(){
   useEffect(() => {
    HomeComponent = loadable(() =>
      import(
        /* webpackChunkName: "home" */
        /* webpackPrefetch: true */
        './components/Home'
      ),
    );
    PostComponent = loadable(() =>
      import(
        /* webpackChunkName: "post" */
        /* webpackPrefetch: true */
        './components/Post'
      ),
    );
  }, []);
}
Ravi Chaudhary
  • 660
  • 6
  • 22
  • but how to do code splitting only on client and not on server – user8989 Jul 19 '20 at 16:30
  • code splitting should not give you the above issue. also, why would you do that selectively on client but not on server. – Ravi Chaudhary Jul 19 '20 at 16:49
  • since webpack would be creating different bundle for these components(the ones you chose for code splitting), you would need to specify them as dependency scripts in html response based on path you would be serving – Ravi Chaudhary Jul 19 '20 at 18:22
  • i don't want the componenet to be loaded asynchronously on the server, but on the client when browser download the `bundle` file it is to big initially so i was wondering if there any way acheive splitting only on the client and not on the server. – user8989 Jul 20 '20 at 07:40
  • updated my answer to take care of client side requirement as well – Ravi Chaudhary Jul 20 '20 at 10:03