I have been exploring react.js lately and using it in combination with middleman. I really like middleman because it serves up static assets that are easy and fast to host. It also allows you to just cache the entire page as well.
Now my ideal goal is to have the user come to my site, serve up the static assets and then have react populate the dynamic data. This seems great but then SEO becomes a problem. Fortunately react comes with server side rendering, but it's not entirely clear how it works in relation to page caching.
So from my current understanding when the server gets hit with react, it only creates a string of the html with the initialize data put into. Generally from examples the data populated is empty. It then gets recalled when the client hits and fills in the api based data and populates the html. Although I don't understand how this is SEO friendly, apparently it is.
Then I realized that I should be able to still cache the entire instance that react creates with the string, serve that up, and then react can still populate it while being seo friendly. Does this work like I want it to or where in the react lifecycle does this not work?
Yes, you can absolutely cache the generated markup string.
The only thing you need to be careful of is that the props you pass on the server should match the props you pass on the client exactly, so that the initial rendered markup matches, or else React is forced to throw away the server-rendered markup and start from scratch. (The development/uncompressed version of React will give you a warning if the markup doesn't match.)
Related
This is a simple question that almost certainly is answered in the NextJS documentation somewhere, but after looking (as well as googling for some writeup about it) I can't find it.
As I understand it, NextJS works thusly:
If you arrive at your app from an 'external' URL, that is, not through a Link, then the page is SSR'd, and NextJS sends a combo of HTML with JS (NextJS framework, React, etc) to the browser. This HTML is produced through React, on the server.
During the SSR getInitialPropsis called on the server and (I assume) passes initial data down to the SSR process through props
Then React lifecycle methods are called (componentDidMount /useEffect). The application still has access to initial data through props. As I understand it, these lifecycle methods are called on the client -- that's what my console.log tells me -- and thus you can be guaranteed access to things like localStorage.
But does this imply that is there a second render on the client side after the original SSR, that is, the original HTML delivered is replaced by the SPA?
Or does the original SSR content remain, but NextJS somehow calls the React lifecycle methods "directly"?
Part of the issue is that I have zero knowledge of how React works internally -- what relation painting the screen and lifecycle methods have with each other.
I'm trying to understand how NextJS works -- what exactly is the flow, and how NextJS' SSR and React work together, and what happens when and where.
Any help much appreciated!
But does this imply that is there a second render on the client-side after the original SSR, that is, the original HTML delivered is replaced by the SPA?
What you're describing is what's called the "rehydration" process. Next will return the server-side content and then rehydrate on the client-side through effects (e.g., useEffect) or data fetching client-side (e.g., SWR).
I would recommend watching this video for a more detailed explanation from Tim, the lead maintainer of Next.js.
I'm creating a single page web application that needs to be 100% restful (first time doing this). So, I'm having trouble to decide how I'm going to render the UI for multiple roles using react.
There's going to be a regular user and an admin, after the login/authentication, the server is going to redirect to the main application page, and there is going to be a menu. The thing is, the admin menu should have an extra option, so I'm thinking on should I handle this.
Should I have two different files for the redirect (user.html / admin.html)? The downside would be that I will probably have a bit of duplicated code, because one of the bundles will have everything the other one has, plus an extra component.
Or maybe a component that defaults to none and then if it's an admin it shows itself? The downside would be that if the user has some JS knowledge he could search the code and see what an admin could do (of course there would be authentication in the server to prevent anything from actually happening).
I was also thinking in getting the menu list through a json, and when I click the extra option, it gets the script with the components that should appear, and then I somehow do a ReactDOM.render with the result (don't even know if that's possible, maybe I'm overthinking). Also I've heard about a React-Router but didn't found enough information, maybe that's what I need?
Any ideas/examples on how this is properly done would be really helpful. Thanks in advance.
Definitely don't duplicate your code. First I'd ask, is there really a problem knowing what an admin is capable of? I wouldn't personally worry about that.
React Router would be used for client side routing, and you definitely want client side routing if you're going for a proper React app. You only use the server for initial App route, and then API calls, essentially.
It is certainly possible to pass back arguments to feed into the button component. Your props could contain a 'buttonList' property that has all the arguments necessary to render the button... But that's only really feasible obfuscation if that button's operation is simple, and that's as far as the admin functionality goes. Writing a generic component that takes in specifics by arguments, which can certainly be passed in from the server, is definitely the React way to do this.
What exactly you need to hide from users and how important that is determines if that will truly be enough, however.
I have just learned react recently and intend to use it for my next project. I have come across react server side rendering for a few times, but wonders why do we still need it in "modern age".
In this article, it argues that with server side rendering, user does not have to wait to load those js from CDN or somewhere to see the initial static page, and the page will resume functionality when js arrives.
But after building with webpack production configuration, and gzip, the whole bundle (with react, my code and a lot other stuff) only takes 40kb, and I have aws CDN for it. I don't quite see the reason to use server side rendering for my situation.
So the question is why people still use server side rendering if the resulting javascript bundle is so tiny after gzip?
Load Times
A rendered view of the application can be delivered in the response of the initial HTTP request. In a traditional single page web app, the first request would come back, the browser would parse the HTML, then make subsequent requests for the scripts — which would eventually render the page. Those requests will still happen, but they won't ever get in the way of the user seeing the initial data.
This doesn't make much difference on quick internet connections, but for users on mobiles in low network coverage areas, this initial rendering of data can make apps render 20-30 seconds faster.
Views with static data can also be cached at a network level, meaning that a rendered view of a React application can be served with very little computational overhead
SEO
When a search engine crawler arrives at a web page, the HTML is served and the static content is inspected and indexed. In a purely client side Javascript application, there is no static content. It is all created and injected dynamically once the appropriate scripts load and run.
Unlike React, most frameworks have no way of serialising their component graph to HTML and then reinflating it. They have to use a more convoluted approach, which often involves rendering their page in a headless browser at the server, then serving up that version whenever a crawler requests it.
React can just render the component tree to a HTML string from a server side JS environment such as Node.js, then serve that straight away. No need for headless browsers or extra complications.
Noscript
It also allows you to write applications which gracefully degrade and ultimately, can be used as thin clients. This means that the processing goes on at the server and the application can be used in a browser with Javascript disabled. Whether or not that's an important market to consider is a debate for another time.
All-or-none rendering
This is a UX concern, some designers decide they don't like incremental rendering. The designer wants the page to show up complete and perfect, without the loading spinner, insertion of fetched text here and there, and displacement of layout.
Scroll bar restoration is a difficult issue for client side rendering. See Keep scroll position when navigating back (When navigating forward and then back, the scroll position is lost). Server side rendering does not suffer from this issue.
I think if you're chasing SEO will better rendered on server.
so all contents will read by bot SEO.
In addition to SEO mentioned above, with SSR browser could present the page right away even before all Java Script files are loaded. I have a tutorial explaining this.
Some javascript frameworks like Dust.js claim that they ALSO support server-side rendering (in addition to client side rendering) as well. Can someone explain how does this work? My understanding is that the JS is always executed in the browser runtime.
JavaScript can be run on servers using systems like Node.js.
With regard to Dust.js, a templating engine, it can generate hypertext and HTML on the server and send that content directly to the client's browser. This is typically used to avoid a flash of temporarily empty templates, caused by the browser requiring a split second to populate a view's templates via a framework like Dust.js. The downside is that the page will take slightly longer to load because more work has to be done on the server before sending data to the client.
Check out this question for the pros and cons of server-side rending. One must choose between slow post-processing (requiring the user's browser to do the work) or slow pre-processing (making the server do the work before the user sees anything).
Server side rendering is converting JavaScript into static html and css.
Earlier JS tended to load last to optimise website performance.
But the problem was it affected SEO.
So server side rendering became the solution to resolve this issue.
The 3 main renders methods are:
Client Side Rendering (CSR)
Is the default rendering process of modern frontend frameworks like ReactJS, the server just returns an almost empty index.html file, and then the user browser using Javascript loads and builds everything.
Server Side Rendering (SSR):
Refers to the process of generating in the server, the HTML content, on-demand for each request.
Usually, you’ll accomplish this by setting up a server running something like Express or Next.js (which use NodeJS) that renders your React app with each request — just as with a more traditional PHP or Rails based website.
Static Site Generator (SSG):
Both Server Side Rendering and Static Site Generator involve generating HTML for each of your site’s URLs. The difference is that Static rendering happens once at build time, while server rendering happens on-demand, as the user requests each file.
With static rendering, you need to generate responses for every possible request ahead of time. But what if you’re building something where you can’t predict all possible requests, like a search page? Or what if you have a lot of user generated content, and the response changes on every request? In that case, you’ll need Server Side Rendering.
*** So which should you use? ***
It depends.
if SEO is irrelevant — e.g. an app that lives behind a login screen — then CSR is fine and you just need something like ReactJS
If you need a good SEO:
a) If you can predict the content (to generate it in build time) then you need SSG and should choose something like NextJS
b) If you can’t predict the content/possible request, the server will need to generate the pages on demand, so you need SSR and should choose something like NextJS.
Note: NextJS allows you to selectively mix in the same project the 3 main rendering forms. They are also other good solutions like Gatsby on the market.
Server-Side Rendering (SSR) is executing JavaScript [SPA application] on the server-side.
Opposite to Client-Side Rendering when JavaScript is executed on the client-side.
Server-Side Rendering is a relatively new technology/therm that allows SPA frameworks like React or Angular to become more SEO-friendly.
Technology is rather inefficient, because of additional work put on the server.
Instead, of creating SPA (single-page application) and then executing it on the server, someone should consider creating the multi-page application in the first place.
SSR term is somehow ambiguous and confusing as some people use it referring to traditional multi-page websites like those built on Wordpress, for example, or any PHP or Java backends where HTML pages are generated by the server, and some use it only for SPA rendered on the server.
The latter, IMHO, is "more correct" as it produces less confusion.
This is a design question. I find myself going back and forth between two UI design styles.
The UI on a prototype I developed recently relied heavily on loading the elements of the UI as partial views via AJAX. I did not like that approach because I had to do a lot of requests to the server while my page was loading. However, the plus of this design was that I could easily edit the partial view templates, so the code was easier to manage.
In the next iteration I decided to package all the information at once and then use JavaScript to generate partial views and plug this information into it (and only use Ajax when on-demand up-to-date information was actually needed). My page loads faster, but I find myself generating a lot of HTML snippets in JavaScript, which is getting harder to manage.
As I see it, using Ajax you get:
Easier to maintain (+)
Longer UI response times (-)
And with JavaScript only, you get
Faster UI response (+)
Easier to handle server-side errors (+)
Harder to maintain (-)
So, There are a few things on which I would like to hear your comments:
I do not like using Ajax unless I don't have a need for actual on-demand data. Am I wrong?
Are there frameworks/libraries that would make managing HTML-generating JavaScript code easier?
Are there any other pros/cons of the two approaches that I have missed?
Thanks,
There are templating libraries for JavaScript, if you want to get that involved. In general I would avoid manually sticking together HTML strings from JS unless there's a particular need to (eg in some cases for performance when dealing with very large tables).
HTML-hacking is difficult to read and prone to HTML-injection security holes when you don't get escaping right.
Start instead with the DOM methods, and use DOM-like content manipulation libraries to make it easier. For example, if using jQuery, do this:
$('<a>', {href: somelink, text: sometext})
and not this:
$(''+sometext+'') // insecure mess
There doesn't need to be a big difference between fetching data through XMLHttpRequest vs including it in the HTML document itself. You can direct a bunch of JSON data to the same function that will build page parts whether it was just fetched by XMLHttpRequest in an update operation, or included in function calls at document load time.
When including data in the page you will generally need to include a timestamp they were generated in any case, so that if the browser goes back to the page a while later without reloading it, the browser can detect that the information is now out-of-date, and cue up an XMLHttpRequest to update it.
The usual question when you're creating your page content from data with client-side JavaScript is, are you going to fill in the initial static HTML version from the server too? If so, you're going to be duplicating a lot of your content generation work in both client-side JS and the server-side language(*). If not, then you're making the content invisible to non-JS user agents which includes search engines. Whether or not that matters to you typically depends on what the app is doing (ie does it need to be searchable and accessible?)
(*: unless you can use server-side JavaScript from something like node.js and re-use your content generation code. This is still a somewhat rare approach.)
Why not look at integrating require.js into your workflow? I'm not entirely sure how it would work with templates, but included in their pipeline is the ability to package all required script files into a single .js to be served by a single server request/response.
I have no personal experience about it, but Closure looks promising. The thing about its templates being usable on both server and client side might be of interest to you. Here is what was said about using it in Google+:
The cool thing about Closure templates is they can be compiled into both Java and JavaScript. So we use Java server-side to turn the templates into HTML, but we can also do the same in JavaScript client-side for dynamic rendering. For instance, if you type in a profile page URL directly, we'll render it server-side, but if you go to the stream say and navigate to someone's profile page, we do it with AJAX and render it client-side using the same exact template.
When working with remote data after a page is loaded, for small datasets I prefer returning data only and adding to the UI with templates.
For large datasets, I recommend using your partial views to render the html on the server to reduce overhead in the client as #bobince mentioned.
For client-side state tracking, check out Knockout at http://www.knockoutjs.com. It uses an MVVM approach with data models bound to UI elements and makes it very simple to send the data back to the server via AJAX. It works with the jquery.tmpl template library out of the box or you can integrate another library of preference with a little more effort.
As far as managing templates, it's easy enough to store common templates in an object, either on the server to be retrieved with your remote data, or in a javascript object on the client.