So basically my issue is that I've mostly only made APIs using node/express/mongoose and have never served my react apps since someone else always did that for me in our Plesk (I think through Apache.)
Now that I'm finally doing some MERN stack stuff for a client on the side I was wondering what the 'correct' way of serving a React App that has already been built.
Express and React-Router clash. BY that I mean that if I have an 'About' page and I go to example.com/about how does express know that's a page on my single-page React app? There's only a index.html anything else dealing with routes on my page are handled by react-router.
But what if it is a file or a folder? So this has been my solution for being able to serve both the website's files and still being able to access the website's routes:
const apps = { //websites are put in this object and iterated through to make the code below less bloated.
example: {
folder: "example-website",
app: express(),
server: null,
port: 80,
protocol: "http",
cert: null,
subdomains: []
}
}
for(let website of Object.keys(apps)){ //Itterate through every website.
website = apps[website]; //Make the website key the website object instead.
const websitePath = path.join(__dirname+`/client/${website.folder}/build`); //Save path to website's build folder for ease of use.
fs.readdir(websitePath, (err, files) => { //itterate through all files in the build folder
if(err){ //log errors.
console.log(err)
} else { //continue if there wasn't an error.
const fileArray = files.filter(file => file !== 'index.html')//remove 'index.html' from the array.
website.app.use('/*', (req,res) =>{
let route = req.params["0"].substring(0, req.params["0"].indexOf('/')); //take the first part of the route.
if(fileArray.includes(route)){ //check if the first part of the route matches a file or folder.
res.sendFile(path.join(__dirname+`/client/${website.folder}/build/${req.params["0"]}`));
} else { //If the list of files doesn't include the route than the route is probably a route within the React App in React-Router
res.sendFile(path.join(__dirname+`/client/${website.folder}/build/index.html`));
}
});
//...more irrelevant code here.
}
})
}
I was wondering if this was the correct way to deal with the conflict between my single-page React app's use of react-router and the way Express handles routes.