Understanding how ReactJS and NodeJS app can work - javascript

I'm trying to learn React JS, but I have difficulties understanding how it should work with NodeJS, let's say with Express.
So far I understand that ReactJS is "V" in "MVC"
This is easy, I can already write a code using create-react-app
This is how I understand that:
"natural" way of combining React and Express is to simply write frontend in React and api in Express (with Mongo for example).
This way we can simply make ajax calls from React to our /api and show data
there is also a possibility to use React to server side rendering, which requires little more configuration. This way we do not call /api from React, we just use React to write code which can be rendered by Express
My question is Am I thinking right ?
Not sure about all that...
Is Isomorphic JavaScript somehow related to #2 ?

You are mostly correct, but using server side rendering does not mean you do not also issue api requests ever. Server side rendering is a technique used to improve initial load time. Rather than pulling down your javascript bundle, which then makes some api calls to load a bunch of data it needs to render, you instead do that initial rendering and bootstrapping of the app on the server. The resulting html and initial state of the application are then returned to the client so the app can be shown immediately to the user. So when talking about server side rendering with react, it's really about the initial load.
After the initoal load, you still have a dynamic frontend applicatoon. You still end up making api requests as the user interacts woth the app. If I go to a different route in the app (assuming it's a single page app) which requires additional data, I'll still be issuing a GET request to load that data. If I click a button to update a resource, I'll still be issuing a PUT or PATCH request to do so.
So in terms of the question of how express and react fit together, express (or whatever backend language/framework you use) provides the api to interact with data in your data store. And react is allowing you to build views that consume those apis. Server side rendering is just an additional technique you can use, not a totally separate paradigm.

Related

Difference between Next 12 client-side routing and Next 13 server-centric routing

In the documentation for Next 13, it says like this:
Unlike the pages directory which uses client-side routing, the new router in the app directory uses server-centric routing to align with Server Components and data fetching on the server. With server-centric routing, the client does not have to download a route map and the same request for Server Components can be used to look up routes. This optimization is useful for all applications but has a larger impact on applications with many routes.
Although routing is server-centric, the router uses client-side navigation with the Link Component - resembling the behavior of a Single-Page Application.
Please can someone explain the difference between client-side and server-centric routing in a bit more detail? It seems to me that in both cases components are rendered on the server, the client gets HTML and gets hydrated with JS. I'm not sure what the difference is except how the data is fetched.
In server-rendered components, the entire component gets built on the server and then sent to the client. the server does not send any javascript bundle, any dependency, and client will not parse anything. server will complete and sent it to the browser and the browser will just display it to the user.
That is why when you decide which components should be server-side rendered or client-side rendered components, you need to look at the component to see if the component has some sort of user interactivity, for example, button click. if there is a clickable component, that component should be rendered by the browser because the browser has to know the logic of how to handle the click once the click event occurs. The server will send the client related js code.
Since your component is rendered on the server it will be easier to fetch the data from the database. Because your server will not send any heavy library to the client, (browser has to parse javascript, and parsing always take s time) this increases the performance and initial loads will be significantly faster.
In app directory you can still use client components with use client directive on top of the page, but overall goal should be using as small amount of client components. Our goal is to minimize user wait time.

Use NuxtJs on server-side to Hydrate a Cordova client

I'm trying to upgrade an old mobile application written in vanilla Javascript+React hosted on Cordova. This application leverages a simple api on the server-side:
when the app requires a page, sends a request to the server
the server elaborate the request, fetch the resources, and then reply with a complete HTML+JS. The Javascript is a ReactJs view compiled with Gulp/Browserify
the app takes the reply and stores it in a local Sqlite DB, then mount the received code and the view become reactive.
if the user requests a view but has no connectivity, the app search though the Sqlite db wether there is a cached view and uses it instead of requesting a fresh copy from the server.
When developing, the React JSX code is immediately compiled to a vanilla JS so, when in production, the api only needs to merge the vanilla JS with the HTML template. Plus, adding new features and fixing bugs is quite easy, because each user essentially download any updated view, each time he enters in it.
The problems with this approach are:
developing is painful because of the continuous compilation
a "base" part of the application resides on Cordova assets (basically the utilities to fetch from server, caching etc) and fixing this parts needs a new app release or ugly override patches
the caching feature often causes problems to the Sqlite database (which is used also for other stuff on the app); as a result, the DB sometimes corrupts and the user must clear the app data.
we would like to get rid of React
We already used NuxtJs for generating static sites, and it's great, but in this case I cannot leverage the SSG because the app should be almost completely served from the api, so we can keep the easy-feature-and-fix stuff.
I never used NustJs SSR and wonder if could be suitable for my use case, for example, could I spin up a NuxtJs instance on server-side which generates the html output and hydrate a barely empty Javascript client on Cordova? Is there a better way to accomplish this task? Should I use only Vue instead?
Thanks

Why is my client side code being compiled and ran on node backend?

I'm new to SSR so I'm not sure if this problem and my solution is standard practices but I can't imagine so.
My goal is to have a dynamic page that allows users to add/remove items on the page. I originally programmed this component with the intention of it only being a client side react project but now I want to put it on a server. Now when I'm translating my code to the new project I've run into a couple errors now that has to do with my backend running the code that is only supposed to be run on client side.
For instance I ran into this problem earlier React Redux bundle.js being thrown into request, and I was able to solve this issue with a Janky solution where I make sure that it's being passed client side code and stop the execution of its being passed from the backend. Now I've had to refactor my code to not use the fetch() function because it's not a function that the node backend recognizes and it's now complaining about my use of the document object because that's not a thing in node either.
I can keep on going importing new modules to fix the errors to keep my website from crashing but I feel like I'm on a small boat patching up new holes with duck tape waiting to find the next hole.
Here's an image of my config if that's necessary I also have additional images in my previous stack overflow question (link aobove)
For the bundle.js issue I am not sure to understand why it happens.
For the fetch issue, I think this is a common problem with SSR and if you implement it by yourself you need to handle conditions in different places of your app:
if(!!window) {
// do client-side stuff like accessing
// window.document
}
Basically the most common usage of SSR is to handle the first execution of you app on the server side. This include:
Route resolution
Fetching data (using nodejs http module)
Hydrating stores (if you use redux or other data library)
rendering UI
Once the execution is done, your server returns the bundled js app with hydrated store and UI and returns it to the client. Subsequent requests or route update will be executed on the client side, so you can directly use fetch or react-router
The pros of doing SSR are:
Great first contentful
Great for SEO
Client-side machine do less works
There is a lot of libraries that can help you with SSR as well as frameworks like nextjs, use-http

Next.js Architecture

I am looking for some Next.js Architecture advise please 🙏
I am in the middle of migrating a very large express NodeJS app which has a custom SSR setup over to a Next.js setup.
For the current NodeJS site I have:
A bunch of routes (which hook up controllers / apis, do fancy redirections etc)
Have a ton of middlewares
Ton of logic in a bunch of express controllers (these controllers do things like API calls, transforming data, validation and the SSR of some React components to form the application)
Most of the time the NodeJS server calls other Microservice APIs (on the same VPC) to fetch data within these controllers (eg: search api, auth api, location api etc - which are all seperate REST api servers) Note: when it fetches from these APIs its done so on an internal api address only
The React Website itself calls the same NodeJS server to fetch data via client side JS when there is a route change eg: The frontend URL would be: www.mywebsite.com.au
And any api call done from the frontend is done with route: www.mywebsite.com.au/api/*
Based on all the docs i have read so far, I figure the best setup is:
To keep my existing express setup for routes / middlewares (for which I have a ton of) this includes the /api/* ones
Migrate controller fetching logic to the publically accessible express apis /api/* (which I kind of already have but need to clean up)
For the existing express controller routes, route these to Next.js instead and use nextApp.render to specific next pages
Use getInitialProps in the Next.js pages to fetch data from those apis I mentioned in 2.
Also add the old prop transform logic that was in the express controllers to getInitialProps
This is so that the server and client share the same logic of whats in getInitialProps - and this will make the architecture clean and give me the ability to have smooth transition to use Link.
The thing im struggling with it is step 4.
It means now on SSR of a page request it needs to call out to the public api (www.mywebsite.com.au/api/*) on getInitialProps to fetch its data.
To me seems like a performance overhead to do this as it requires a network hop to public domain mywebsite.com.au to fetch data it could have got locally on that same request (by calling localhost:3000/api/* for instance)
Any advise on how to avoid the network hop outside for server render?
Can I detect if its a server render and then use an internal URL (eg: use localhost:3000/api/* on the request to the same web server) or is that not best practices when using Next.js?
The server needs to call out to itself to fetch its data, alot of the overhead involved with fetching data is around the delay (I.E Between the client and nearest datacenter) this will be less of a concern when its (datacenter -> datacenter).
If performance is still an issue, your next best bet will be to do SSR caching, of which there are many different methods alot you can find in a quick google search however it will depend on your hosting/setup.
I treat listing-page.jsx and handler for api/listing route to be the same. You may need to write 2 small functions to extract the parameters passed into the request and pass it down to your service module function like ListingService.getSingleListisng(id)

Converting React app to isomorphic app?

I've developed a web application using React and Redux and then packed it with Webpack, it's hosted using IIS and presumably just runs client-side and makes calls to a Web API (.net for reasons); also hosted on IIS.
How do I make the jump and make this application 'isomorphic' so that the React code runs both client and server side?
You'll need a few things:
1) some way to run node: Really the only things that happen server-side with React are a renderToString call to give you strinigfied HTML you can send to clients (it's just a static HTML rendering of your app w/ React), hydration (see more on that in a bit) to get data into your components, and route-matching.
2) a router (if you have routes): If your app uses multiple routes, you'll need to use React-router to tell node what component(s) should be rendered
3) a good reason to go universal: there are some relatively simple aspects to going universal and there are some relatively complicated ones. Matching the routes isn't all that hard, and it will essentially just be you telling your server what to send down. The harder, more complicated part of universal JS w/ React is fetching data to send down to clients on initial render. This usually involves some server-side data fetching, so you have to have a way to both get the data and pass it into your app to be rendered correctly. There are ways to do this, but it is certainly a significant step up in terms of overall complexity.
This is how I did it, w/o the need for any server-side data fetching: Server side rendering with react, react-router, and express
See also:
https://ifelse.io/2015/08/27/server-side-rendering-with-react-and-react-router/
http://jamesknelson.com/universal-react-youre-doing-it-wrong/
You need Node.js to make an isomorphic web app.
This is because an isomorphic application requires an appropriate server-side runtime to execute the React Javascript code on the server. I don't believe IIS has support for parsing Javascript exactly - only Node has this runtime.
If you aren't using Node, then you should introduce it at some stage in your application. You can use IIS as a reverse proxy: create a Node server for IIS to forward requests to, let Node render the React as static HTML using renderString, and then have Node respond to requests from IIS with the rendered HTML. IIS will act as middleman for all incoming requests and responses.
Reverse proxies add some minor latency to an application, but, as always, premature optimisation is the root of all evil.

Categories

Resources