React Routing vs Express Routing - node.js

Been watching alot of tutorials and i see that there is express routing as well as react routing.
Is the react routing for client and the node js routing for server (api?).
Wanting to know if someone could please clarify this as new to React, Node, Express.
Thanks

It is possible (and even recommended) to use both of them in combination.
TL;DR
react-router is used to navigate between multiples pages/views of your front-end app/website. Usually in a single page app (SPA), where pages/views are loaded dynamically.
express router is a way to return static content (index.html, image.png...) AND to handle API calls that are often related to database logic. Those routes are handled server-side.
Example
myapp.com/my-portfolio is a view and should be handled and rendered by react router
// this router render pages components dynamically based on the url
<Route path="/my-portfolio" component={Portfolio} />
<Route path="/page2" component={Page2} />
myapp.com/user/create or myapp.com/api/getMyJson is an api call that should be handled server-side by express router:
// app.js
// api call that return json data
// this is where I will usually return database content
app.get('/api/getMyJson', (req, res) => {
res.send('{"my_var":"value"}');
});
// api call that return the content of folder app/public where
// the index.html and static resources are usually exposed
app.use(express.static('app/public'))
Single page application workflow
The front-end (client browser) request the back-end (your server) for the application static content (myLogo.png, index.html...) usually served by express router
While the first page is loaded and the user begin to interact with the app, the front-end continues to load other pages in the background (lazy loading)
When the user navigate to another page (with react-router), the page is already loaded and the user is taken there without any further server call nor page reloading
On another hand, express router need to handle API calls like myapp.com/user/userId/get/notifications to get data that is not "static" like json data.

I'll try explain the difference through an example. Say we have a single page application built with react at www.example.com
React Routing
We hit www.example.com and the index.html is loaded from the server. Note that it has all of your react pages in your bundle.js file. You now click the about button on the navbar, this sends you to www.example.com/about. This call does not hit the server, it is handled by your react router.
Express
Much like above we hit www.example.com and get the index. This time when we hit /about we get information from the server
Take a look at this blog post:https://medium.com/airbnb-engineering/isomorphic-javascript-the-future-of-web-apps-10882b7a2ebc

Related

Conditionally use next.js app or create react app with the same website domain according to users login

I have a website which I've built with CRA, node.js and I want to use ISR for most of the pages.
The problem is that about 20% of the users are registered users, which get their own content, and different header, which means I can only use SSR, and not ISR.
My thought is to use something like:
In my node.js server I would check if the user is logged
If he is not logged, I would send a get request to the next.js server, get the static html file and serve it.
If the user is logged I would just send him my CRA app.
Another option that I thought about is to use a proxy server with filter on the request which check if the session ID or cookie ID is set
Is it possible? Which option is better?
Shall I be able to use CDN to serve those static files?
Is there any better idea to solve this problem?
Just keep everything in the Nextjs application.
If you need static generated pages use getStaticProps and getStaticPaths or nothing (to have the same result as a CRA app) in that page.
If you need some server related logic use getServerSideProps in that page.
UPDATE
After run next build
The page test is a simple component
const Test = () => <div>test</div>;
export default Test;
In the other pages (/gpp, /gpp/[id]) getServerSideProps is defined
.....
const GppPage: NextPage = () => (
<>
<Head>
<title>GPP</title>
</Head>
<Box>
....
</Box>
</>
);
export async function getServerSideProps(context) {
return {
props: {
session: "mysession"
}
};
}
export default GppPage;
In the image the Test page is clearly a static page (look at symbols)
If you define in _app.tsx some getInitialProps or getServerSideProps in that case you will inherit the SSR behaviour
Instead of using next.js I ended up creating my own ISR for my website. This way I could use SSR for registered users and ISR for unregistered users. While using SSR in CRA app is not recommended by the create react app team, I found out that it is pretty simple with the help of this article for SSR, this article for SSR with react router. I used react 18 and react router 5.
While this solution worked for me, it is not guaranteed that it will work later so I won't recommend it until the create react app team will recommend it.
The pros of the solution:
More freedom with the code. For example, I could serve different pages for mobile and desktop (and still serve static pages).
Reduced costs compared to next.js
The cons of the solution
Unstable because the create react team doesn't recommend it
Missing out of some of the next.js features like images optimization
The html pages are not served from CDN (I used EBS)

How does serving different pages in React works?

Let's say I have a react projects, and an Express server for serving my project, as follows(After building the project):
]
This way, only the index.html is served, isn't it? If the user routes to a different page, how is that page sent to him?
Routing in javascript is managed by using HTML5 push state. So every time you click a link and go to another route, the browser history and push state is being used. That's the basis for routing in almost of all the single page applications.
Until and unless you refresh the page, your request doesn't go to the server. Hence, index.html is served only once and after that the router (here the react-router) takes over and manages the routing in url using the history API of the browser.
Hope this helps !
That is done using react-router which manages the routing using the browser's History API.
This style of a website is called a single page application as opposed to a multi page application where the server sends different pages depending on the url you route to.
you can use react-router-dom like this
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/someurl" component={ComponentForSomeUrl}
</Switch>
and render it with BrowserRouter
but you can use something like history.push, in my opinion react-router-dom is really simple and better than react-router
you don't need to send html file to specific route, in case of react express is used for building API (in most cases)
In you React folder you want to do npm install --save react-router-dom.
So inside the React Router family of libraries, there is a couple of different dependencies you can possibly install.
Ensure you never install React Router by itself.
The react-router library as it is published on npm is the core library of everything inside the React Router general project.
So react-router has some core navigational logic inside of it. It decides how to work with React, how to change content out depending on different rules and some other low-level logic.
To gain some actual implementation as it works specifically in the browser, install react-router-dom.
So anytime you want to use React Router on a project to handle navigation, always install react-router-dom, not react-router.
There are other similarly named projects that you might think you need as well, react-router-native for use inside of React Native projects.
In web applications we make use of react-router-dom, we are not making native mobile apps.
React-router-native is for native mobile applications only.
For the browser you always want react-router-dom as opposed to react-router-native
So perhaps in your App.js component you want to set something up that looks like this:
import React from "react";
import { BrowserRouter, Route } from “react-router-dom”;
const App = () => {
return <div>App</div>;
};
export default App;
I also recommend if you are new to React Router to get familiar with it by setting up something temporary like so:
import React from "react";
import { BrowserRouter, Route } from “react-router-dom”;
const PageOne = () => {
return <div>PageOne</div>;
};
const PageTwo = () => {
return <div>PageTwo<button>Click Me</button></div>;
};
const App = () => {
return (
<div>
<BrowserRouter>
<div>
<Route path=“/” exact component={PageOne} />
<Route path=“/pagetwo” component={PageTwo} />
</div>
</BrowserRouter>
</div>
);
};
Visit your localhost:3000 and then your localhost:3000/pagetwo, check out how all that is working.
When we visit a page called localhost:3000 and we type that address into the url it loads up the application.
React Router itself does not care about that entire url, instead React Router only cares about all the characters that are listed after the domain name or port definition.
Localhost:3000 is interpreted as being localhost:3000/
If I go to localhost:3000/ it still loads up my application.
Now I have other examples here if I go to localhost:3000/pageone, React Router only cares about everything after the port and domain
Same thing if I went to airbnb.com/listings/spain react router would only consider /listings/spain when deciding what content to render to the screen.
Notice in the example above I created an instance of BrowserRouter, well BrowserRouter creates an object of its own known as the history object.
This history object is going to look at the URL inside the address bar and extract just that portion of the URL that react router cares about.
The history object is then going to communicate that path over to BrowserRouter who communicates that path to both Route components and those Route components decide whether to show themselves or hide themselves depending on the path that the user is visiting and the path property that it was passed when it was created.

How to use the same view in FrontEnd and express server-side rendering?

I have a partial view that is used on server-side rendering to build a HTML page and also in FrontEnd to make a partial update on the UI. BecauseI want to use the same partial view file on both server-side and FrontEnd, I was looking for the best approach to share this file between the two sides.
For now, TBMK I used the following approach:
Placed the partial view file in /public folder which is served by express static middleware.
The server application loads the partial view from the file system.
The FrontEnd loads the partial via an AJAX HTTP request.
Is there any better approach?
I've had a similar problem. My solution was to have a particular route (maybe even in a special controller, for separation of concerns sake) serving the ajax requests.
The controller is serving files from the views directory.
If you'd like to deliver e.g. a file from the app/viewsDir/partialsDir directory you'd use a URL like:
http://myhost.com/partials/my-partial
then controller the could respond like:
router.get('/partials/:partialName', function(req, res, next) {
res.sendfile(`viewsDir/partialsDir/${req.params.partialName}`,
{root: __dirname });
});
This way, you could even have the file preprocessed by handlebars or any other serverside templating engine.
I did it this way, because I didn't want to have any templates located in the public directory.

Express JS access remotely

I have an app set up using BackboneJS, NodeJS and ExpressJS. I have trouble accessing my routes from my application. But I can access my routes directly in my browser and see the output.
For example this works:
http://test.myserver.com:3000/employees/1
(where test.myserver.com is my server address accessible externally)
My express server declaration is as follows:
var express = require('express'),
employee = require('./routes/employees');
var app = express();
app.get('/employees/:id', employee.findById);
app.listen(3000);
My problem is that when I try to access the route through my application I get an access error.
http://test.myserver.com/pages/index.html#employees/1
GET http://localhost:3000/employees/1?callback=jQuery19107984810129273683_1457829695460&_=1457829695461 net::ERR_CONNECTION_REFUSED
How can I access my routes from within my application using Express?
I see an issue. You say you're loading a web page at:
http://test.myserver.com/pages/index.html#employees/1
But, the URL request is for:
http://localhost:3000/employees/1?callback=jQuery19107984810129273683_1457829695460&_=1457829695461
Those are different domains and different ports. It looks to me like jQuery sees that this is a cross origin request and is trying to turn it into a JSONP request, but your server is not support JSONP.
Likely what you need to do is to get the Javascript in your web page to be requesting the SAME origin (same domain, same port) that the web page is loaded from. Then, it will not be cross origin request and it should work (if nothing else is wrong).
Please show us the relevant Javascript in your web page that is making this request so we can advise more specifically on how to fix it.
Also, if you're expecting your node.js server to serve your web pages, you will need node.js code to do that (you don't show any of that code) since node.js does not serve any pages by default (unlike some other web servers).

Express.js or angular for handling routes in a MEAN application?

I am totally new to everything Nodejs/express/angular, and I just ran into a question that bothers me.
When you have a MEAN stack, it seems that routes can be handled by both Express.js and Angular.
Angular:
For instance, if I define a route in Angular, I can do it like this:
var app = angular.module("app", []).config(function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: '/templates/login.html',
controller: 'LoginController'
});
$routeProvider.when('/front', {
templateUrl: '/templates/front.html',
controller: 'FrontController'
});
$routeProvider.otherwise({redirectTo: '/front'})
});
But with express.js I do:
app.get('/',function(req,res){
res.sendfile('templates/angular.html');
});
So my question is:
When do you use angular routing, and when do you use express routing?
(I might miss something very obvious here, but I hope you can point it out)
Those two serve different purposes on a single page app.
The app would do all the CRUD (endpoints where you create/read/update/delete your stuff, for example: projects, users, bills, etc). Also it would do all the authentication stuff (like /login and /register).
All of that needs routes, because you would want something like /api/users to grab all your users. All those routes, AKA CRUD routes and authentication routes goes into express.js router. Why there? Because those are routes of the backend.
On the other hand, you have your angular application, which contains the visual part of your application and there you want some routes. You want / to point to your home, you would want /users to have a page where you list your users or even /users/add to have a page with a form to add new users.
You could see it this way:
Backend routes (express ones): Those are the routes that an end user won't have to know about or even use them (your angular app will use them to communicate with the backend to work with its data but an end user wouldn't put them directly on the browser)).
Frontend routes (angular ones): Are the routes that maps to different pages of your application and because of that, end users can use them to access some parts of your application directly.

Resources