Best way to render dynamic sitemap - react - reactjs

I am a beginner in react and I have made a portfolio website using react frontend.
I wanted to add a dynamic sitemap to the application and almost tried every possible way given on youtube, stackoverflow and google. But, I couldn't do what I wanted like if I add a new portfolio, it will not be there in the sitemap.
Things I already tried:-
At first, I added a sitemap.xml file in the public folder with all static contents but there was the same problem, I had to build whole application everytime I add a portfolio and also I will have to manually change the sitemap.
I also tried react-snap and react-snap-sitemap together which mostly worked but then, for some pages, I don't know why but the css stopped working. Mostly it happened with the pages which I didn't want in the sitemap or I didn't want them to be crawled.
Then, I also tried a way where there was a sitemap-generator.js which we would have to run to create a sitemap.xml file in the build folder, but then, we would have to build it again and again, and a bigger issue was that it used babel scripts which was giving errors.
Then I finally found out react-dynamic-sitemap which works almost perfectly but the issue is that it is rendering the component Sitemap and not a file sitemap.xml.
So, the xml content is displayed as text.
I also found out ways to display it as xml content but I was unable to do so.
I assume that this sitemap could not be submitted to google and also, this is not working as purely dynamic.
Because, for the portfolio details pages, I have to pass slugs in the slugs parameter like this: [{id: "foo"}, {id: "bar"}]. I tried to bring these from the database but even if I use .then() and then load the Routes after the portfolios data is fetched from the server, it gives error as it has to be loaded in other Sitemap component till then.
Code for react-dynamic-sitemap:-
Sitemap.js
import React from "react";
import Routes from "./Routes";
import DynamicSitemap from "react-dynamic-sitemap";
export default function Sitemap(props) {
return (
<DynamicSitemap routes={Routes} prettify={true} {...props}/>
);
}
Routes.js
import React, { useContext, useEffect, useState } from 'react';
import { Route, Routes } from 'react-router-dom';
import { Portfolio } from './PortfolioComponent/Portfolio';
import { PortfolioDetail } from './PortfolioDetailComponent/PortfolioDetail';
import Sitemap from './Sitemap';
const MyRoutes = () => {
return (
<Routes>
...Other Static Routes...
<Route
path="/portfolio"
element={<Portfolio />}
sitemapIndex='true'
changefreq='weekly'
priority='1'
/>
<Route
path="/portfolio/:slug"
element={<PortfolioDetail />}
sitemapIndex='true'
changefreq='weekly'
priority='1'
slugs={[Objects of the slugs of different portfolios have to written staticly]}
/>
<Route path="/sitemap" element={<Sitemap />}></Route>
</Routes>
)
}
export default MyRoutes;
Can someone please answer these points, and end the issue for all React developers:-
What is the best way to generate sitemaps staticly in react, as many solutions say to use nextjs or to use online sitemaps generator
If no other way possible, how can we render react-dynamic-sitemap content as xml

If I'm not mistaken, you are using Create React App (CRA), right?
I have to be honest, CRA is easy to get started, but as you scale up and require more advanced features (e.g. image optimization, sitemap generation, SEO, etc), as you may have already noticed, you will start finding it problematic.
Since you want to have a sitemap, indicating your site is starting to grow into a decent size, instead of digging the rabbit hole, I would suggest you move to a more scalable framework, which Next.js is one of the most popular ones.
That being said, be warned that even Next.js doesn't have native support to sitemap. Most people just rely on next-sitemap, but it is proven to be a robust solution

Related

Including React Components (Using React.Lazy or Next.JS Dynamic Import) that are bundled separately

I am building a Next.JS site that includes a bunch of modules that act as "mini-wizard" like experiences that allow people to learn about various topics. These modules though aren't just text though and include a lot of functionality and some api calls to my backend. I would like to maintain these separately and have them sit in something like an S3 bucket and then have the main next.js site (Deployed through AWS Amplify currently, but might switch to Vercel) dynamically import them.
So I'm wondering if it is possible to dynamically import a js file from a S3 bucket that is separate from the bundled Next.JS application? I know that is super vague statement and also makes no sense when you think about it technically, but I want to implement something where I can push code updates to one of these modules without having to redeploy the entire site and also prevent the site from becoming massive as we have 100s or 1000s of these modules. I looked at some of the micro-frontends documentation and it doesn't quite seem to solve this problem since I would like to include these components and provide them data utilizing useContext so they can function and interact with data that lives inside the main site.
I haven't had much success so far in trying any approach, but this is somewhat the implementation would look like in code:
import dynamic from 'next/dynamic';
import { useContext, createContext, useState } from 'react';
const RemoteLearningModule = dynamic(() => import('https://s3_bucket_domain.com/modules/module_123.js'), {
loading: () => 'Loading...',
})
export default function ModuleDisplayer() {
const ModuleContext = createContext();
const [exampleData, setExampleData] = useState("test data");
return (
<div className="ModuleWrapper">
<ModuleContext.Provider value={exampleData}>
<RemoteLearningModule contextComponent={ModuleContext} />
</ModuleContext.Provider>
</div>
);
}
The line that doesn't work, and I have no solution for, is:
import('https://s3_bucket_domain.com/modules/module_123.js')
So this is kind of the exact spot where I am wondering if the idea of remote importing modules, like this, is even remotely possible. Thanks for any input you can add or any existing resources I may have not looked at!

React - Is it a best practice to use Loader in the main Routes for the API call

AIM: To fetch an api on the web application load on the project level. Because, the application in dependent on this api call. So, If there a place where I can call an api on project level. Please suggest that solution as well.
Sample code:
import "./styles.css";
import { Routes, Route } from "react-router-dom";
import { useEffect } from "react";
export default function App() {
useEffect(() => {
APICall();
},[])
if (isLoading) { // Getting the loader state from
//API call
return <Spinner />;
}
return <Routes>
<Route element={<HomePage />} path="/">
</Routes>;
}
Doubt:
Is this best practice to call an API on the mainroutes and make the spinner load till the API
is fetched or else will this cause any side effect. If possible please suggest an alternate solution for this issue.
There're many solutions. But mostly it depends on your project complexity. For really simple projects it's not ideal, but it's okay to make as you did. But I would highly recommend letting the fetch responsibility to your components that really need those data - so you should think about breaking your components
One feature that it's worthy to take a look at is "loader" function from react-router, which is a great feature that you could be using.
With this feature you ensure that you're providing the correct fetched data for each of your routes.
You could be using react-query library, because it's a better alternative for useEffect, on the performance level. With "react-query" you fetch data as soon as rendering starts so you don’t have to wait until react loads the entire component
For really complex projects with many API calls, you could use "redux-sagas"
Create a wrapper component that encapsulate this API call. For example, you have 2 types of pages in your application - protected and unprotected routes. You could create a component that receives another Component as prop and are called: ProtectedRoutes which returns 2 components conditionally - UnProtectedPage and Component.

Using React and a bundler to build drop-in script for multiple clients

Ok, so here's what I'd like to do, but I'm not sure how because I've only ever started create react app projects for single clients. But what if I had multiple clients? And what if instead of entire sites, it's just a drop in gallery that renders in the element of their choice?
-multiclientscript
-commoncomponents (react components)
-clientAlpha
-alpha.js (has logic, imports common components, renders components where client wants on their site)
-clientBeta
-beta.js (same as alpha.js, but might import different components, whatever)
Is it possible to set up a build with webpack or some other bundler to bundle all dependencies for each client into a single script file that the client can include on their page?
If so, can someone help me get pointed in the right direction, keeping in mind I've only done very vanilla CRA projects?
Thanks!
Unless you need Webpack-specific features, using Rollup might be better for this (and it's easier to configure).
But yes, it's certainly possible. Your bundle entrypoint would have e.g. (might require e.g. adding event listeners to work in all possible loading phases, but you get the gist)
import * as ReactDOM fom 'react-dom';
import Gallery from './my-components/Gallery';
Array.from(document.querySelectorAll(".my-gallery")).forEach(galleryEl => {
const id = galleryEl.dataset.galleryId;
ReactDOM.render(galleryEl, <Gallery id={id} />);
});
and the client's HTML would have
<div class="my-gallery" data-id="123" />
<script src="gallery-bundle.js"></script>
and it Should Just Work from there.
Of course you might want to consider the overhead of having to ship React and React DOM in your bundle – Preact might be an option...

Every react.js package works normally with next.js after the javascript enters the application?

I'm new to using Next.js to create websites with react.js. I am trying to put the module "react-insta-stories" (https://github.com/mohitk05/react-insta-stories). Only he accuses that the document is not defined. I know you've had similar questions here, but I wanted to ask you something different, more general ... Because there are several awesome modules that I wanted to use in this project and the next.js seems to make it difficult. Some modules just that only speak with the "browser" . The question is ... can I use any module even from react.js after javascript instantiates my application with no problems with next.js? And does anyone know how I could put this react-insta-stories in my project? Because I tried some solutions, but I think they are beyond my knowledge.
By default next.js performs server side rendering. The quick and dirty way of getting react components that require the document or window to work is to call them as a dynamic component in next.
If you can a better way that allows for server side rendering of your component is to run this code in a useEffect hook or similar, as this will be sent to the browser to run.
For example
import React, { useEffect, useRef } from 'react'
function ComponentWithEffect(): JSX.Element {
const divRef = useRef<HTMLDivElement>(null)
useEffect(() => {
divRef.current?.width = window.width
divRef.current?.height = window.height
}, [])
return(
<div ref={divRef}/>
)
}
But this is not always possible, because with external libraries you might not have access to the underlying methods. There are heaps of examples in the repo as well.

React App - Include /health - Health Endpoint for Load Balancer

I have a React Application and I wish to deploy this behind a load balancer, where the load balancer periodically pings the app to see whether it's healthy. My requirement is to provide a /health endpoint, that can be used for health checking.
What would be the ideal way to implement a health endpoint?
This is something that is required for anyone planning to deploy a React App in a auto-healing fashion
The main page of this App is /dashboard, which is a heavy page. Hence, it cannot be used as a health endpoint.
i.e: I have seen react apps which have /hello kind of endpoints which return a simple message like I am healthy.
I will be answering my own question. After some considerable amount of research and asking around from experienced React developers, the following is the used approach for Including a health endpoint in React Applications.
This requirement came up when containerising the React App to be used in a Kubernetes Environment.
Do NOT ever try to use an existing page as your health check endpoint. Because, your regular pages are heavy and healthcheck endpoints need to be simple.
Hence, create a new route with /health (or a preferable path) and return a simple HTML element. given below is a Simple Route component.
<Route path="/health">
<h3>Hey There!!! The App is Healthy</h3>
</Route>
This being used in a Routes.js file, is given below.
import React from 'react';
import { Switch, Redirect, Route } from 'react-router-dom';
const Routes = () => {
return (
<Switch>
{/* This endpoint will just return you to a dummy HTML with a simple heading tag */}
<Route path="/health">
<h3>Hey There!!! The App is Healthy</h3>
</Route>
{/* All other routes will be defined here */}
{/* Finally you will be redirected to a not found page */}
<Redirect to="/not-found" />
</Switch>
);
};
export default Routes;
The answer above will work but the health endpoint will contain all of the index.html content which is technically unnecessary for the health endpoint.
A much better approach is just adding a file called health in the public folder. Then, when /health is called, the service will return the content of the file, which is faster and much smaller.

Resources