Integrate and serve React-Admin from existing Express application - reactjs

In my project I need an administrator application. I have stumbled upon the admin-react. It seems it does exactly what I need it to do. I have checked their tutorial. Made some drafts, and got it running (following tutorial).
However I have an Express application that has routes and API's already working, and also I have React application served by the Express one. I would like to serve the Admin-React instead, in other words remove the existing React application and start customizing the React-Admin one as a static resource. Simply, my existing Express application should serve the React-Admin and expose the existing API's to it.
Looking at the tutorials, I found no information how to do it. It had yarn start and it starts running on port 3000.
I am missing something here very basic it seems.
Is there an example of that setup?
This is my Express.js that already serves React application (not React Admin) from public folder.
'use strict';
/* jshint camelcase:false */
require('dotenv').config();
if (process.env.NODE_ENV === undefined) {
throw new Error('No environment variable was set. For development use [export NODE_ENV=dev].');
}
let express = require('express');
var favicon = require('serve-favicon');
let path = require('path');
let cookieParser = require('cookie-parser');
let bodyParser = require('body-parser');
let expressValidator = require('express-validator');
let configuration = require('./app/Configuration');
let app = configuration.getApp();
let config = configuration.getParameters();
let errorHandler = require('./src/Error/Handler');
let session = require('client-sessions');
app.use(require('./src/Twig/ExtendWithCustomFunctions').extend());
app.use(session({
cookieName: 'session',
secret: 'xxxxxxx',
duration: 12 * 60 * 60 * 1000,
activeDuration: 2 * 60 * 60 * 1000
}));
app.use(bodyParser.json());
app.use(errorHandler.bodyParser);
app.use(expressValidator());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(favicon(__dirname + '/public/favicon.ico'));
configuration.setErrorHandler(errorHandler);
configuration.initializeControllers(__dirname);
configuration.initializeErrorHandling();
module.exports = app;

The only way to serve a React Admin from an Express endpoint is to build it first.
If you followed the tutorial, you should have run a create-react-app application, so you can run the following command to bundle your app:
npm run build
# or
yarn build
Your bundle files will be available under the static folder.
Then, you can move these files to your express app, in a subfolder, where you'll be able to serve them with express.static.
More info about the create-react-app build & deployement: https://facebook.github.io/create-react-app/docs/deployment
There is even an example of how to serve the build: https://facebook.github.io/create-react-app/docs/deployment#other-solutions

Related

How to run cubeJS-Backend application using express

I am trying to run cubeJs-backend application using express. I have added code changes like below.
I have created cube.js file with the below code
const express = require('express');
const path = require('path');
const expressApp = express();
const options = {
basePath: 'cube'
}
require('dotenv').config();
const core = CubejsServerCore.create(options);
core.initApp(expressApp);
I have used .env file for the environment variables. When I run the application using node cube.js the application got started and also connecting to the data base. But, when I try to load in the browser using http://localhost:4000 it is not loading.
Here is my .env values:
CUBEJS_DB_HOST=localhost
CUBEJS_DB_PORT=5438
CUBEJS_DB_NAME=test
CUBEJS_DB_USER=postgres
CUBEJS_DB_PASS=test
CUBEJS_DEV_MODE=true
CUBEJS_DB_TYPE=postgres
CUBEJS_API_SECRET=b6e176d3942fd2811bacfd2b5e5dd00b47aae3f07d92000961f17c60f4d9a30eca5bfde0e1f2d460d9e358a0a6be7b3fa6812f245713915a1effea402a716c13
CUBEJS_EXTERNAL_DEFAULT=true
CUBEJS_SCHEDULED_REFRESH_DEFAULT=true
CUBEJS_WEB_SOCKETS=true
Embedding Cube.js within Express (any other framework / in application) is deprecated.
I suggest you run Cube.js with Docker, as it’s a better solution than embedding it into an Express app.
This link might be helpful as well: https://cube.dev/blog/cubejs-loves-docker

My MERN app is deployed on Namecheap / cPanel but it's not accessing Mongo Atlas DB

ISSUE
My app is hosted on Namecheap shared hosting, but it doesn't connect to my Mongo Atlas DB.
DETAILS
I'm very new to this, and have only deployed to Heroku. I tried to use them at first, but I couldn't figure out how to get the image file upload/retrieval working with S3.
So I'm trying Namecheap.
Anyways on the cPanel file directory, my app is in: /home/username/repositories/myapp
I also ran the npm run build command locally, and placed the contents of the newly-created /build/ directory inside cPanel's /home/username/public_html
I'm almost certain that it doesn't have to be done that way, but so far that's the only thing that gets my actual website to render on the browser.
I used cPanel's "Setup NodeJS App" menu to put my app up, and set the "Application Starter File" to server.js
My server.js file
const mongoose = require('mongoose');
const express = require('express');
const app = express();
const dotenv = require('dotenv');
const cors = require('cors');
const path = require('path');
// Activate dotenv for secure keys
dotenv.config();
// Middleware to recognize incoming Request Object as a JSON object
app.use(express.json());
// Local file storage
app.use('/uploads', express.static('uploads'));
// Bind Routes
const commissions = require('./routes/api/commissions');
const projects = require('./routes/api/projects');
const users = require('./routes/api/users');
// Use Routes
app.use(cors());
app.use('/commissions', commissions);
app.use('/projects', projects);
app.use('/users', users);
// Mongo connect
mongoose
.connect(process.env.URI || process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
})
.then(() => console.log("Connected to MongoDB"))
.catch(err => console.log(err));
// For Deployment
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client', 'build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'client', 'build', 'index.html'));
});
};
// Run server
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
I ran NPM install in cPanel (as well as a script in my package.json to run npm install on the client-side) hoping both of those would enable my app to work (like in development).
I also checked my Mongo Atlas IP Whitelist but it's already allowing for 0.0.0.0/0 (from my heroku deployment).
Also, the namecheap support staff opened Port 5000 for me, (I read in another forum that this was the solution for someone with a similar problem) but that did not work for me either.
Solved by:
Adding my Shared Hosting IP address (located in cPanel) to Mongo Atlas IP Whitelist
Contacting cPanel support and having them open the appropriate backend ports
Changing the NodeJS version of my app on cPanel's "Setup NodeJS App" menu
The biggest thing was the Node version. Node has many versions, but as of this post cPanel only has the following Node Version options:
12.19.1
11.15.0
10.22.0
9.11.2
8.17.0
6.17.1
My particular version is none of those, so I was informed to just select the highest version available. But that's what was breaking the connection to my Mongo Atlas DB.
I tested each of those options, and the one that worked was 8.17.0.

After deploying React/Express app to Heroku unable to start passport.js flow (page reloads instead) [duplicate]

I'm building a node + express server, with create-react-app to the frontend.
I used passportjs for auth routes handling, and all the stuff totally working on localhost ( backend on port 5000 and frontend on port 3000, with a proxy ).
When I deploy to Heroku, seems like the server can't recognize my auth routes and so heroku serve up static index.html.
If I test my APIs with Postman all seems to work ( I can see the html page for google oauth ), but with an anchor tag in my react app or manually writing the endpoint in the url, I can see only the same page reloading.
My server index.js:
const express = require('express')
const passport = require('passport')
const mongoose = require('mongoose')
const path = require('path')
// KEYS
const keys = require('./config/keys')
// MONGOOSE MODELS
require('./models/User')
mongoose.connect(keys.mongoURI)
// PASSPORT SETUP
require('./config/passport')
// CREATE THE SERVER
const app = express()
// EXTERNAL MIDDLEWARES
require('./middlewares/external')(app)
// ROUTE HANDLERS
require('./routes/authRoutes')(app)
// PRODUCTION SETUP
if (process.env.NODE_ENV === 'production') {
// express serve up production assets ( main.js, main.css )
app.use(express.static('client/build'))
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
})
}
// START THE SERVER
const PORT = process.env.PORT || 5000
app.listen(PORT)
Flow:
LOCALHOST:
react app starts -> I click 'Google Login' -> GET request to "/auth/google" -> google oauth flow -> redirect to "/" and my react app reappears, the user is logged in.
HEROKU:
react app on my-app.herokuapp.com/ -> click on "Google Login" -> the page reloads, nothing happens. the user is not logged in.
Please guys, help me.
Thanks
This is a result of the service worker being installed by default to make your app a Progressive Web App
To determine if this is an issue for you, test your heroku production mode app in incognito mode. The request for /auth/google should now reach the server and behave as it does in development.
Once you determine it is an issue, you can remove the
import registerServiceWorker from "./registerServiceWorker";
from your /client/src/index.js file.
You browser cache may already contain an installed service worker so you may have to
clear browser cache on a user browsers
uninstall the server worker programmatically
import { unregister } from './registerServiceWorker';
....
unregister();
I had the same issues with same symptoms exactly.
For me the cause was a typo in the keys: in server/config/prod.js I had a line reading cookieKey: process.env.COOKIE_KEY but in Heroku Config Variables that variable was named cookieKey. Renaming it to COOKIE_KEY inside Heroku solved the issue.
If you've followed the Stephen Grider tutorial one thing I'm wondering: Is your passport.js file in config or services? I see you've written in index.js: require('./config/passport')
whereas mine in index.js is require('./services/passport')
may not be your solution to the google oauth flow hanging in production but may help.

Express/React - stylesheets are 404 in Heroku production (but ok locally)

I'm running an Express/React app on Heroku, and the app seems to be unable to find some stylesheets that I'm pulling in from the /node_modules directory - however, the app runs fine locally... just flops in production.
In the Express index.js file, I'm calling for the stylesheets like so:
const express = require('express')
const path = require('path')
const app = express()
const renderReact = require('./renderReact.js');
app.use(express.static(path.join(__dirname, 'public')))
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css'))
app.use('/css', express.static(__dirname + '/node_modules/quill/dist'))
// THIS APP EMPLOYS SERVER-SIDE RENDERING - THIS IS BASICALLY THE GET REQUEST TO THE HOME ROUTE...
renderReact(app);
and when running this on my local machine, the Bootstrap and Quill stylesheets are served up perfectly - they can be found at http://localhost:3000/css/bootstrap.min.css etc. as expected.
However, once deployed to Heroku, no such luck - the two stylesheets return 404 errors. Why is it that this works in local development but fails in production? I'd appreciate any advice on how to resolve this issue - thanks!
(Note - this app does utilize Webpack and I'm aware of the style-loader... I'd kind of prefer to avoid using that if possible, but I'll do it if it's the only way...)

Configuring Yeoman for building non-root projects

I might be missing something obvious, but i really can't figure it out by going over the docs and issues on GitHub -
I'm developing an AngularJS project that will be deployed on a specific sub-directory on the server (i.e not the root).
I'm using Yeoman.io, and trying to configure it so the app is self-contained and doesn't rely on absolute paths like '/images' and so on.
Every attempt to mess around with the Grunt file or Compass config ends up with a broken build. Paths of images and sprites are wrong - sometimes it's a wrong directory and sometimes wrong filename (no revision prefixes).
Anyone had good experience with that?
So if I understand you correctly, you want to serve your angular project on a specific path on system.
In grunt.js, I've registered a server task which starts my (local) server:
grunt.registerTask('server', 'Start server', function() {
var done = this.async();
var app = require('./app.js');
var http = require('http');
// Start server
http.createServer(app).listen(app.get('port'), function () {
console.log("Express server listening on port " + app.get('port'));
}).on('close', done);
});
app.js contains the server config:
var express = require('express'),
path = require('path');
var app = module.exports = express();
// Configuration
app.configure(function () {
app.set('port', process.env.PORT || 4000);
app.use(express['static'](path.join(__dirname, 'dist')));
});
In my example I serve the project on directory dist, but this can be anything.

Resources