I just start learning NodeJS and seems amazing to me. Anyway, I'm facing a weird issue about the view rendering. Essentially I want use the MVC pattern, so I organized my project in the following way:
Inside app.js I wrote the following code:
const express = require('express');
const app = express();
require('./config/environment.js')(app, express);
require('./config/routes.js')(app);
app.listen(process.env.PORT || 3000);
Essentially, I declared the server using expressjs 'cause is indicated for MVC application, and then I placed all the configuration for the environment within envinroment.js, passing to the constructor of the module the app and the express:
module.exports = function(app, express){
app.set('development', function(){
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
app.set('production', function(){
app.use(express.errorHandler());
});
app.set('view engine', 'ejs');
app.set('views', __dirname);
if(process.env.NODE_ENV === 'production'){
app.set('port', 80);
}
};
as you can see I setted as view engine the ejs package, so in this way I can render html file within a javascript file and pass information to the view.
Then in routes.js I wrote:
module.exports = function(app){
app.get('/', function(req, res){
res.render('home.ejs', {counter: 2});
});
};
this is the code that cause the problem, infact when I load my application I get:
Failed to lookup view "home.ejs"
I also tried using:
const path = require('path');
res.render(path.join(__dirname+'/views/home.ejs'), {counter: 2});
but same problem..
Thanks in advance for any help
Add
let path = require('path');
to the start of your script.
Then, in your app.js write:
app.set("views", path.join(__dirname, "..", "views"));
instead of just "app.set('views', __dirname);".
And in your routes.js write:
res.render('home', {
counter: 2
});
Related
I am building a Node.JS app with Express and Handlebars to serve the public content. The app is running in pm2.
The app is working fine, but I want to serve static files. I added 2 static routes which are loaded fine when I check the Express log.
But when I try to access the files, I get a 404. I noticed the message on the 404 states "Cannot GET /js" where I would expect "Cannot GET /scripts/scripts.min.js".
The URL should be on /scripts/scripts.min.js, internally it's located inside a public folder:
app.js
public
scripts
scripts.min.js
images
styles
Here is my app.js:
const express = require('express');
const { engine } = require('express-handlebars');
require('dotenv').config();
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
const {
NODE_ENV,
PORT,
HOST,
} = process.env;
// Use body-parser middleware
app.use(bodyParser.json());
// Use express-handlebars as the view engine
app.engine('handlebars', engine({
defaultLayout: 'main',
layoutsDir: __dirname + '/views/layouts',
partialsDir: __dirname + '/views/partials',
}));
app.set('view engine', 'handlebars');
app.set('views', __dirname + '/views');
app.use(express.static(path.join(__dirname, 'public')))
app.use('/scripts/monaco/', express.static(path.join(__dirname, 'node_modules','monaco-editor','min','vs')));
// Define routes
app.get('/', (req, res) => {
res.render('home', { title: 'Home' });
});
app.get('/debug', (req, res) => {
res.send(__dirname + '/public')
})
app.post('/', (req, res) => {
console.log(req.body);
res.send('Success');
});
// Load external routes (also tried the staticFiles by using res.sendFile)
require('./routes/processing')(app);
// require('./routes/staticFiles')(app);
// Start the server
app.listen(PORT, () => {
app.currentServer = {
host: HOST ? HOST : "127.0.0.1",
port: PORT,
};
console.log(`Server init on: http://:${PORT}`);
});
I tried serving the files using express.static, I also tried sending them trough specific routes by using res.sendFile.
It looks like Express (or something else) is interpreting the URL path incorrectly. /scripts/scripts.min.js is downgraded to /js so it seems.
I hope anybody has a clue!
so I was trying to follow a tutorial to use node.js as the front end of a wordpress site
This one http://www.1001.io/improve-wordpress-with-nodejs/
Here is the code from server.js
var frnt = require('frnt');
var fs = require("fs");
var path = require("path");
var express = require('express');
var app = express();
var doT = require('express-dot');
// Define where the public files are, in this example ./public
app.use(express.static(path.join(__dirname, 'public')));
// Make sure this is set before the frnt middleware, otherwise you won't
// be able to create custom routes.
app.use(app.router);
// Setup the frnt middleware with the link to the internal server
app.use(frnt.init({
proxyUrl: "http://localhost:8888/frnt-example/wordpress", // The link to your wordpress site
layout: false // We simplify this example by not using layouts
}));
// define rendering engine
app.set('views', path.join(__dirname, "views"));
app.set('view engine', 'html' );
app.engine('html', doT.__express );
// respond with "Hello World!" on the homepage
app.get('/', function (req, res) {
res.send('./views/index.html');
});
app.listen(8080); // listen to port 8080
It keeps outputting the following
./views/index.html
Rather than rendering the html?
I've never used frnt, but res.send sends a string so that's no big surprise.
Look at res.sendfile which sends the contents of a file.
I prefer to use ejs , it's sems like html just edit index.html to index.ejs
1- install ejs module npm install ejs
2- add this in app.js
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
and render the index.ejs by using
app.get('/', function (req, res) {
res.render('index'); // or res.render('index.ejs');
});
res.send() // it send just a string not file
Hope it usefull !
Hi I'm trying to work with Express 3 using handlebars. But I am unable to "lookup the view" I am stuck with this error.
Error: Failed to lookup view "500" in views directory
"d:\projects\meadowlark\site\views" at EventEmitter.app.render
(d:\projects\meadowlark\site\node_modules\express\lib\application.js:519:17)
at ServerResponse.res.render
(d:\projects\meadowlark\site\node_modules\express\lib\response.js:904:7)
at d:\projects\meadowlark\site\meadowlark.js:29:7 at
Layer.handle_error
(d:\projects\meadowlark\site\node_modules\express\lib\router\layer.js:58:5)
at trim_prefix
(d:\projects\meadowlark\site\node_modules\express\lib\router\index.js:269:13)
at
d:\projects\meadowlark\site\node_modules\express\lib\router\index.js:238:9
at Function.proto.process_params
(d:\projects\meadowlark\site\node_modules\express\lib\router\index.js:313:12)
at
d:\projects\meadowlark\site\node_modules\express\lib\router\index.js:229:12
at Function.match_layer
(d:\projects\meadowlark\site\node_modules\express\lib\router\index.js:296:3)
at next
(d:\projects\meadowlark\site\node_modules\express\lib\router\index.js:190:10)
Its really strange for me. Can anyone explain this issue to me how can I solve it?
My js code is as follows:
var express = require('express');
var app = express();
// set up handlebars view engine
var handlebars = require('express3-handlebars')
.create({ defaultLayout:'main' });
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'handlebars');
app.set('port',process.env.port || 3000);
app.get('/', function(req, res) {
res.render('home');
});
app.get('/about', function(req, res) {
res.render('about');
});
// 404 catch-all handler (middleware)
app.use(function(req, res, next){
res.status(404);
res.render('404');
});
// 500 error handler (middleware)
app.use(function(err, req, res, next){
console.error(err.stack);
res.status(500);
res.render('500');
});
app.listen(app.get('port'),function(){
console.log('Express started on http://localhost: '+ app.get('port') + " Press CTRL+C to terminate.");
});
I think I know what the issue here is, remember this setup of app.js from an O'Reilly book ("Web Development with Node & Express").
Here's what the author fails to clarify:
If you have your .handlebars template files in views/layouts/, structure your view engine setup like this:
var path = require('path');
var express = require('express');
var handlebars = require('express-handlebars'); // 'express3-handlebars' has been deprecated
var app = express();
// Set up handlebars view engine
app.set('views', path.join(__dirname, 'views/layouts/'));
app.engine('handlebars', handlebars({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
Note that you will need the var path = require('path'); in order to set 'views' to the filepath views/layouts/.
If you read the error, it clearly tells you that you are missing a 500 view template in your template directory. I'm not sure what your directory structure you have, but place a 500.handlebars file in the same directory the 404.handlebars file is. Should be somewhere in the views/ or views/layouts directory.
Make sure that your files: home.handlebars, about.handlebars, 404.handlebars, 500.handlebars and main.handlebars don't have hidden extensions. Like this: home.handlebars.html, about.handlebars.html, 404.handlebars.html, 500.handlebars.html, and main.handlebars.html.
If they do, removing those extensions and using only the .handlebars extension should resolve the issue.
I really apologize if I'm leaving something out and am totally stupid, but I've checked and checked over again a number of times, and the file upload functionality is just not working over here. I made a super minimal app to demonstate. Just generated a new express app with the most up-to-date version (3.4.7) and added the least i could to make a file upload work.
Here's my app.js file
/**
* Module dependencies.
*/
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/tasks', function(req, res) {
res.render('form');
});
app.post('/tasks', function(req, res) {
console.log(req.files);
res.send('ok');
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
exports = module.exports = app;
And here's my form.jade view file:
doctype html
html
head
title Task Upload
body
form(action='/tasks', method='post', enctype='multipart/form-data')
input(name='task', type='file')
input(type='submit')
Everytime I try to upload a file, req.files logs out undefined. Can anyone save me out from this problem?
Add the following in your app.js
app.configure(function(){
app.use(express.methodOverride());
app.use(express.bodyParser({keepExtensions:true,uploadDir:path.join(__dirname,'/files'}));
});
And then try to access as follows;
req.files.task
It is recommended not to use bodyParser, but to simply define the type of handling you want. In your case since its file uploading, you can enable it as follows
app.configure(function(){
app.use(express.methodOverride());
app.use(express.multipart());
});
You can read about why using bodyParser() is not a good idea in the following link.
http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html
In Express 4, req.files is no longer available on the req object by default.
To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty,.
i am trying to create a route for localhost:port/admin/
and i want to keep the routes.js files and view.js files in matching folders so i wont have too much spaggeti later on
but i keep getting: 500 Error: Failed to lookup view "/admin/manage_subjects"
for trying to create a new route and using same folders few the same
i have the following view folder with express
mainapp(root)
routes(folder)
admin(folder)
index.js(nested inside admin)
index.js(nested inside routes)
views(folder)
admin(folder)
admin_layout.jade(nested inside admin)
manage_subjects.jade(nested inside admin)
index.jade(nested inside views)
layout.jade(nested inside views)
code:
routes/admin/index.js
exports.index = function (req, res) {
res.render('manage_subjects',{title:'Express'});}
views/admin/manage_subjects.jade
extends admin_layout
block content
h1 = title
p Welcome to #{title}
my app.js code
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, admin_routes = require('./routes/admin/')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, repository = new (require('./domain_model/repository'))();
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
//fill local subjects
repository.subjects.GetAll(function (err, data) {
if (err) throw err;
app.locals.subjects = data;
});
//append routes
app.get('/', routes.index);
app.get('/admin', admin_routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on http://localhost:' + app.get('port'));
});
I've been dealing with what I think is the same problem and figured out how to fix it. So in case someone else comes across this problem I'm posting my solution.
So here is what I had that was causing 404's and 500's
app.js
var routes = require('./routes/index');
var admin = require('./routes/admin');
app.use('/', routes);
app.use('/admin', admin);
and here was my routes/index.js
//append routes
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index', {title: 'Express'});
});
module.exports = router;
and my routes/admin.js:
var express = require('express');
var router = express.Router();
router.get('/admin', function(req, res) {
res.render('admin/index', {title: 'Express'});
});
module.exports = router;
by defining the second /admin inside the router.get() function I think I was effectively telling node to look for the html in my views folder under the following path views/admin/admin/index.ejs. So to fix that all I had to do was remove either the /admin from the router.get() or the /admin from the app.use()
So my working code now looks like this:
app.js
var routes = require('./routes/index');
var admin = require('./routes/admin');
app.use('/', routes);
app.use('/admin', admin); //I left the /admin here and instead removed the one in routes/admin.js
and here was my routes/index.js
//append routes
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index', {title: 'Express'});
});
module.exports = router;
and my routes/admin.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) { //NOTICE THE CHANGE HERE
res.render('admin/index', {title: 'Express'});
});
module.exports = router;
So making that change made it so I could have sub folders in my views folder.
Simple Answer for sub-folders inside the views folder (mine is called frontend)
click here the picture to see the folder structure
file app.js
app.set('views', [path.join(__dirname, 'frontend'), path.join(__dirname, 'frontend/locked'), path.join(__dirname, 'frontend/template'), path.join(__dirname, 'frontend/public')]);
app.set('view engine', 'pug')
I'd check out TJ's video on Modular apps on his vimeo the best part about this work flow is your code becomes really flexible and it's alot easier to stay DRY.
Additionally I would do something like this with my app.set("views")
var path = require("path");
app.set('views', path.join(__dirname, 'views'));
// you can then extend this to the example for routes
Another alternative would be something like in your app.js file:
var express require("express")
var app = express()
var routes = require("./path/to/routes")(app)
and then routes would look like:
routes = function (app) {
app.get("/route", middleWareifYou.gotIt, route.handler || function (req, res) {
res.send("some msg");
});
};
module.exports = routes
Cheers, I hope this helps!
I had a similar problem and what worked for me was setting the views folder in both the main app file and in the router file too.
So in the main app.js file I had:
app.set('views', viewsFolderPath);
And inside my router.js file I also did the same thing:
app.set('views', viewsFolderPath);