Is it possible to serve static content and views from the same directory?
I found a partial solution below:
//Enable Express static content serving:
app.use(express.static(__dirname + '/html')); //Static path is folder called html
//Also enable EJS template engine:
app.engine('.html', require('ejs').__express);
app.set('views', __dirname + '/html'); //Set views path to that same html folder
app.set('view engine', 'html'); //Instead of .ejs, look for .html extension
//Start server
app.listen(8000);
//Express routes:
app.get('/', function(req,res) {
res.render('index', { message: 'hello world'});
//this only serves static index.html :(
});
app.get('/home', function(req,res) {
res.render('index', { message: 'hello world'}); //<-- this serves EJS
//whoo-hoo! serves index.html with rendered EJS 'hello world' message
});
This is working perfectly, except for the first route '/' which does not render EJS. All other routes (/home, /about, etc) will conveniently serve the dynamic EJS along with static content. Is there anyway to trick that first '/' to work in the same way?
For Express 3.x try putting router before static:
app.use(app.router);
app.use(express.static(path.join(__dirname, 'html')));
For Express 4.x the router has been deprecated but the concept is the same as routes are like middleware so you should be able to call them before the static middleware.
Related
I have some plain HTML/CSS files in my frontend folder and the ejs files in the views folder and every other ejs file loads perfectly but the index.ejs file
I don't know what I am doing wrong here
This is my server.js: (this is a basic version of my server file)
const app = express();
app.set('views', __dirname + '/views');
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/frontend"));
app.get("/", (req, res) => {
res.render("index");
});
//The below file loads perfectly. (requireAuth is a authentication middleware)
app.get("/create", requireAuth, (req, res) => {
res.render("create");
});
Also both the files index.ejs and create.ejs are very similar
If anyone requires any extra details then they can comment down.
You've defined static middleware for / (root path) and the index page is also defined for root path, but because static middleware is defined early, express tries to find and return static file instead of rendering index page.
You have two variants here:
Define static middleware for some path different than root:
app.use("/public", express.static(__dirname + "/frontend"));
Don't use root path for index page: app.get("/index", (req, res)...
im trying to serve up static files using express and pug as the templating engine but somehow my assets are not being loaded
my files path :
+front
+views
+login
index.pug
+images
+js
+css
...
server.js
here is my server code :
app.use(express.static('front'));
app.set('views', './front/views')
app.set('view engine', 'pug')
router.get('/login', (req, res) => {
res.render('./Login_v1/login', { title: 'Login', message: 'Login'})
})
pug code :
link(rel='icon' type='image/png' href='/images/icons/favicon.ico')
step first add path to your static folder in app.js/server.js(your entry file of express)
app.use(express.static(__dirname + 'images/icons')); // path of your image folder
than you can access it by
href='localhost:serverPort/favicon.ico
I have a mean-stack application. By going to https://localhost:3000/#/home, it reads views/index.ejs. Here is the setting in app.js:
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.all('/*', function(req, res, next) {
res.sendFile('index.ejs', { root: __dirname });
});
Actually, I don't use the feature of ejs in index.ejs. So now I want to use just a index.html rather than index.ejs.
I put the content of index.ejs in public/htmls/index.html and views/index.html. And here is the current setting in app.js:
var app = express();
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.all('/*', function(req, res, next) {
res.sendFile('index.html', { root: __dirname });
// res.sendFile('index.html'); // does not work either
});
However, running https://localhost:3000/#/home returns
Error: No default engine was specified and no extension was provided.
Does anyone know how to fix it?
Edit 1: by following the answer of user818510, I tried res.sendFile('index.html', { root: path.join(__dirname, 'views') }); in app.js, it still can NOT find index.html.
Whereas, in routes/index.js, the following can find index.html, but it gives a warning express deprecated res.sendfile: Use res.sendFile instead routes/index.js:460:9.
var express = require('express');
var router = express.Router();
var path = require('path');
... ...
router.get('*', function(req, res) {
res.sendfile('./views/index.html'); // works, but a deprecation warning
// res.sendFile('index.html', { root: path.join(__dirname, 'views') }); does not work
});
It is really confusing...
If it's a single page mean application, then you only need to start express with static and put index.html in static/ dir :
Project layout
static/
index.html
server.js
server.js
'use strict';
var express = require('express');
var app = express();
app.use(express.static('public'));
var server = app.listen(8888, function () {
console.log("Server started. Listening on port %s", server.address().port);
});
Now you can call http://localhost:8888/#home
It looks like a problem with the path. Your index.html is located at public/htmls/index.html and views/index.html. Your root option in res.sendFile should be __dirname+/public/htmls/ or __dirname+/views
In your code, you are using the path:
res.sendFile('index.html', { root: __dirname });
Your app.js would be in the project root where you have public directory alongside at the same level. Based on your rootoption in res.sendFile, you would have to place index.html at the same level as your app.js.
You should change the root path in res.sendFile. Use:
res.sendFile('index.html', { root: path.join(__dirname, 'public', 'htmls') });
OR
res.sendFile('index.html', { root: path.join(__dirname, 'views') });
The above root is based on the path that you've mentioned in your question.
Here's the link to the docs:
http://expressjs.com/en/api.html#res.sendFile
Your no default engine error is probably because you have commented the line where you set the view engine to ejs but still have existing ejs views. Uncommenting that line with the root path change should solve your issue.
Do not serve static content from an application server.
Use a web server for that, and in production, a content delivery network like Akamai.
A content delivery network will charge you per bandwidth (e.g: 10 cents per Terabyte). Serving the equivalent of 10 cents in Akamai can cost you thousands of dollars using cloud instances.
In addition to that, your servers will have unnecessary load.
If you absolutely have to serve static content from your application servers, then put a reverse proxy cache like nginx, varnish or squid in front of your server. But that will still be very cost inefficient. This is documented in the express website.
This is common practice in every Internet company.
As my username implies, I'm new to node.js. I'm trying to learn it. As part of this process, I'm working to setup a basic web site. This web site will show a couple of basic web pages and expose a single REST endpoint. The structure of my project is:
config.js
home.html
start.js
routes.js
server.js
resources
css
style.css
images
up.png
down.png
javascript
home.html.js
start.js has my main server code. That file gets executed via command line using 'node start.js'. Once started, my server begins listening on port 3000. The code in start.js looks like this:
var express = require('express');
var app = express();
var UserProfileHandler = require('./app/handlers/UserProfileHandler');
app.configure(function () {
app.engine('html', require('ejs').renderFile);
app.set('views', __dirname + '/');
app.use(express.logger({ stream: expressLogFile }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
var routes = {
userProfiles: new UserProfileHandler()
};
function start() {
routeConfig.setup(app, routes);
var port = process.env.PORT || 3000;
app.listen(port);
console.log("SUCCESS: Server listening on port %d in %s mode", port, app.settings.env);
}
exports.start = start;
exports.app = app;
My routes.js file has the following:
function setup(app, routes) {
viewSetup(app);
apiSetup(app, routes);
}
function viewSetup(app) {
app.get('/', function (req, res) {
res.render("/home.html");
});
app.get('/home.html', function (req, res) {
res.render("/home.html");
});
}
function apiSetup(app, routes) {
app.get('/api/userProfiles/:username', routes.userProfiles.getUserProfiles);
}
I am trying to load home.html in a browser window. I attempt this by visiting http://localhost:3000 and http://localhost:3000/ and http://localhost:3000/home.html. Unfortunately, none of these work. In fact, I receive an error that says:
Express 500 Error: Failed to lookup view "/home.html"
I know that I'm close. If I visit http://localhost:3000/api/userProfiles/me I receive a JSON response back like I'm expecting. For some reason, i can't seem to return HTML though. My home.html file looks like the following.
<html>
<head>
<script type='text/javascript' src='/resources/javascript/home.html.js'></script>
</head>
<body>
We're up and running! <img src='/resources/images/up.png' />
</body>
</html>
Its a pretty basic HTML file. Even if the HTML comes back though, I'm concerned the JavaScript file and Image it references won't be accessible. I'm concerned of this because I'm not really sure how paths and such work in Node.
How do I get home.html to work in my Node setup?
Thank you!
as your view file is in same folder as your main file, below changes should make it work
1.change the view folder configuration line
from
app.set('views', __dirname + '/');//wont work
to
app.set('views', __dirname);//will work
2.change view render lines
from
res.render("/home.html");//wont work
to
res.render("home.html");//will work
with both the changes, the view should be working fine
update to below comments.
the issue you mentioned regarding the images,css and js is due to the static folder configuration which should be changed from
app.use(express.static(__dirname + '/public'));
to
app.use(express.static(__dirname + '/resources'));
as your static folder is named resources.
but make sure in your view you are refering the css/js/image files like
eg:
/css/style.css
/images/up.png
/images/down.png
/javascript/home.html.js
from your view file
Also if the above dint work, check if you have given the path correctly and also you can try by taking the
app.use(express.static(__dirname + '/resources'));
before the
app.use(express.methodOverride());
app.use(app.router);
lines like
app.configure(function () {
app.engine('html', require('ejs').renderFile);
app.set('views', __dirname + '/');
app.use(express.static(__dirname + '/public'));
//try changing the position of above line in app.configure and resatrt node app
app.use(express.logger({ stream: expressLogFile }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
});
had similar problem in my case is
app.set('./views');
look for the dot, dont know why but the dot will mess it up.
I had it like this
app.set('/views') and no matter what i did couldt find the folder until added the dot.
I am new to node and server-side development in general and started having a look at it today so mind my question. I have looked for suiting answers in previous post, yet somehow every suggested solution was criticized by many users.
I can't serve static scripts/styles due to the following error:
Failed to load resource: the server responded with a status of 404 (Not Found)
I am using express 3.1.0.
Here is my code:
app.js
var express = require('express');
var app = express();
var routes = require('./routes');
app.configure(function () {
app.set('view engine', 'jade');
app.use(express.static(__dirname + '/public'));
});
app.get('/', routes.home);
app.get('/about', routes.about);
app.get('/blog', routes.blog);
app.get('/faq', routes.faq);
app.get('/terms', routes.terms);
app.get('/privacy', routes.privacy);
app.get('/jobs', routes.jobs);
app.get('/press', routes.press);
app.listen(8080);
index.js (routes)
exports.home = function(req, res){
res.render('home', { title: "Home"});
};
exports.about = function(req, res){
res.render('about', { title: "About" });
};
etc...
layout.jade
doctype 5
html
head
title= title
link(rel='stylesheet', href='public/styles/bootstrap.css')
body
block content
br
a(href='../') Home
br
a(href='../about') About
br
etc...
home.jade
extends layout
block content
p Home
When you setup server middlewere it looks for requests at the root unless specified otherwise if you are looking for a stylesheet in "public/styles" you request it at just "/styles"
to make the middlewere answer to requests to /public change it to
app.use('/public', express.static(__dirname + '/public'));
I tried using
app.use('/public', express.static(__dirname + '/public'));
instead of
app.use(express.static(__dirname + '/public'));
and it worked.
However according to the first answer in this post: express.js not serving my image it is not considered good. I can't understand why? And what else would be a better solution?