Static files not served by express when using pug - node.js

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

Related

EJS file not loading after using express.static

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)...

How redirect from a hbs(handlebars) page to a html page

I am working on my portfolio project. I am using handlebars and nodeJS.
I have a section called projects where I list 4 different projects to showcase. I have an index.js where all my routing is done. Projects 1,3,4 work just fine. These all will be clicked on from a project section on my index page.
However, I am so lost on how to route my project 2. Projects 1,3,4 are all handlebars(.hbs). But my project 2 is an html page. As seen in my code snippet, the html is store under the same /public folder as all my other code. However, I still get the error "Failed to lookup view "../public/views/fountainWebsite/html/home" in views directory". I am not sure how this needs to be done??
// === VARIABLES === //
var express = require('express');
var app = express();
var handlebars = require("express-handlebars");
var path = require("path");
var router = express.Router(); //creates a router object
//===== view ENGINE SET UP =====//
app.set('view engine', 'handlebars');
app.engine(
"hbs",
handlebars({
layoutsDir: path.join(__dirname, "/public/views/layouts"),
partialsDir: path.join(__dirname, "/public/views/partials"),
extname: ".hbs", //expected file extension for handlebars files
defaultLayout: "layout" //default layout for app, general template for all pages in app
})
);
app.set("views", path.join(__dirname, "views"));
//thought this would maybe fix the error?? It didn't//
// app.set("fountainWebsite", path.join(__dirname, "fountainWebsite")); //
app.set("view engine", "hbs");
app.use("/public", express.static(path.join(__dirname, "public")));
//===== .GET PAGES =====//
app.get('/', (req, res, next) => {
res.render('../public/views/index', {title: 'Home Page', css:['../public/css/style.css'], js:['../public/js/navBar.js']});
});
app.use('/', router);
router.get('/project1', (req, res, next) => {
res.render('../public/views/partials/project1', {title: 'Data Structures', css:['../public/css/projects.css'], js:['../public/js/navBar.js']});
});
//error here//
router.get('/project2', (req, res, next) => {
res.render('../public/views/fountainWebsite/html/home');
});
router.get('/project3', (req, res, next) => {
res.render('../public/views/partials/project3', {title: 'This Portfolio', css:['../public/css/projects.css'], js:['../public/js/navBar.js']});
});
router.get('/project4', (req, res, next) => {
res.render('../public/views/partials/project4', {title: 'Dictionary', css:['../public/css/projects.css'], js:['../public/js/navBar.js']});
});
It is important that we understand what our code is doing. Let's start with the route handler for /project2:
router.get('/project2', (req, res, next) => {
res.render('../public/views/fountainWebsite/html/home');
});
This is telling Express to listen for a request with the path /project2 and to render the file at ../public/views/fountainWebsite/html/home.
Handlebars requires an extension (like .hbs) in order to know which view engines to use to render the file. As we have omitted an extension from our file path, Express will assume the extension is .hbs because that's what we told it to do when we called app.set("view engine", "hbs");
I have to assume that your file path with extension is ../public/views/fountainWebsite/html/home.html since you have put it in a folder called "html". If this is the case, Handlebars is not going to find this file because it is looking for ../public/views/fountainWebsite/html/home.hbs and it will throw an Error.
The simple solution would be to rename this file with a .hbs extension. This will at least allow Express to locate the file and render it through the Handlebars view engine.
However, one problem with this approach may be that this view gets rendered wrapped in your layout.hbs file and you do not want that. Perhaps you want this HTML file to be unprocessed and served as a static asset.
In this case, you could remove the /project2 route handler and let Express serve this file as a static asset. Since you have already registered your public/ folder as static assets folder with the call app.use("/public", express.static(path.join(__dirname, "public"))); and your file path shows that this HTML file is already within the public/ folder, you should be able to request this HTML directly from your browser at the path /public/views/fountainWebsite/html/home.html.

Use `index.html` rather than `index.ejs`

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.

Fails to look up view in Express

This is the structure of my project.
app
-controllers
index.server.controller.js
-models
-routes
index.server.routes.js
-views
index.ejs
config
-express.js
I set the view directory in my express.js file:
app.set('views', '../app/views');
app.set('view engine', 'ejs');
And this is in my controller file:
exports.render = function(req,res) {
res.render('index' , {
title: 'welcome to this page'
})
};
Whenever i open localhost i get
Error: Failed to lookup view "index" in views directory "../app/views/"
You're giving it a wrong path. Try this
app.set('views', __dirname + '/../app/views');

Serve static content and views from same directory?

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.

Resources