Error: Failed to lookup view in Express - node.js

Note: my auto answer at end of the post
I'm trying to make a better experience of nodeJS and i don't really like to get all the script in one file.
so, following a post here i use this structure
./
config/
enviroment.js
routes.js
public/
css/
styles.css
images
views
index
index.jade
section
index.jade
layout.jade
app.js
My files are right now:
app.js
var express = require('express');
var app = module.exports = express.createServer();
require('./config/enviroment.js')(app, express);
require('./config/routes.js')(app);
app.listen(3000);
enviroment.js
module.exports = function(app, express) {
app.configure(function() {
app.use(express.logger());
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/views');
app.set('view engine', 'jade'); //extension of views
});
//development configuration
app.configure('development', function() {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
//production configuration
app.configure('production', function() {
app.use(express.errorHandler());
});
};
routes.js
module.exports = function(app) {
app.get(['/','/index', '/inicio'], function(req, res) {
res.render('index/index');
});
app.get('/test', function(req, res) {
//res.render('index/index');
});
};
layout.jade
!!! 5
html
head
link(rel='stylesheet', href='/css/style.css')
title Express + Jade
body
#main
h1 Content goes here
#container!= body
index/index.jade
h1 algoa
The error i get is:
Error: Failed to lookup view "index/index"
at Function.render (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\application.js:495:17)
at render (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\response.js:614:9)
at ServerResponse.render (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\response.js:638:5)
at c:\xampp\htdocs\nodejs\buses\config\routes.js:4:7
at callbacks (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\router\index.js:177:11)
at param (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\router\index.js:151:11)
at pass (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\router\index.js:158:5)
at Router._dispatch (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\router\index.js:185:4)
at Object.router [as handle] (c:\xampp\htdocs\nodejs\buses\node_modules\express\lib\router\index.js:45:10)
at next (c:\xampp\htdocs\nodejs\buses\node_modules\express\node_modules\connect\lib\proto.js:191:15)
But i don't really know what is the problem...
I'm starting thinking is because the modules exports...
Answer:
Far away the unique solution i found is to change the place i defined app.set('views') and views engine
I moved it to the app.js and now is working well.
var express = require('express');
var app = module.exports = express.createServer();
require('./config/enviroment.js')(app, express);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
require('./config/routes.js')(app);
app.listen(3000);
I don't really understand the logic behind this but i gonna supose it have one.

Adding to #mihai's answer:
If you are in Windows, then just concatenating __dirname' + '../public' will result in wrong directory name (For example: c:\dev\app\module../public).
Instead use path, which will work irrespective of the OS:
var path = require ('path');
app.use(express.static(path.join(__dirname + '../public')));
path.join will normalize the path separator character and will return correct path value.

npm install express#2.5.9 installs the previous version, if it helps.
I know in 3.x the view layout mechanic was removed, but this might not be your problem. Also replace express.createServer() with express()
Update:
It's your __dirname from environment.js
It should be:
app.use(express.static(__dirname + '../public'));

It is solved by adding the following code in app.js file
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.set('views', __dirname);
app.get('/', function(req, res){
res.render("index");
});

I had the same error at first and i was really annoyed.
you just need to have ./ before the path to the template
res.render('./index/index');
Hope it works, worked for me.

You could set the path to a constant like this and set it using express.
const viewsPath = path.join(__dirname, '../views')
app.set('view engine','hbs')
app.set('views', viewsPath)
app.get('/', function(req, res){
res.render("index");
});
This worked for me

Check if you have used a proper view engine.
In my case I updated the npm and end up in changing the engine to 'hjs'(I was trying to uninstall jade to use pug).
So changing it to jade from hjs in app.js file worked for me.
app.set('view engine','jade');

In my case, I solved it with the following:
app.set('views', `${__dirname}/views`);
app.use(express.static(`${__dirname}/public`));
I needed to start node app.min.js from /dist folder.
My folder structure was:

This problem is basically seen because of case sensitive file name.
for example if you save file as index.jadge than its mane on route it should be "index" not "Index" in windows this is okay but in linux like server this will create issue.
1) if file name is index.jadge
app.get('/', function(req, res){
res.render("index");
});
2) if file name is Index.jadge
app.get('/', function(req, res){
res.render("Index");
});

use this code to solve the issue
app.get('/', function(req, res){
res.render("index");
});

Just noticed that I had named my file ' index.html' instead for 'index.html' with a leading space. That was why it could not find it.

This error really just has to do with the file Path,thats all you have to check,for me my parent folder was "Layouts" but my actual file was layout.html,my path had layouts on both,once i corrected that error was gone.

i had the same problem but, i change the name of the file from index.html to index.ejs and works!!!!
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.render('index');
});
router.get('/contact', (req, res) => {
res.render('contact', { title: 'Contact Page' });
});
module.exports = router;
and index.js
const express = require('express');
const morgan = require('morgan');
const path = require('path');
const app = express();
//settings
app.set('port', 4000);
app.set('views', path.join(__dirname,'views'));
app.set('view engine', 'ejs');
//middlewares
//routes
app.use(require('./routes'));
//static files
//listening
app.listen(app.get('port'), () => {
console.log('Server is running at http://localhost:'+app.get('port')+'/');
});
update:
add this in index:
app.engine('html', require('ejs').renderFile);

I change the views folder name to views_render and also facing the same issue as above, so restart server.js and it works for me.

I had the same issue and could fix it with the solution from dougwilson: from Apr 5, 2017, Github.
I changed the filename from index.js to index.pug
Then used in the '/' route: res.render('index.pug') - instead of res.render('index')
Set environment variable: DEBUG=express:view
Now it works like a charm.

I had this issue as well on Linux
I had the following
res.render('./views/index')
I changed it too
res.render('../views/index')
Everything is now working.

I had the same issue. Then just check the file directory in your explorer. Sometimes views folder isn't present.

In my case, I was deploying my web app on a Windows Server and I had a service set up to run a .bat file with only one line as content:
node D:\webapp\app.js
But this was not enough. I also had to change the directory before that, so I added the following line at the beginning of the .bat file:
cd D:\webapp

app.get("/", (req, res) => {
res.render("home");
});
// the code below brought the error
app.get("/", (req, res) => {
res.render("/");
})

I was facing this error because i mistakenly deleted my error.ejs file and it was being called in app.js file and was not found in views as it was already deleted by me

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

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.

Failed to lookup view "index" in views directory

I am trying to learn node.js.
I have the following code.
var express = require('express');
var app = express();
var port = process.env.PORT || 5000;
app.use(express.static('public'));
app.use(express.static('src/views'));
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.render('index', { title: 'Hello from render', nav: ['Books', 'Author'] });
});
Failed to lookup view "index" in views directory
I have the file named index.ejs. How can I get rid of this error?
Try with
app.set('views', __dirname + '/views');
This is how I fixed it.
app.set('views', './src/views');
app.set('view engine', 'ejs');
I had the same problem too. I have saved the index file as .html file. But it should be index.ejs. then it worked. Check that too
For me it was a banal problem: when I named my 'views' folder, accidentally I typed a white space before the name, so the name was ' veiws', thus, ejs couldn't find the 'views' folder.
i fixed this error by writing below line befor my
app.set('viewengine' , 'ejs')
app.set('views',path.join(__dirname,'views'));
using path is more convenient ,also note to require path befor using it
I had the same issue, then I saved my index file inside the views folder. Now the issue is gone. Also add this line of code in your file
app.set('views', path.join(__dirname, '/views'))

Parse Cloud Hosting with Express and Handlebars Templates

There is a node package for using handlebars templates in Express.js, express-handlebars, but I'd like to be able to use the same package in a Parse Cloud Hosting project. The only discussion I can find about how to make it work is here, and it's painfully brief: https://parse.com/questions/dynamic-website-handlebars-for-template-engine
The last comment mentions specifying the 'cloud' directory 'to the required command for a lot of dependent modules'. The author does not explain how he did that, and the thread is now closed.
After following the install instructions I have this in my main app.js file:
var express = require('express');
var exphbs = require('express-handlebars');
var parseExpressCookieSession = require('parse-express-cookie-session');
var home = require('cloud/routes/home');
var register = require('cloud/routes/register');
var login = require('cloud/routes/login');
var app = express();
// Configure the app
app.set('views', 'cloud/views');
app.set('view engine', 'hbs');
app.engine('hbs', exphbs({
extname: 'hbs',
defaultLayout: 'layouts/main.hbs'
}));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('ABCDEFG1234567'));
app.use(parseExpressCookieSession({ cookie: { maxAge: 3600000 }}));
app.use(app.router);
// Define all the endpoints
app.get('/', home.index);
app.get('/register', register.new);
app.post('/register', register.create);
app.get('/login', login.new);
app.post('/login', login.create);
app.get('/logout', login.destroy);
app.listen();
My file structure looks like this:
cloud
└──routes
└──views
└──layouts
└──main.hbs
└──home
└──index.hbs
└──register
└──new.hbs
└──login
└──new.hbs
config
node_modules
public
package.json
All route files are a slight variation of this:
exports.index = function(req, res){
res.render('home/index');
};
Running my app results in the following error:
Error: Failed to lookup view "home/index"
With the default 'ejs' templates, the app runs fine. Personally, I'm fine with ejs templates, but it's not up to me. Handlebars are what's required of the project, so that's what I'm out to accomplish. Thanks!

Node.js Express rendering any *.jade

I have a test node.js server running the following code:
var app = require('express')();
app.set('views', __dirname + '/public');
app.set('view engine', 'jade');
app.get('/', function(req, res) {
res.render('index.jade', {name: "Test data."});
});
app.listen(3000);
This code works find. I'm wondering what the best practices are for choosing a .jade file based upon the url without hard-coding it, kind of like you might for html files using express.static. Of course, I don't want there to be a direct path correlation either (instead assigning different routes to different directories or groups of directories.) There doesn't seem to be a whole lot of solid information on the subject. Anything would be helpful. Thanks.
with utilization of splats you could do something like this:
var app = require('express')();
app.set('view engine', 'jade');
// /foo/Sam/path/to/view.jade yield a rendering of 'path/to/view.jade' with name: 'Sam'
app.get('/foo/:name/*.*', function(req, res) {
res.render(req.params.join('.'), {name: req.params.name});
});
app.listen(3000);

Resources