Rendering noscript version serverside without reuse markup warnings in React - reactjs

In my JS component I currently render the non-js version of the markup for compatibility with old browsers. Then Client-side this is re-rendered to the js-on markup.
This causes the error below where you can see the noscript version triggers this error.
Warning: 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) <div class="shortlist ...
(server) <noscript data-reacti ...
Is there a way to resolve this issue where the client gets the fastest experience while maintaining support for noscript browsers?

My solution was to replace <noscript> with <div id="noscript" ref="noscript"> and in componentDidMount call this.refs.noscript.style.display = 'none';.
To hide the noscript div ASAP I've also added <script>try{document.getElementById('noscript').style.display='none'}catch(e){}</script> to the index.html just immediately after placeholder for serverside rendered markup.

Related

Is SSR enabled while using Client-Components in Next.JS?

I was trying out the new features from Next.js 13 and I can't explain to myself, why Client Components still use SSR. I thought that using Client Components would result in Components that are only rendered on the client.
Can anyone explain, how that exactly works?
Thanks
Server-side rendering basically means fetching the data on the server. So when the server sends the html to the browser, it already populates the HTML, so the search crawler will see HTML with populated data so your page will be indexed higher. Once the HTML is sent down to the browser, the browser will parse the HTML and your page will have javascript interactivity, onClick, mouseOver etc. All the client components in next.js uses ssr.
But the server component is a different concept. Entire HTML is rendered on the server so any dependency used on the server will stay on the server. So your browser will not have to parse HTML and go through all javascript. so client bundle size will decrease and your app performance will increase.

Angularjs route doesn't show html in view source, but react does

As I'm using angular route for my SPA, my view page source is empty (only ng-view exists). I see a website developed by react , has the similar functionality. But when I see the page source, content is there. (ex for angular, ex for react)
How is it possible in react ? And why not in angular? Any idea?
Edit: As crawlers like google, supports SPA crawling since a few years ago, Is it really necessary to use server side rendering?
Server side rendering might not be implemented in angular project which you are looking at, that's why you are not able to see the rendered html. React and angular2 has the feature of server side rendering, which means you can render html from your script on server and send that html to client.
You can see only in page sources ng-views because it doesn't execute JS what is needed to render another elements in your SPA. React can be rendered on server side and gives rendered HTML to your browser while Angular is rendered only in your browser

Universal React without Javascript

What are best practices for invoking different CSS when the client for my server-rendered universal React page has Javascript disabled?
I've tried including Modernizr with className="no-js" on the html tag but it wasn't edited.
I've managed to get something to work as shown below but there must be a better way.
<link rel="stylesheet" href="/public/css/script.css" />
<noscript>
<link rel="stylesheet" href="/public/css/noscript.css" />
</noscript>
I've looked for examples but haven't found anything relevant.
In a server rendered application, you can have one of many data sources:
query param
cookie
POST data
The only input for server side code is the request made when loading up a page in your app in your browser. You may choose to configure the server during its boot (such as when you are running in a development vs. production environment), but that configuration is static.
The request contains information about the URL requested, including any query parameters, which will be useful when using something like React Router. It can also contain headers with inputs like cookies or authorization, or POST body data.
In a script/noscript mapping, you can setup one of several defaults:
Render noscript as the default, then override it by injecting script specific CSS via the CSSOM
Serve a noscript specific route as the default, then jump to the script route based on a cookie
Create a form which posts scripting capabilities to the server, then use that as a jump page to avoid noscript/script in the markup
References
redux / Server Rendering: Processing Request Parameters
Rendering noscript version serverside without reuse markup warnings in React

"React attempted to reuse markup" error with webpack + code splitting

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?
Should I worry about the error message?
Any way to figure out what React renders to at the exact time this message occurs?
Any fix to make the message go away? (other than to not use code splitting)
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
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 because System.import / import is always async which would mean the mark-up would still differ on the very first render.

React server and client rendering

Using https://github.com/ayoubdev/reactjs-isomorphic-starterkit as a boiletplate.
I'm trying to figure out how to inject the client's bundle into the server rendering process.
As the webpack build for server and client is well separated, is there a simple trick to achieve this goal ?
Thanks
I'm not too sure about the specifics of this boilerplate repo. But I can try to explain the main idea, and you can dig deeper.
The basic idea is, use a bundler (in this case, webpack is used, gulp, grunt, whatever else is fine as long as you transpile) and build a bundle based on the entry point for your React components. Then link this bundle via script tag in some html file.
For the server side, you can use ReactDOMServer.renderToString. Import your component(s), pass them into ReactDOM.renderToString. Pass the HTML to some templater like ejs or use a raw HTML string and call React.render from the server.
Client side.
In your example, the entry point is here and hooked here. Notice the <div class= "app"> tag. This is tag we are referencing in our entry point. We also reference our bundled js from webpack via script tag, client.bundle.js.
Server side
In your example, the relevant code is here. Notice the renderComponent function. It builds a string based on the HTML of the component supplied from ReactDOMServer.renderToString, which is called on Line 39. It then sends all of that html back as a response in res.send
This blog article uses jade as an example, which you can use as an alternative if you find this boilerplate a bit much.

Resources