Node JS, Express & Pug Confusion - links / routes - javascript

I have Node.js, Express and Pug installed, and thought I was doing an MVC application. However, while I want my frontend pages to be (home, about, contact, login) with (snippets of data to connect to the backend) I can create these with pug (under views).
Wouldn't it be much faster to do these pages as static under my public folder with a stylesheet attached? Of course, I believe they would then need to be compiled into HTML for these to work I.
All I want to be able to do is create navigation that links these pages simply in pug, however, when running NPM I keep getting 404 errors (despite it working this morning).
If I can do this easily with pug, and just put a link, then why am I creating routes on the backend? Can someone please clarify this?
Pug (Sep nav file)
nav
a(href="/") Home
a(href="about") Framework
a(href="contact") Pricing
a(href="login") Support
Express Routes
app.get("/about", (req, res) => {
res.render("about");
});
app.get("/contact", (req, res) => {
res.render("contact");
});
app.get("/login", (req, res) => {
res.render("login");
});
app js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// View Engine ----------------------------
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Routes
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.get("/about", (req, res) => {
res.render("about");
});
app.get("/contact", (req, res) => {
res.render("contact");
});
app.get("/login", (req, res) => {
res.render("login");
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
I've used Django before and despite its MVT (its very similar) but a lot simpler I think and I was able to do e.g %link% to insert it into the HTML page.

Related

Not able to route some sites with ejs

I'm working on my side structure and tried to add multiple single pages.
Here is my site structure:
bin
node_modules
public
query
routes
- index.js
views
-menu
--menu1.ejs
--menu2.ejs
--menu3.ejs
-partials
--header.ejs
-index.js
-anzeige.js
-eintragen.js
I tried to route the sites in my index.js like this:
//works
router.get('/', (req, res) => {
console.log('Request for index recieved');
res.render('index');
});
//works
router.get('/menu1', (req, res) => {
console.log('Request for menu1 page recieved');
res.render('menu/menu1');
});
//not working
router.get('/menu2', (req, res) => {
console.log('Request for menu2 page recieved');
res.render('menu/menu2');
});
//not working
router.get('/menu3', (req, res) => {
console.log('Request for menu3 page recieved');
res.render('menu/menu3');
});
//works
router.get('/anzeige', (req, res) => {
console.log('Request for anzeige page recieved');
res.render('anzeige');
});
I also added index.js to my app.js as a route but somehow my console says me that menu2 and menu3 can't be found (error 500 internal server error).
Request for menu2 page recieved
GET /menu2 500 7.958 ms - 305
GET http://localhost:3000/menu2 500 (Internal Server Error)
Additionally my app.js, which first creates const routes and implents it afterwards with app.use('/', routes);
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
//Place routes here
//var indexRouter = require('./routes/index');
const routes = require('./routes');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
//add routes here
app.use('/', routes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
menu2.ejs
<!DOCTYPE html>
<html lang="de">
<head>
<title>Speiseplan anzeige</title>
<%- include('partials/header') %>
</head>
<body class="mainContainer">
<div class="midContainer">
<h1>menu2</h1>
</div>
</body>
</html>
Am I missing something? It's a bit strange that some sites work and some not.
Problem found - here the soultion for everyone with the some problem.
As Rajan mentioned I should use ../partials/header instead of partials/header.
This worked for me and everything is now displayed perfectly.
Thank you all!

Express.js unexpected 'GET' to '/json/version'

I'm new to Express, but I keep getting a 404 error because something is making a GET request to '/json/version'. It goes through the first app.use('/') and adds the session data, then it ignores the two routers, and then triggers the 404 error handling. Does anyone know where it could be coming from? It's holding up my project and I'm quite frustrated.
I found someone with the same issue here, but nothing has been very helpful (as far as I can tell). Most of this app is generated from express-generator, with only the session being added by me, but I can't find any documentation from express-session that says this is expected behavior. Below is my code.
// Package requirements
let createError = require('http-errors'),
express = require('express'),
session = require('express-session'),
path = require('path'),
cookieParser = require('cookie-parser'),
logger = require('morgan');
// Local requirements
let indexRouter = require('./routes/index'),
usersRouter = require('./routes/users');
// App definition
let app = express();
// View engine setup (EJS)
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// Session data
app.use(session({
secret: 'Super Secret',
}));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', (req, res, next) => {
req.session.id = 1;
next();
});
app.use('/', indexRouter);
app.use('/', usersRouter);
// Catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// Error handler
app.use(function(err, req, res) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
// Specifies Node.js port
app.listen(3000, function() {
console.log('Listening on port 3000')
});
module.exports = app;
Thanks in advance!
Was addressed in this issue.
Click "Configure" in chrome://inspect and remove port 3000

Express node.js - understanding routing

I have this about.js route and it works fine but I don't understand how / in router.get() would work while /about wouldn't?
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('about', { title: 'About' });
});
module.exports = router;
----------------- UPDATE ----------------------
It's basically what I got out of the box after installing express.js
except the about lines.
I expected router.get('/about' ...) in about.js would work but it threw an error and it worked with / instead and that's what bugs me.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var about = require('./routes/about');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/about', about);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
The problem
When you define a route on your app.js as you did with app.use('/about', about);. You are already telling express that you expect requests to hit http://yourserver/about route.
If you try to define /about again inside your about.js with:
router.get('/', function(req, res, next) {
res.render('about', { title: 'About' });
});
What you're doing is tellig the Express that you will hit a /about inside your firstly declared /about. So it will expect requests on this route: http://yourserver/about/about
The solution
It's actually what you're using. Define a root route inside your about.js as:
router.get('/', function(req, res, next) {
res.render('about', { title: 'About' });
});
This way your app will be:
Modular since you're using different files for different routes (about.js, users.js)
Easier to read
With simplier routes inside each file, since you don't need to type /about everytime you wish to create a new route.
If you wish a http://yourserver/about/help simply add a handler inside your route file about.js as here:
router.get('/help', function(req, res, next) {
res.render('help', { title: 'Help' });
});
If you want the route /about work then you have to create another route:
router.get('/about', function(req, res, next) {
res.render('about-page', { title: 'About' });
});
because / will only work for the home page.

Basic nodejs route resulting in 404

I am trying to create two separate routes in NodeJS, I am using the express framework and angular on the client side. I am currently able to render my index page successfully by visiting localhost:3000/ although when I try to render the login page by visiting localhost:3000/login I am getting a GET /login 404 error and not sure why b/c I set it up extremely similar to the index route. Not sure if I missed something.
This my app.js
//require dependencies
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//require routes but do not user yet
var routes = require('./routes/index');
var login = require('./routes/login');
//start app
var app = express();
// view engine setup - default views directory
app.set('views', path.join(__dirname, 'views'));
app.locals.delimiters = '<% %>';
app.set('view engine', 'hjs'); //use hogan templating for views
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/login', login);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
routes/login.js
var express = require('express');
var router = express.Router();
router.get('/login', function(req, res){
res.render('login');
});
module.exports = router;
views/login.hjs
<!DOCTYPE html>
<html>
<head>
</head>
<body>
HELLO WORLD
</body>
</html>
Visiting localhost:3000/login renders the following:
{{ message }}
{{ error.status }}
{{ error.stack }}
When writing app.use('/login', login), you are telling Express to use your router under the namespace : '/login'; Therefore, all routes defined into login.js don't need this prefix.
Try to access localhost:3000/login/login ;)
Then, just change your router to:
router.get('/', function(req, res){
res.render('login');
});

Why the /users route in Express and Node?

Edit: The default express app is this:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
----------------------------------------
These refer to files that look like:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
module.exports = router;
------------------------------
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
However, the documentation says:
// this middleware will not allow the request to go beyond it
app.use(function(req, res, next) {
res.send('Hello World');
})
// requests will never reach this route
app.get('/', function (req, res) {
res.send('Welcome');
})
So my question, is why would a request ever make its way to the /users route when a default (i.e. '/') route has already been specified? Is it because routes and users are not functions?
On a related note, why even specify the / if that is what is used by default each time?
Lastly, the default app specifies the '/users' route: Why not just put another path in the index.js route? I am confused how the app can specify app.use('/users', users) and then, in the users route, specify
router.get('/', function(req, res) {
res.send('respond with a resource');
});
What does the / correspond to? It seemed like all requests to / would be handled by the first route (the one that use the routes default file)
app.use() is middleware. You pass it an optional path and a function and it is the function's job to decide if it wants to pass the request on to further middleware or further routes. It does that by calling next() or if it doesn't want to pass it on, it doesn't call next().
So, if you have:
app.use("/", fn);
That middleware will get called for all paths, but the code inside the function you pass it decides whether to pass the request on or not.
There are two routers in the Express 4 application skeleton: routes (mounted on '/') and users (mounted on '/users'). You may use both of them or only routes or you may even add more routers.
app.js:
var routes = require('./routes/index');
var users = require('./routes/users');
app.use('/users', users); // please note the mounting point!
app.use('/', routes);
users.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
Please note that router.get('/', ... ) for the users router means that the requested url is http://yourserver/users and not http://yourserver/

Categories

Resources