Im building my first node.js app with express and pug as view/template eingine. A problem I am experiencing atm is the following:
Issue: Same CSS file loads on other routes & template.pugs but won't load on one specific route/template. Get a 404 error.
my server.js:
var express = require('express');
var path = require('path');
var app = express();
var bodyParser = require("body-parser");
app.set('views', './templates');
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, './public')));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
require('./router')(app);
var listener = app.listen(process.env.PORT, function() {
console.log('Server is live on PORT : ' + listener.address().port);
});
my router.js (css loads for "/" & "/events", not for /events/new"):
var controller = require ('./controller');
module.exports = function (app) {
//start
app.get('/', controller.index);
// All Events View
app.get('/events', controller.show_events);
app.get('/events/new', controller.new_event_form);
};
my controller.js (css loads for "index" & "show_events", not for "new_event_form" )
module.exports = {
index: index,
show_events: show_events,
new_event_form: new_event_form
};
function index (req, res) {
res.render('index');
}
function show_events(req, res) {
res.render('show_events');
};
function new_event_form(req, res) {
res.render('new_event_form');
};
Now comes the odd part. For this template "show_events.pug" it loads the css file. route: /events
doctype
html
head
title Database
link(rel='stylesheet', href='./css/main.css')
link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Roboto:400,400i,700')
body
div#wrapper
header
h1 Database: Events
menu
a(href='/')
h2 Back
a(href='/events/new')
h2 Create New Event
But for this template "new_event_form.pug" it won't load the css file. Route: /events/new
doctype
html
head
title Database
link(rel='stylesheet', href='./css/main.css')
link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Roboto:400,400i,700')
body
div#wrapper
header
h1 Event: New
menu
a(href='/events')
h2 Cancel
Css perfectly loads as well for the index "/" route.
Folder/file structure so far
controller.js
router.js
server.js
public
- - css
- - - - main.css
templates
- - index.pug
- - show_events.pug
- - new_event_form.pug
Kind find any mistake so far, don't get why it loads on the index route and the show_events route, but not on the new_event_form route.
Thanks for any hints or solution !
Update
when comparing the routes i noticed some differencies:
- for https://terminal.glitch.me/events the request adress for the css file is https://terminal.glitch.me/css/main.css
- for https://terminal.glitch.me/events/new the request adress for the css
file is https://terminal.glitch.me/events/css/main.css
So simple:
In the pug file for the events/new route the link ref should contain
2 dots before /css/main.css, not 1
So I changed this
link(rel='stylesheet', href='./css/main.css')
to this
link(rel='stylesheet', href='../css/main.css')
now it's working
It was just not clear for me how to use ../ this type of things for absolute paths ...
Related
So, this is a strange one. I am running a Nodejs application using Express and Pug. I have all my static files in a Public folder and my Pug files in the Views folder. I set up the app.js file to grab all the static files from the Public folder. I am using Nginx to handle the server.
Here is the weird part, when i run it on a Ubuntu instance using AWS I get a 404 on all of my js and css files. When i run it on my local computer I get 304 errors, but everything loads and works.
Any ideas what I did wrong? I will Show some of my code beneath.
Pug File
doctype html
html
head
meta(charset='utf-8')
title Signature Pad
meta(name='description', content='Signature Pad - HTML5 canvas based smooth signature drawing using variable width spline interpolation.')
meta(name='viewport', content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no')
meta(name='apple-mobile-web-app-capable', content='yes')
meta(name='apple-mobile-web-app-status-bar-style', content='black')
link(rel='stylesheet', href='stylesheets/signature-pad.css')
#signature-pad.signature-pad
.signature-pad--body
canvas
.signature-pad--footer
div
.description Sign Above
.signature-pad--actions
div
button.button.clear(type='button', data-action='clear') Clear
button.button(type='button', data-action='undo') Undo
div
form(action='', method='POST', onsubmit='completeAndRedirect();return false;')
label(for='fname') First name:
input#firstName(type='text', name='fname')
label(for='lname') Last name:
input#lastName(type='text', name='lname')
br
br
label(for='company') Company:
input#company(type='text', name='company')
br
br
input.button.save(type='submit', value='Submit', data-action='save-svg')
script(src='js/signature_pad.umd.js')
script(src='js/app.js')
App.js file
const express = require('express');
const path = require('path');
const NetSuiteOauth = require('netsuite-tba-oauth');
const bodyParser = require('body-parser');
const app = express();
//Parse incoming request
app.use(bodyParser.json());
//app.use(bodyParser.urlencoded({ extended: false }));
//View engine
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
//Static Files
app.use(express.static(__dirname + '/Public'));
app.get('/', (req, res, next)=> {
return res.render('landing', {title: 'Home'})
});
app.get('/customer', (req, res, next)=> {
return res.render('signature', {title: 'Customer'})
});
app.get('/employee', (req, res, next)=> {
return res.render('signature', {title: 'Employee'})
});
app.post('/customer', (req, res, next)=>{
return res.render('entered', {title: 'Home'})
});
app.post('/employee', (req, res, next)=>{
return res.render('entered', {title: 'Home'})
});
app.listen(8080);
Folder Structure
Image of File Structure
Please let me know if I am not clear, first time posing on Stack
On nginx in your production server, you need to modify the sites_available file, to point to your static folder as default.
server {
root /www/data;
location / {
}
.....
}
please check attached link for serving static folder static nginx
This question already has an answer here:
Resource was blocked due to MIME type mismatch using pug and node
(1 answer)
Closed 2 years ago.
This happens only when I use route.
./routes/users.js
const express = require('express');
const router = express.Router();
const dbQuery = require('../controllers/db_query');
router.get('/', async function(req, res) {
console.log('ROUTE - /');
const result = await dbQuery.getUsers();
res.render('users', {
data: result
});
});
router.get('/:id', async function(req, res) {
console.log('ROUTE - /id');
const result = await dbQuery.getUser(req.params.id);
console.log('result', result);
res.render('user', {
data: result
});
});
module.exports = router;
./App.js
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 setup
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')));
app.use('/', indexRouter);
app.use('/users', 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, 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;
./routes/users.js
const router = express.Router();
const dbQuery = require('../controllers/db_query');
router.get('/', async function(req, res) {
console.log('ROUTE - /');
const result = await dbQuery.getUsers();
res.render('users', {
data: result
});
});
router.get('/:id', async function(req, res) {
console.log('ROUTE - /id');
const result = await dbQuery.getUser(req.params.id);
console.log('result', result);
res.render('user', {
data: result
});
});
module.exports = router;
./views/users.pug
extends layout
block content
// Navigation
nav#mainNav.navbar.navbar-expand-lg.navbar-light.fixed-top
.container
a.navbar-brand.js-scroll-trigger(href='/') Node.js Excersise
button.navbar-toggler.navbar-toggler-right(type='button' data-toggle='collapse' data-target='#navbarResponsive' aria-controls='navbarResponsive' aria-expanded='false' aria-label='Toggle navigation')
| Menu
i.fas.fa-bars
// Masthead
header.masthead
.container.d-flex.h-100.align-items-center
.mx-auto.text-center
h1.mx-auto.my-0.text-uppercase Users List
h2.text-white-50.mx-auto.mt-2.mb-5 This is where you can find all the users.
// Projects
section#projects.projects-section.bg-light
.container
.col-md-10.col-lg-8.mx-auto.text-center
ul
each user in data
div(class='profile-tile')
img(class='img-rounded' src='images/profile/' + user.Uid + '.jpg' alt= user.Uid + ' image')
br
a(class='profile-name' href='/users/' + user.Uid)= user.Uname
li(style='list-style-type:none')= user.Uemail
// Contact
section.contact-section.bg-black
.container
.col-md-10.col-lg-8.mx-auto.text-center
button.btn.btn-primary.mx-auto(onclick="window.location.href='/'") Back
.social.d-flex.justify-content-center
a.mx-2(href='#!')
i.fab.fa-twitter
a.mx-2(href='#!')
i.fab.fa-facebook-f
a.mx-2(href='#!')
i.fab.fa-github
// Footer
footer.footer.bg-black.small.text-center.text-white-50
.container Copyright © : node.js.exercise 2020
// Bootstrap core JS
script(src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js')
script(src='javascript/bootstrap.bundle.min.js')
// Third party plugin JS
script(src='https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js')
// Core theme JS
script(src='javascripts/scripts.js')
Below is my problem.
I tried to display the data I got from db and pass by route to render. (see h1 and img)
I have the result as expected, BUT the image(img) is not displaying and the CSS of the page.
by the way the code below is same with the ./views/users.pug, I did just display the data in simpler way.
./views/user.pug
extends layout
block content
nav#mainNav.navbar.navbar-expand-lg.navbar-light.fixed-top
.container
a.navbar-brand.js-scroll-trigger(href='/') Node.js Excersise
button.navbar-toggler.navbar-toggler-right(type='button' data-toggle='collapse' data-target='#navbarResponsive' aria-controls='navbarResponsive' aria-expanded='false' aria-label='Toggle navigation')
| Menu
i.fas.fa-bars
// Masthead
header.masthead
.container.d-flex.h-100.align-items-center
.mx-auto.text-center
h1.mx-auto.my-0.text-uppercase Users List
h2.text-white-50.mx-auto.mt-2.mb-5 This is where you can find all the users.
// Projects
section#projects.projects-section.bg-light
.container
.col-md-10.col-lg-8.mx-auto.text-center
div(class='profile-tile')
img(class='img-rounded' src='images/profile/' + data[0].Uid + '.jpg' alt='image')
h1= data[0].Uid
h1= data[0].Uname
h1= data[0].Uemail
// Contact
section.contact-section.bg-black
.container
.col-md-10.col-lg-8.mx-auto.text-center
button.btn.btn-primary.mx-auto(onclick="window.location.href='/'") Back
.social.d-flex.justify-content-center
a.mx-2(href='#!')
i.fab.fa-twitter
a.mx-2(href='#!')
i.fab.fa-facebook-f
a.mx-2(href='#!')
i.fab.fa-github
// Footer
footer.footer.bg-black.small.text-center.text-white-50
.container Copyright © : node.js.exercise 2020
// Bootstrap core JS
script(src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js')
script(src='javascript/bootstrap.bundle.min.js')
// Third party plugin JS
script(src='https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js')
// Core theme JS
script(src='javascripts/scripts.js')
./views/layout.js
head
meta(charset='utf-8')
meta(name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no')
meta(name='description' content='')
meta(name='author' content='')
title Node.js
link(rel='icon' type='image/x-icon' href='/images/favicon.ico')
// Font Awesome icons (free version)
script(src='https://use.fontawesome.com/releases/v5.13.0/js/all.js' crossorigin='anonymous')
// Google fonts
link(href='https://fonts.googleapis.com/css?family=Varela+Round' rel='stylesheet')
link(href='https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i' rel='stylesheet')
// Core theme CSS (includes Bootstrap)
link(href='stylesheets/styles.css' rel='stylesheet')
body
block content
I'm trying to figure out why is it not rendering properly when i go to:
localhost/users/1
lastly, I notice that when i go to the route
localhost/users
i got the expected result. BUT if I place a '/' in the end
localhost/users/
I'll will have the problem above. No CSS and it's not reading my static defined in app for my images: app.use(express.static(path.join(__dirname, 'public')));
I'm 2 weeks in learning node.js, I'm trying to learn PUG with it now.
Thank you all in advance.
Manage to get the answers for this from my colleague(Thanks to Kevin).
The cause of the issue is, I did not place a '/' in from of my link(href='stylesheets/styles.css' rel='stylesheet') at ./views/layout.pug. This cause the browser to assume the path is relative to the document.
note: This can be checked in the browser's network debugging tab.
When I'm in localhost:port/users, the relative path would be okay since the current URL doesn't have '/'. so the stylesheet would work in URLs
localhost:port/users
localhost:port/edit
and so on...
stylesheet's relative path would be:
localhost:port/stylesheets/styles.css (which is correct)
BUT when this encounters a '/' in the path. the relative path will change base on its current location's/URL's path.
In that case.
e.g
localhost:port/users/
localhost:port/users/1
localhost:port/edit/abc
...
Stylesheet would now be relative to these paths above or document path:
localhost:port/users/stylesheets/styles.css (which is NOT correct)
FIX
If we place '/' at start, the browser will look for that page relative to the root of the website (referred to as an absolute URL).
I also got ideas from this issue:
https://github.com/pugjs/pug/issues/2662
i need two defaultlayout for my project nodejs (point of sale), the first: for the authentication page and the registration of a new user (cashier) (with his own CSS code), the second for the dashboard (pos interface as well as the product addition page ...) (with its own CSS code too).
the structure of my code should be:
views/
layouts/
mainDashboard.hbs
mainLogin.hbs
dashboard.hbs
addProduct.hbs
login.hbs
register.hbs
My code in server.js (make juste one DefaultLayout):
const express = require("express");
const exphbs = require("express-handlebars");
const app = new express();
// view enginge
app.engine(
"handlebars",
exphbs({
defaultLayout: "mainlogin" ,
})
);
app.set("view engine", "handlebars");
Now i want to make two different layout with different CSS Code,
I find this post but I do not understand the solution (I specify that I am a beginner in node.js and that site is my first project So I need more detail please)
To explain what is happening in the post you need to know some basic things:
1) res.render is a express function which is used to render views(like .hbs, .ejs etc etc). Typically how you use render function is like this:
res.render('index.hbs')
Which returns some html and writes it to browser.
2) app.use is used to add middlewares(which is nothing but functions with 3 params) to the middleware chain.
app.use(middleware1);
app.use(middleware2);
For the above example every http request will go through middleware1 THEN middleware2 THEN the handler like app.get or app.post.
So basically a middleware is created to overwrite the res.render function
Now, to use the code shown there,
Make two folders inside views for two themes. For example,
views/
theme1/
index.hbs
theme2/
index.hbs
In the index.js file it should be normal express code then add the middlwares:
const express = require("express");
const app = express();
...
...
...
app.use(function(req, res, next) {
// cache original render
var _render = res.render;
res.render = function(view, options, done) {
// custom logic to determine which theme to render
var theme = getThemeFromRequest(req);
// ends up rendering /themes/theme1/index.hbs
_render.call(this, 'themes/' + theme + '/' + view, options, done);
};
next();
});
function getThemeFromRequest(req) {
// in your case you probably would get this from req.hostname or something
// but this example will render the file from theme2 if you add ?theme=2 to the url
if(req.query && req.query.theme) {
return 'theme' + req.query.theme;
}
// default to theme1
return 'theme1';
}
app.listen(8080, ()=>console.log("Started"));
Now let's say you make a route:
app.get('/', (req, res) =>{
res.render('index.hbs');
});
Now go to, http://localhost:8080/ it will render the theme1/index.hbs if you do http://localhost:8080/?theme=theme2 it will render the theme2/index.hbs.
Hope you understood the explanation.
I facing a problem that my Angularjs is not rendering or load in my Jade layout. Somehow the stylus is working perfectly with. I counldn't find out the reason why. I'm still the beginner in learing jade, stylus and angularjs
Below are my codes:
index.jade
!!! 5
html(ng-app='ng-app')
head
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js')
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-resource.min.js')
script(src='https://cdn.firebase.com/v0/firebase.js')
script(src='http://firebase.github.io/angularFire/angularFire.js')
script(type='text/javascript', src='angular.js')
link(rel='stylesheet', href='style.css')
body
.addressBook(ng-controller='addressBook')
h1 Address Book
table(width='710px', border='0', cellspacing='0', cellpadding='0')
tr.title(height='35px', align='left')
td(width='130') Name
td(width='180') Email
td(width='210') Address
td(width='80') Mobile
tr.details(ng-repeat='contact in contacts')
td {{contact.name}}
td {{contact.email}}
td(style='padding-bottom: 30px;') {{contact.address}}
td {{contact.mobile}}
angular.js
function addressBook($scope)
{
$scope.contacts =
[
{name:'Peter', email:'john_peter#asd.co', address:'No.123, Road 12/20, Street Army, 58200 KL, Malaysia', mobile:'601231231234' },
{name:'Lim', email:'Amy#asd.co', address:'54, 13/15, Happy Garden, 58200 KL, Malaysia', mobile:'60123473534' }
];
}
app.js
var jade = require('jade')
, express = require('express')
, http = require('http')
, app = express();
var stylus = require('stylus');
require('./angular.js');
app.configure(function(){
console.log('Configuring views....');
app.set('port', 1234);
app.set('views', './');
app.use(express.bodyParser());
app.use(express.static( __dirname + '/'));
app.set('view engine', 'jade');
});
app.get('/test', function(req,res){
res.render('index.jade');
});
server = http.createServer(app);
server.listen(app.get('port'), function(){
}).on('error', function(err) {
throw err;
});
thank you in advanced for everyone who helps
I suspect the issue you are having is that the path to your views that you have specified is wrong and you are serving them up statically.
For example, if you have your views in a sub-directory of the base directory, and you have set the base directory to be served up as static content, it will serve up the jade as static content.
What you should do is put your views in a different folder to the static content so that is a sibling not a child and this should work. If you want to post your directory structure I can have a look.
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?