I have a react app that I was able to build into static files which I then added to my node js app. after installing dotenv and adding require('dotenv').config() to server.js in the node server application. The following piece of code I had in the react application does not seem to be working now although the static files are being rendered in the browser just fine.
let node_server_url;
//TODO
// set the NODE_ENV on the .env file.
// create the .env file on the root of the project and add a NODE_ENV on the file
// e.g NODE_ENV=development or NODE_ENV=production
let urlConfig = (process.env.NODE_ENV === "production") ? {
urlBackend: `https://mybluebookloanuat.bayportbotswana.com`,
} : {
// urlBackend: `http://10.16.32.22:5000`,
urlBackend: `http://localhost:5003`,
}
// eslint-disable-next-line
export default node_server_url = urlConfig.urlBackend;
server.js:
require('dotenv').config()
...
const app = express();
// for parsing request body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// cross origin access to allow backend to communicate with frontend
app.use(cors());
const db = require("./app/models/index");
// to drop existing database and resync the database
db.sequelize.sync({force: false})
require("./app/routes/loan_application.routes")(app);
app.use(express.static(path.resolve(__dirname, 'assets')))
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'assets', 'index.html'));
});
I want to be able to just set up in the .env file the address for development and for production in the node server app. Can someone help me?
Related
Background
I am migrating an Angular app in GKE cluster. The base docker image that I must use(company policy) does not have any options to install any new softwares like shell, Angular cli command ng etc. The base docker image has only Node installed.
There is a shared base url, let's say, www.my-company.com, that everyone has to use for app deployment with a path added after the base url like www.my-company.com/my-angular-app/ - all the other Angular apps must be differentiated using the path of the app.
What I did
Since I can't run ng serve command in the base image, I added Express dependency in the package.json in Angular application and created an express server to route the traffic to Angular app.
I was following this youtube video to configure the application - https://www.youtube.com/watch?v=sTbQphoYbK0&t=303s. The problem I am facing is to how I load the the static files in the application.
If I define absolute path inside sendFile method of server.js file, although the application is working, but in future, if I need to add any other files in the application, I have to create another route in server.js file.
I don't know how Express can search a file automatically from the static folder(and sub folders) and return only that file when needed. I defined a static folder too, but seems like it is not working.
Following is my server.js code
==============================
const express = require('express');
const http = require('http');
const path = require('path');
const port = 8080;
const contextPath = '/my-angular-app';
const router = express.Router();
const app = express();
app.use(contextPath, router);
app.listen(port, ()=> {
console.log("Listening on port: ", port);
});
app.use(express.static(__dirname + '/dist/testapp/'));
router.get('/', function(req, res) {
// to get index.html file
res.sendFile(path.resolve(__dirname + '/dist/testapp/index.html'));
});
router.get('/*', function(req, res) {
let path = __dirname +'/dist/testapp/' + req.path
console.log('full path: ', path);
// To return static files based on incoming request, I am facing problem here(I think)
res.sendFile(path);
});
==============================
I want Express will send any files based on file name in the request. It should also take care of nested directories in the /dist/testapp/ directory
/dist/testapp/ -> This is the directory where Angular generates code for my app after I execute ng build command
WEBAPP.get("/admin/script.js", (req, res) => {
console.log(req.path);
if (req.session.username !== "Admin") return res.render("error");
res.sendFile(__dirname + "/admin/admin.js")
});
WEBAPP.get("/admin", (req, res) => {
if (!req.session.loggedin) return res.render("error");
if (req.session.username !== "Admin") return res.render("error",);
res.render("admin", {
csrfToken: req.csrfToken(),
title: "ADMIN PORTAL",
username: req.session.username,
nav_avatar: GetImageURL(req.session.avatar, "small")
});
});
There's no need to publically share /admin/script.js in my case but if a user requests this URL say example.com/admin/script.js a check for username equaling "Admin" if all is okay we sendFile.
I would maybe assume that you're not properly targeting your static files. Perhaps console.log the target.
I am currently working on a nodejs project, and I have a simple question. I want to serve some libraries from my node_modules folder statically to the client (maybe stupid, but not relevant to the question), but I dont want to trash my main server JS file with all these statically served files like this:
const express = require('express');
const app = express();
// Imports here
app.use('/assets/lib/bootstrap', './node_modules/bootstrap/dist');
app.use('/assets/lib/axios', './node_modules/axios/dist');
app.use('/assets/lib/aos', './node_modules/aos/dist');
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
If I have 10+ imports, this would trash up my Server JS file, which I like to keep as clean as possible. I was wondering why this option wouldn't work:
./routes/route1.js :
const express = require('express');
const router = express.Router();
const path = require('path');
// Imports here
router.use('/bootstrap', path.resolve(__dirname, 'node_modules/aos/dist'));
router.use('/axios', path.resolve(__dirname, 'node_modules/aos/dist'));
router.use('/aos', path.resolve(__dirname, 'node_modules/aos/dist'));
// path to node_modules file is not the problem here
module.exports = router
And in my main Server JS file:
const express = require('express');
const app = express();
const route1 = require('./routes/route1');
// Imports here
app.use('/assets/lib', route1);
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
But this gives me an error. The file is not statically served to the client. Is this because an express Router can't serve static files? Maybe this is a rookie mistake, but any help is appreciated. The first code snippet does work, but I'm trying to keep my code organized.
Use the express.static middleware in your route1.js file instead of simply passing the folder path string to the route.
I'm deploying a project on my hosting, but I've some trouble with the 'entry point' of my app.
I've developed an application under react js (with webpack).
When I setup it, I don't know which file to make the 'Application startup file'?
For the moment, it's a simple 'server.js' that say hello and give me the current version of node.
When I'm on my project in local, I just launch npm start and it works.
Resolved by editing the 'server.js' file like this :
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
});
app.listen(9000);
I don't quite understand how to link my web application and server. Tried to use
res.sendFile(path.resolve('./public/index.html'));
But it doesn't connect components written in vue.js
In vue.config.js (make one in your client src folder if you haven't already), add the target directory for the build:
const path = require("path");
module.exports = {
outputDir: path.resolve(__dirname, "path/to/server/directory/public")
};
Now when you run npm run build the static files will be bundled there.
Then, all you need to do is point your server to that folder.
If you're using Node/Express as a backend:
// Handle production
if (process.env.NODE_ENV === 'production') {
// Static folder
app.use(express.static(__dirname + '/public/'));
}
Also, if your Vue app is an SPA, add this inside the if block, after app.use(express.static(__dirname + '/public/'));, to handle routing:
// Handle SPA
app.get(/.*/, (req, res) => res.sendFile(__dirname + '/public/index.html'));
I'm a beginner in Express. So I might've failed to frame the question properly. I have created a MEAN application wherein I've separated my frontend and backened. Frontend runs on port:4200 and server runs on port:3000. I wanted to run both frontend and backend on same port as part of deployment. I'm getting MIME type errors, someone told me that there is some problem with my server environment. Maybe I'm not sending headers properly. Here is my code:
I have mentioned tried solutions in the code itself as <----TRIED THIS
server.js
const express = require('express');
express.static.mime.define({'application/javascript': ['js']}); <----TRIED THIS
const bodyParser = require('body-parser');
const path = require('path');
// express.static.mime.define({'application/javascript': ['js']}); <----TRIED THIS
const api = require('./routes/api');
const PORT = 3000;
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/api', api);
app.get('/', function(req, res) {
// res.send('Hello from the server'); <----TRIED THIS
// res.writeHead(200, {'Content-Type': 'text/html'}); <----TRIED THIS
// res.set('Content-Type', 'text/plain'); <----TRIED THIS
// res.setHeader("Content-Type","application/json"); <----TRIED THIS
res.sendFile(path.join(__dirname, 'dist/application/index.html'));
})
app.listen(PORT, function() {
console.log('Server listening on PORT '+PORT);
});
api.js
For instance I'm showing you GET function only
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const db = <my db string>;
const jwt = require('jsonwebtoken');
mongoose.connect(
...
)
function verifyToken(req, res, next) {
...
}
router.get('/myarticles', (req, res) => {
var person="Tanzeel Mirza";
console.log('Get request for tanzeel articles');
Article.find({contributor: person}, (error, article) => {
if(error) {
console.log(error)
}
else {
if(!article) {
res.status(401).send('Invalid email')
}
else if(2>4) {
console.log("test passed");
}
else {
res.json(article);
}
}
})
})
module.exports = router;
But still I'm getting
Loading module from “http://localhost:3000/runtime-xxx.js” was blocked because of a disallowed MIME type (“text/html”).
Loading module from “http://localhost:3000/polyfills-xxx.js” was blocked because of a disallowed MIME type (“text/html”).
Loading module from “http://localhost:3000/main-xxx.js” was blocked because of a disallowed MIME type (“text/html”).
Please correct me.
PS: I asked separate questions for MIME error here. But no answers.
Since your assets are inside dist/application folder, Use app.use(express.static(path.join(__dirname, 'dist/application')));
To match all web app routes, Use app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'dist/application/index.html'));
}).
This a generic route and will be called into action only if express can't find any other routes and always serve index.html. For example any valid /api route will never reach this handler, as there a specific route that handles it.
Final code for server.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const api = require('./routes/api');
const PORT = 3000;
const app = express();
app.use(express.static(path.join(__dirname, 'dist/application')));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/api', api);
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'dist/application/index.html'));
})
app.listen(PORT, function() {
console.log('Server listening on PORT '+PORT);
});
A few points to not.
To serve static files, you need not set any headers manually. Express looks up the files in the folder (dist folder in your case) you set as static directory with the express.static middleware function. Express also sets the response headers based on the file extension.
So you don't need express.static.mime.define in your code anymore.
In your case you have defined app.use(express.static(path.join(__dirname, 'dist'))); which listens for static files at dist folder. In this app.use command, you haven't used a mount path which means that all the requests will go through the static middleware. If the middleware finds an asset with the same name, path and extension in dist folder it returns the file, else the request is passed to the other route handlers.
Also, If you are using static middleware, as long as there is an index.html in dist folder (immediate child of dist folder), your route handler for "/" will never get invoked as the response will be served by the middleware.
If you don't have an index html file in dist folder(immediate child of dist), but it's present somewhere in subfolders of dist, and still you need to access it using root path "/", only then you need a route handler for path "/" as below.
app.get("/", function(req, res) {
res.sendFile(path.join(__dirname, "dist/application/index.html"));
});
JS files referred using "./" in dist/application/index.html are referred relative to dist folder itself and NOT dist/application folder.
You can refer this REPL for updated code 👉.
https://repl.it/repls/SoreFearlessNagware
Try below urls
/api/myarticles - Rendered by "/api" route handler
/api/myarticles.js - Rendered by static asset middleware because the file exists in dist/api folder
/ - rendered using "/" route handler and res.sendFile because index.html doesn't exist in dist folder.
/test.js - Rendered using static middleware because file exists in dist folder
Additional links for reference.
https://expressjs.com/en/api.html#res.sendFile
https://expressjs.com/en/starter/static-files.html
1.Build your angular project, either inside or outside the server folder using ng build cmd.
2.To build your project inside server, change the dist-folder path in angular-cli.
3.To change path, either use cli cmd or edit the angular-cli.json file's "outDir": "./location/toYour/dist"
Or by using this cli cmd ng build --output-path=dist/example/
4.Then In your server root file include the static build/dist folder using express.
5.Like this app.use(express.static(path.join( 'your path to static folder')));
6.Now restart your server.