Reputation: 19928
I've started implementing code splitting in an "universal" app (react-router, redux, webpack - largely based on https://github.com/erikras/react-redux-universal-hot-example).
On the (only) route where code splitting is implemented, I am getting the following React error message when doing a full browser refresh:
warning.js:44Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) <!-- react-empty: 1 -
(server) <div class="root" dat
If I disable code splitting, the error message goes away. I am guessing this is due to React doing a first render before the Javascript chunk was loaded by the Webpack loader and therefore, it generates markup that is different from the one generated on the server. Is that correct?
Upvotes: 3
Views: 1035
Reputation: 7063
Should I worry about the error message?
Yes, if React determines the mark-up differs it'll fail to re-use any of the existing mark-up and instead re-generate it from the client render resulting in more work for the browser.
Any way to figure out what React renders to at the exact time this message occurs?
You can compare the differences by diffing the generated source in dev tools and the html sent over the network.
Any fix to make the message go away? (other than to not use code splitting)
You could call match
as you've suggested in your answer or alternatively, if you happen not to be using React Router or your split points aren't setup via the router you could load all required chunks up front, e.g.
<!-- index.html -->
<script src="entry.js"></script>
<script src="chunk1.js"></script>
<script>
// NOTE: Instead of calling render immediately in `entry.js` you would need to define a function on the global to allow you to render the app after the second chunk has loaded.
window.App.render();
</script>
NOTE: This would only work when using
require.ensure
becauseSystem.import
/import
is always async which would mean the mark-up would still differ on the very first render.
Upvotes: 0
Reputation: 19928
The solution is to call react router's match
function before doing the first render.
See https://github.com/reactjs/react-router/issues/2036#issuecomment-225792937 and https://github.com/reactjs/react-router/blob/v2.4.1/docs/guides/ServerRendering.md#async-routes
Upvotes: 2