Bundle React/Express App for production - reactjs

My app is built with "create-react-app" and also Express.js as back-end.
How should I set up for the app for production?
Here is my user.js file from Express:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.json(['Hello World'])
});
module.exports = router;
I have "Proxy" setup in the package.json file in the React folder.
"proxy": "http://localhost:3001"
"create-react-app" has the command for build:
npm run build
Is my app bundled for production if I just run "npm run build" in the react folder or I have to setup something in my Express files?

If Express acts as both your API and your application server, at a basic level you'd need to setup Express to load the index.html of the React application when no other API routes are caught. You would do this by using sendFile() along with Node's path, registering a "catch-all" route after all your other API endpoints, in the main file for your Express application.
app.use('/users', usersRouter);
app.use('*', function (request, response) {
response.sendFile(path.resolve(__dirname, 'index.html'));
});
The path within sendFile() needs to point to the location of the index.html of the React client/frontend applicaiton. Exactly what goes into sendFile() entirely depends on the structure of your project. If for exampple you have the React application in a folder called client which has a build folder generated by create-react-app npm run build, the sendFile() would look like:
app.use(express.static(path.join(__dirname, 'client', 'build')));
// API route
app.use('/users', usersRouter);
app.use('*', function (request, response) {
response.sendFile(path.join(__dirname, 'client', 'build', 'index.html'));
});
The * in app.use() such as app.use('*', function (request, response)); means effectively all HTTP verbs (GET, POST, PUT, etc). If you do NOT put this after your API routes/paths, it will prevent your React client application from making calls to the API as it will catch all requests, order is very important.
Then you simply build the React application then run the Express application.
Hopefully that helps!

Related

live reload when running express with CRA

I have my create react app setup similar to this setup. https://www.newline.co/fullstack-react/articles/using-create-react-app-with-a-server/
All is working great so far.
when I'm running on localhost:3000 i'm seeing hot reloading as CRA dev server is taking care of that for me.
Now when I run my app using my express server localhost:8081 i'm loading my html file and assets from CRA build folder which obviously means I'm only going to get the built files.
What i'd like to do is when running in port localhost:8081 I can get a reload of development changed files and not just the static build files.
The reason for this is let's say I'm using an authentication setup where I need to check if user is logged in before I allow the * route to proceed otherwise redirect to another route in express. I want to be able to check for this when working in development.
If I run the dev server localhost:3000 then I no longer get the route change loading my html files from express. Only the api call would work from express.
Here is my setup in express:
const express = require("express");
const path = require("path");
const PORT = process.env.PORT || "8081";
const app = express();
const indexPath = path.join(__dirname, "../build/index.html");
app.use(express.static(path.resolve(__dirname, "../build"), { index: false }));
app.get("/test", (req, res) => {
res.json({ message: "welcome to backend" });
});
app.get("*", (req, res) => {
console.log("sending index.html");
res.sendFile(indexPath);
});
app.listen(PORT, () => console.log(`listing on port ${PORT}`));
This express route will only work when using in localhost:8081 which is getting the build files.
app.get("*", (req, res) => {
console.log("sending index.html");
res.sendFile(indexPath);
});
But this never runs when working in dev server localhost:3000 so I can not do any authentication on this route when working in development mode. This would mean to test this I would have to keep rebuilding the build folder which is crazy.
I'm running my client in one terminal and my server in another. I also restarted both multiple times. The proxy as I said works in my package file for the /test route when called using fetch .
This a similar unanswered question I found:
create-react-app + nodejs (express) server

How to connect frontend to json data on heroku

I'm trying to deploy my first React app on Heroku. I used simple json files for the backend.
Locally, everything runs good: my server is on localhost:8080, and frontend axios calls gets data from it like so:
axios.get(localhost:8080/bench).then( (response) => {
// my logic here
})
My deployment flow is:
to run a npm build and put everything in the build folder into the server end's public folder. Here's the entry-point file:
const path = require("path");
const publicPath = path.join(__dirname, "public");
console.log(publicPath);
app.use(express.static(publicPath));
app.get("*", (req, res) => {
res.sendFile(path.join(publicPath, "index.html"));
});
push to build artifacts to Heroku
Doing so, everything from the frontend part runs good on Heroku.
My concern is that I can't figure out what axios calls I should use for the frontend to get the data from the server. Is there anything I am missing?
Localhost only works on your machine. In your frontend, you'll need to change the axios url to point to the URL of your deployed server like so:
axios.get(`${YOUR_HEROKU_URL}`/bench)

Can't understand client side routing

So I was looking into the p2p.chat.I modified it a bit to have a better room encoding technique and noise suppression based on RNN noise.
I ran the npm run bundle cmd to generate the production build and tried hosting using the express server. But I was not able to emulate the client-side routing as seen on the webpack dev output. It doesn't use react-router.
I have no idea how to host this web-app.
p2p.chat
okay got it fixed after replacing the contents of jam.js to this
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, '')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, '', 'index.html'));
});
app.listen(9000);
I removed the directory reference in it

Shopify App Proxy - How to include my asset files in the request response | React / JS / Heroku

I'm building a Shopify App with React & Express, deployed via Heroku, which I'm trying to embed into my storefront using an Application Proxy.
When I finally load the proxied URL on my store - I get a blank screen and a bunch of 404's in the console for my .css and .js chunk files. The request was sent, authenticated, and my API's response is (200) - it just won't render anything.
Finally, after much research, I realized that Shopify has changed the path to these CSS and JS files to be my-store.myshopify.com/hash.chunk.js etc. instead of the reference to my Heroku server.
It appears this problem has been encountered before in this thread: Shopify app - how to include assets using an app-proxy with ruby on rails However, I can't seem to find a node/react/heroku equivalent to the Ruby solution presented here.
Any guidance or help would be greatly appreciated!
I begin by serving my React App through express with:
app.use(express.static(path.join(__dirname, 'client/build')));
and then when my proxy URL is hit I send back the index file within the client/build folder:
router.get('/proxy', (req, res) => {
res.set('Content-Type', 'application/liquid').sendFile(path.join(__dirname, '../client/build/index.html'));
});
I've managed to find a working solution to my problem after much trial and error.
The homepage in package.json is important. I had it set to just my Heroku address when it should actually be set to herokuaddress.com/YOURPROXYROUTE (i.e. /app/my-app)
Some additional middleware is required as well - for those interested I have the following routes set up to field requests from Shopify's app proxy.
This is set up above any of my route imports in server.js:
app.use(express.static(path.join(__dirname, 'client/build')));
and these routes are imported below that from a /shopify-routes.js file:
router.get('/proxy', (req, res) => {
res.set('Content-Type', 'application/liquid').sendFile(path.join(__dirname, '../client/build/index.html'));
});
router.get('/proxy/static/css/:file', (req, res) => {
res.set('Content-Type', 'text/css').sendFile(path.join(__dirname, `../client/build/static/css/${req.params.file}`));
});
router.get('/proxy/static/js/:file', (req, res) => {
res.set('Content-Type', 'text/javascript').sendFile(path.join(__dirname, `../client/build/static/js/${req.params.file}`));
});
Though this may be a bit heavy-handed, it has solved the problem and the app is loading within the Shopify storefront now.

How to add React to Express.js

I have got the basic files of express with express generator.
Now I want to add react to my express folder and integrate react with express. How can I do?
In your express file, you would need to link your react folder as static assets.
const express = require('express')
const path = require('path')
const app = express()
app.use(express.static(path.join(__dirname, 'client/build'))); // this is where your built react js files are
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/build/index.html'));
}); // this makes sure that all paths access your react.js files
while in development, you can access your express app by adding a proxy option in your package.json
for example, when you start your express with
node index.js
It will be served at a localhost:3000 or something else when you specify another port like localhost:5000
In order to access the json or the data your express app is sending, you need to setup a proxy in your client's package.json. The proxy is used for data to be accessed, so before your client side connects to a localhost, it goes through that proxy to have access to data being sent
If for example, your express app is run at localhost:5000, add the following to your client sides package.json
"proxy": "http://localhost:5000"
so start your express app first then your react app, and you will have combined your react app with your express server.

Resources