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);
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.
total noob question but I cannot find any solutions to this sorry so last resort is to ask here.
I am trying to learn pug. Have created a boilerplate project and unable to render index page. Ive searched and read as much as I can but all I get is 'Error parsing body of the with expression' error. The index.js looks as simple as follows but stopping me in my tracks:
var express = require('express');
var router = express.Router();
// GET home page.
router.get('/', (req, res) => {
res.render('index', { title: 'Express' });
});
module.exports = router;
if anyone can provide a one liner to point me in the right direction to resolve this and keep rolling on my pug and nodejs journey I'd really appreciate it. Pug is appearing very difficult at this stage despite all the raving about it :/
I have checked one of my old projects. You can try something like this:
Install pug:
$ npm install pug --save
Then set up the app:
const express = require('express')
const app = express()
const port = 3000
// you don’t have to specify the engine or load the template engine module in your app;
// Express loads the module internally, as shown below (for the above example).
app.set('view engine', 'pug')
// views, the directory where the template files are located
// This defaults to the views directory in the application root directory.
app.set('views', './views')
app.get('/', (req, res) => {
res.render('index', { title: 'Hey', message: 'Hello there!' })
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
Example pug file:
html
head
title= title
body
h1= message
Using template engines
I am building a blog using Node js and Express and hosting it on firebase. When I serve the website locally everything works just fine and the html is served as expected. But, when I deploy the server the routes no longer work and the html files can't be found. I'm sure it has to do with how firebase deploy hold the html files.
I'm not really sure where to go from here. I can't really find great guidance on how to set up something like this on the firebase docs.
const functions = require("firebase-functions")
const cors = require("cors")
const express = require("express")
const path = require("path")
/* Express with CORS */
const app = express()
app.use(cors({ origin: true }))
app.get("/", (request, response) => {
response.send("Hello from Express on Firebase with CORS!")
})
//File path consts
const publicDir = "/Users/wilson/wildman-talks-fb/public";
const blogDir = "/Users/wilson/wildman-talks-fb/public/blogs";
app.get("/about/", (req, res) =>{
res.sendFile(path.join(publicDir, "/about.html"));
});
app.get("/contact/", (req, res) =>{
res.sendFile(path.join(publicDir, "/contact.html"));
});
app.get("/tools/", (req, res) =>{
res.sendFile(path.join(publicDir, "/tools.html"));
});
app.get("/five-steps-july-20/", (req, res) =>{
//res.send(path.join(publicDir, "/five-steps-july-20.html"));
res.sendFile(path.join(publicDir, "/five-steps-july-20.html"));
})
exports.app = functions.https.onRequest(app)
So what is happening is when I deploy the site locally all of the links in my webpage work to other html webpages for my site. When I deploy it on firebase I get 404 errors. I was able to use path.join(__dirname, "../public") and print out all of the files contained there. When i did that these were the files that were there on my local host: [".DS_Store","404.html","about.html","blogs","contact.html","css","five-steps-july-20.html","img","index.html","js","mail","tools.html","vendor"]. After deploying it just returns me a 500 error so I guess that won't help.
Your directories contain absolute paths to your filesystem. Try to use dynamic absolute paths.
Change the paths from
const publicDir = "/Users/wilson/wildman-talks-fb/public";
const blogDir = "/Users/wilson/wildman-talks-fb/public/blogs";
To
const path = require("path");
const publicDir = path.join(__dirname, "/public";)
const blogDir = path.join( __dirname, "/public/blogs");
I have a index.html and wanted to link it to a twitter.ejs page. I was unsuccessful and now I am wondering if I can just change the extension from ejs to html. I tried to do it, but it does not work. Does only Node.js/Express work with a .ejs file?
My code trying to redirect from index.html to twitter.ejs: http://jsfiddle.net/1moj4v07/4/
index.html
<li>Tweet!</li>
script.js
const express = require('express');
const bodyParser= require('body-parser')
const app = express();
const MongoClient = require('mongodb').MongoClient
var router = express.Router();
var db
MongoClient.connect('mongodb://name:password#cluster0-shard-00-00-fquoc.mongodb.net:27017,cluster0-shard-00-01-fquoc.mongodb.net:27017,cluster0-shard-00-02-fquoc.mongodb.net:27017/twitter?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin', (err, database) => {
if (err) return console.log(err)
db = database
app.listen(3000, () => {
console.log('listening on 3000')
})
})
app.use(bodyParser.urlencoded({extended: true}))
var path = require('path')
app.set('view engine', 'ejs')
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(path.join(__dirname, '/public')));
app.get('/', (req, res) => {
db.collection('tweets').find().toArray((err, result) => {
if (err) return console.log(err)
res.render('twitter.ejs', {tweets: result})
})
})
app.get('views/', (req, res) =>{
res.render(views,local)
})
app.get('/twitter',function(req,res){
res.render('twitter', {});
});
app.post('/tweets', (req, res) => {
db.collection('tweets').save(req.body, (err, result) => {
if (err) return console.log(err)
console.log('saved to database')
res.redirect('/')
})
})
Folder structure
twitter
├── views
| └── twitter.ejs
|
├── public
| └── styles.css
|
├── index.html
I have a index.html and wanted to link it to a twitter.ejs page. I was unsuccessful and now I am wondering if I can just change the extension from ejs to html. I tried to do it, but it does not work. Does only Node.js/Express work with a .ejs file?
Express does indeed support formats other than .ejs, such as .html like you've asked, you'll just need to setup a new View Engine to support this. However, it looks like you have a number of other issues related to the structure of your Node application and the way your routes are loading its views.
To get a .html file rendered via Express, you can use res.render() with HTML files by creating a new View Engine in Express and then using that. The only requirement is that ejs is installed via npm i --save ejs. We need the ejs package directly because you'll need the renderFile() function for our new html view engine. Once you make the below change you can use res.render() to render a .html file.
This approach will not break data injection using EJS since renderFile() is still being used. The whole point of this approach is to continue getting EJS functionality if needed but, it will also render standard HTML as well all with one View Engine.
You also have a number of things that don't make sense in the given code along with a bad structure of your views.
index.html isn't being served
twitter.ejs is returned at the root of the app
app.get('views/') uses a views variable that is never defined
I've given a new Express Server setup and Project Directory Structure
Folder Structure for App
/public
/styles
styles.css
/views
index.html
twitter.html
server.js
package.json
Updated Express Server
const express = require('express')
const bodyParser = require('body-parser')
const MongoClient = require('monogdb').MongoClient
const path = require('path')
const app = express()
let db
MongoClient.connect('<connectionString>', (err, database) => {
if (err) {
return console.log(err)
}
db = database
app.listen(3000, () => console.log('listening on 3000'))
})
app.engine('html', require('ejs').renderFile)
app.set('view engine', 'html')
app.set('views', path.join(__dirname, 'views'))
app.use(bodyParser.urlencoded({extended: true})
app.use(express.static(path.join(__dirname, 'public')))
// When at the base of the application, return /views/index.html
app.get('/', (req, res) => {
return res.render('index')
})
// When GET /twitter is requested, get tweets from DB
// and render /views/twitter.html
app.get('/twitter', (req, res) => {
db.collection('tweets').find().toArray((err, tweets) => {
if (err) {
console.log(err)
return res.sendStatus(500)
}
return res.render('twitter', {tweets})
})
})
Problem - I am not able to get any response from postman when hitting localhost:9000. It should give me a user json back which is in my routes file only for time being. Instead it spits out the following.
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript" src="/static/js/main.ce2f0561.js"></script>
</body>
Setup
Using create-react-app with express to connect.
My folder structure is
--src React app lives in this
--server
-- index.js
-- express.js
-- controllers
-- routes
-- rs_notes.js
rs_routes.js
'use strict';
module.exports = function(router){
const notesController = require('../controllers/cs_notes');
router.route('/', function(req, res, next) {
// Comment out this line:
//res.send('respond with a resource');
// And insert something like this instead:
res.json([{
id: 1,
username: "samsepi0l"
}, {
id: 2,
username: "D0loresH4ze"
}]);
});
};
express.js
const express = require('express');
const morgan = require('morgan');
const path = require('path');
const app = express();
const router = express.Router();
// Setup logger
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] :response-time ms'));
// Serve static assets
app.use(express.static(path.resolve(__dirname, '..', 'build')));
require('./routes/rs_notes')(router);
// Always return the main index.html, so react-router render the route in the client
router.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'build', 'index.html'));
});
module.exports = app;
index.js
'use strict';
const app = require('./express');
const PORT = process.env.PORT || 9000;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}!`);
});
Full project link - https://drive.google.com/file/d/0B35OQMkRo3KcSHlkeXdWVjVjc0U/view?usp=sharing
My questions or doubts are
Am I passing the router in a right way. We used to pass app in this
way prior to express 4 ? So not sure if same structure works here.
I am able to load it in browser by hitting localhost:9000 (server is run by node server command as configured) but not in postman.
I was able to fix up this stack by learning the use of Router appropriately and moving some code here and there. But it was still not working for base route i.e when I simply do router.get('/', ...). Gives the same error message. So I rather reversed the approach of connecting node and react. I published my efforts on medium for the same reason as two separate posts.
https://medium.com/#kushalvmahajan/i-am-about-to-tell-you-a-story-on-how-to-a-node-express-app-connected-to-react-c2fb973accf2