I am trying to build a webapp using React, React Router and Webpack libraries, and taking advantage of server side rendering.
Now, I have a basic structure working - when I visit a URL, the page is rendered on the server, sent back to the client where React confirms that the output rendered on the client side matches with what's generated on the server and takes over from there.
My problem is when I try to open URLs which have to load components asynchronously.
When I visit a URL which has to load a dependency asynchronously, the server renders the output including all dependencies, but when it comes to the client, the markup which React renders does not include the asynchronously loaded components and therefore is different from server's and I get an error in the console which says
Warning: React attempted to reuse markup in a container but the checksum was invalid.
The way I see it the solution would be to either not render the asynchronously loaded components on server and lose out on the benefits of server side rendering or to somehow tell React to ignore the differences between the server and client, and not discard the server's markup, because I know that the component will eventually be loaded and markups will match.
Has anyone else come across this problem and knows what a good solution would be?
You need to also run match on the client side to load all the route components.
There's a fleshed out example available at https://github.com/rackt/example-react-router-server-rendering-lazy-routes.
Related
I am very used to the approach where SSR meant that the page got a full refresh and received a full HTML from the server, where it gets rendered with razor/pub/other depending on the backend stack. So every time the user would click on the navigation links, it would just send a request to the server and the whole page would refresh, receiving a new HTML. That is the traditional SSR which I understand.
With SPA however, we have for example react or angular, where we receive almost empty HTML on the beginning and then the JS so that the whole app gets initialized on the client side. We can then have some REST API to get json data and render views on the frontend (client side routing and rendering) without any page refresh. We don't even need any server really.
Now, what I have a problem understanding is how SSR (such as next.js) works with react.
From what I am reading, the first request returns full HTML+CSS (which helps with SEO etc - I get that), but what happens later? What happens after that first/initial request? Does the whole react app initialize in the browser and then it just behaves EXACTLY as if it was a normal SPA (meaning we have client side routing and rendering from now on, without any need to make requests to that server)? In other words, does next.js still make any server requests after the initial one, or does it act like a typical SPA with CRA from now on?
I spent lots of time reading but all the articles mainly focus on the initial request and SEO and time to first byte, paint etc. and I am simply trying to understand why its called SSR since it seems to work different than the traditional SSR which I described on the beginning.
does next.js still make any server requests after the initial one, or does it act like a typical SPA with CRA from now on?
You got it right. The first (initial) request is handled by the server and after that the frontend handles the routing (at least in the case of Next.js).
If you want to see an example OpenCollective is built with Next.js. Try playing around with it and see the Network tab in the DevTools.
I am simply trying to understand why its called SSR since it seems to work different than the traditional SSR which I described on the beginning.
It is called SSR because the app is effectively being rendered on the server. The fact that frontend routing takes over after the initial render doesn't remove the fact that the server did the work of rendering the app as oppose to the user machine.
That's Not all the things that happen with Next.js, In Next.js You can build something called Hybrid apps.
In traditional SSR, all of your client requests get handled by the server. Every request goes to the server and gets responses.
In classic CSR with something like React, as you said, all the things happens in the browser via the client-side javascript.
But, in Next.js you can define three different approaches (mainly two according to the docs) for pages to get delivered.
based on the app needs and requirements, you can serve a couple of pages in pure traditional SSR mode, a couple of them in classic CSR mode, and a couple of in SSR mode via dynamic data that get fetched and rendered into the pages on the fly.
these features bring lots of flexibility to design a web-app that behaves perfectly in every different scenario that is needed.
I'm working on a Next.js app that needs to fetch a config file from a remote server before initializing. I want to request the config file just once per call to the server before rendering the app server side. After that, I would like to be able to get the same config in the client without having to make a second request to the remote server from the browser.
I have tried to achieve this by using getInitialProps function either in _app or _document files and then use the React's Context API to make the configuration visible to every component but unless I'm wrong, this will run the code that requests the configuration both in server (on the first call from the browser) and client (on every page navigation).
I have also tried to create a server.js file, request the configuration from there and store in a variable within a ES6 module. However, I couldn't make this approach work because apparently the Next.js React app can't access the same modules than the server.js because they are actually two different apps. Again, I could be wrong.
Basically I would like to know if Next.js offers any kind of "bootstrapping place" where I can perform app initialization tasks that generate data that can be sent to the React app Next.js will initiate.
You are correct in that anything in getInitialProps in _app.js or _document.js will be run on every server request. Once you get your config, you can pass it down to the components in pages as props. From there, I think you have two choices:
Now that the app is bootstrapped, run the rest of the app as a SPA client-side. This would prevent any future SSR from happening. Obviously, you lose the benefits of SSR and the initial page load is likely longer, but then it would be snappy afterwards.
After getting the config in _app.js, send it as a cookie (assuming it's not too big to be a cookie?). On future requests to the server, the cookie will be sent automatically and you would check the cookie first - if it doesn't exist, get the config. If it does exist, skip that more expensive bootstrapping because the app is bootstrapped.
So I think it really depends on whether you want a single page application bootstrapped on the server but then entirely client side after that (option 1) or server side rendering per page while minimizing expensive bootstrapping (option 2).
Nothing prevents you from sending multiple cookies from the server if that makes sense for your app and bootstrapping. And remember not to make it a HTTP-Only cookie because you'll want to read that cookie client side - after all, that's what you're looking for - the client side configuration generated on the server.
Despite we ended up leaving Next.js for this and other reasons that made us decide Next.js was not the best option for our use case, we kind of mitigated this problem as follows while be sticked to it, I hope it makes sense to anyone. Also, by now maybe Next.js provides a better way to do this so I would read the Next.js docs before using my approach. Final note: I don't have access to the code anymore since I change to a different company so maybe there are some points that won't be 100% as we made it.
There is goes:
We created a module that was responsible to request the config file and keep the results in a variable. At the moment of importing this module, we ensure that the variable is not already present in window.__NEXT_DATA__. If it is, we recover it, if it's not, we request it to the remote server (this will be helpful in the clint side rendering).
We created a server.js file as described by Next.js docs. In this file we make the call to get the config file and store it in memory.
In the body of the function passed to createServer we add the config file into the req object to make it accesible to the app in the getInitialProps functions server side.
We made sure that the getInitialProps using the config file returns it, so that it will be passed to the components as props and also serialized by Next.js and made available to the client in the __NEXT_DATA__ global Javascript variable.
Given that the config ended up in the __NEXT_DATA__ variable in the server, using the trick described in the step 1 makes the app not request the config for a second time.
Would there be any mechanism (at least theortical) which would allow to control which scripts are provided to a client? I have splited code into dynamically loadable parts using import('dynamically_loadable_file') but whenever is it called on a client, the file is served. I'd like to perform some security check whether does a user have permission to load the file. I thought of middlewares but those are only for HTTP and executable scripts are served through WebSockets.
Also, if it would be possible I would like to control content of the provided scripts. E.g. I'd like to add or "hide" some functions or variables to the script based on a user loading them. I guess something like dynamic compilation using AST would be required, or maybe there is/would be available something else. I guess that's another level but if there would be some content available on such ideas I'd be thankful.
Maybe it is not possible with meteor at all, so if this is possible wherever in JavaScript (node.js) world, it'd help too.
Thanks for ideas and explanations.
Most client-side protection mechanism can be surrounded with enough knowledge and the right tools.
The most viable solution to your problem would be to use a server side rendering (ssr) library for your current front-end engine.
With ssr your would solve to
allow to control which scripts are provided to a client?
perform some security check whether does a user have permission to load the file
scripts are served through WebSockets
control content of the provided scripts
add or "hide" some functions or variables to the script based on a user loading them
Because all your templates are rendered on the server and only the resulting data is returned to the client.
Some ssr packages for Meteor:
Generic: https://docs.meteor.com/packages/server-render.html
React: https://www.chrisvisser.io/meteor/how-to-set-up-meteor-react-with-ssr (guide with link to a boilerplate repo)
Vue: https://github.com/meteor-vue/vue-meteor/tree/master/packages/vue-ssr
The native Meteor Way
Besides this I would like to emphasize, that you can achieve most data handling through Publications and Methods.
Showing / hiding HTML elements on the client does not add any security if your data and logic are not secured on the server.
If you only publish the right data to the right user (for example using alanning:roles) then it does not matter which scripts you load.
Same goes for Methods: If you are very strict in who (use again alanning:roles) can call a Method then it does not matter, if a user can disable the Router and see all of the "hidden" areas on the client because all invalid actions are rejected server-side.
I have a React/Redux/SSR app. Right now my app works as follows:
A user visits some url, browser sends request to Frontend server (Node.js)
Frontend server gets all necessary data for this url from Backend server (Ruby) and build html then responds to user's browser with filled window._PRELOADED_STATE_ with appropriated Redux store's state
User's browser renders received html and runs bundle.js script which is React app. It uses filled before window._PRELOADED_STATE_ to initialize app (at this time actions run again)
I want to prevent Redux actions performance on the first rendering on client because all is done on the server already.
What I have tried: on client after the first rendering I delete window._PRELOADED_STATE_ and run actions if window._PRELOADED_STATE_ exists only. But deleting of window._PRELOADED_STATE_ performs before app initialization so actions run anyway.
How can I get desired behaviour? Any ideas are appreciated.
Do you have the opportunity to use React in dev mode?
In dev mode React will complain if it's not able to match the SSR code with the front-end code. It looks to me that you can have a similar situation.
If that's not the case, which are the actions that run at the beginning?
I use Parse BaaS
I have a React based web app created by this generator (which uses the latest ES syntax and BabelJS)
I'm new to React, it took me a while to configure and get things working (on my machine and on my mind).
One of the greatest benefits of React is the semi-transparent server side rendering.
I wonder how (and if) I can check the user login status while rendering the page on the server side.
For now I'm not able to achieve it, and React is telling me that this is bad:
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