images not rendering in production - node.js

I have deployed my node.js express app to production via a docker file, however, the images are not being rendered, and browser standard placeholder images are being rendered in-place of these.
In order for my app to render these images, is there something I am doing wrong? Is there a piece of code I need to include?
My file structure is as follows
base directory > public > icons
base directory > index.js
Relevant portion of my index.js server file
const { join } = require("path");
app.set('views', join(__dirname, 'views'));
app.use(express.static(join(__dirname, 'public')));
const port = 3000
var cookieParser = require('cookie-parser')
app.use(cookieParser())
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }))
app.use(cookieParser());
process.env.NODE_ENV === 'production'
app.set('view engine', 'ejs');
app.get('/',(req,res)=>{
res.render('index',{
data: 'name'
})
})
Here is the error message I get when I try to open the image file
ejs file:
<% data.countries.forEach(function(count){ %>
<div class="flex">
<div class="template">
<div class=“Country>
<img class="img" src="/icons/<%= count.icon %> " width="25" height="25" /> <%= count.name %>
</div>
<div class ="Category">
<%= count.categories.map(cat=>cat.name).join(' | ') %>
</div>
</div>
</div>
<% }); %>

Can you open the file directly by his path?

One possible answer is because inside your EJS file, your image is pointing at a URL that looks something like /icons/HK.png, but your ExpressJS public path is set to /public indeated here:
app.use(express.static(join(__dirname, 'public')));
So one possible solutions is to add a new public path for your icons set by adding this code:
app.use('/icons', express.static(join(__dirname, '/public/icons')))

Related

Node-Express error: No default engine was specified and no extension was provided

I've just started learning Node.js and i'm trying to create a web application that returns the form in users.ejs when http://localhost:8083 is entered. What is going wrong here?
./index.js
var express = require("express");
var mysql=require("mysql");
var app = express();
var usersRouter=require('./routes/users');
app.use("/",usersRouter);
var server = app.listen(8083, function(){
var port = server.address().port;
console.log("Server started at http://localhost:%s", port);
});
./routes/users.js
var express=require("express");
var router=express.Router();
router.get('/',function(req,res){
res.render("./views/users");
})
module.exports = router;
./views/users.ejs
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="user-detail">
<h2>Create User Data</h2>
<form action="/users/create" method="POST">
<label>Full Name</label>
<input type="text" placeholder="Enter Full Name" name="fullName" required>
<label>Email Address</label>
<input type="email" placeholder="Enter Email Address" name="emailAddress" required>
<label>City</label>
<input type="city" placeholder="Enter Full City" name="city" required>
<label>Country</label>
<input type="text" placeholder="Enter Full Country" name="country" required>
<button type="submit">Submit</button>
</div>
</div>
</body>
</html>
The view engine for rendering the template file is not configured.
You need to setup the view engine on the app level via app.set method, by setting view engine to ejs :
view engine
String The default engine extension to use when omitted. NOTE:
Sub-apps will inherit the value of this setting.
https://expressjs.com/en/5x/api.html#app.settings.table
so in index.js add this:
app.set('view engine', 'ejs');
also, you need to install ejs
npm i -S ejs
and include it, so your index.js file should look like this
var ejs = require('ejs');
app.set("view engine", "ejs");
Now the view engine is set, but your users router will fail with this error:
Error: Failed to lookup view "./vies/users" in views directory
It's this method here:
res.render("./views/users");
It's now trying to load users template from views/views, i.e. there's an extra view. It's coming from yet another app setting - views, a directory to store and read view templates:
views
String or Array A directory or an array of directories for the
application's views. If an array, the views are looked up in the order
they occur in the array
Default: process.cwd() + '/views'
https://expressjs.com/en/5x/api.html#app.settings.table
It's configured by setting the views path on the app level, like so:
app.set('views', path.join(__dirname, 'views'));
And as you can see, it's already set to process.cwd() + '/views' by default, so it's optional, which means that's where that extra view is coming from, so you just need to remove views/ in the users router, so it'll pick it up from the root by default:
res.render("./users");
Final code:
./index.js
var express = require("express");
var app = express();
// load ejs template renderer
var ejs = require("ejs");
// register the given template engine
app.set("view engine', 'ejs");
// optional, as it defaults to process.cwd() + '/views'
// needs path too:
// var path = require("path");
//app.set("views", path.join(__dirname, "views"));
var usersRouter = require("./routes/users");
app.use("/", usersRouter);
var server = app.listen(8083, function() {
var port = server.address().port;
console.log("Server started at http://localhost:%s", port);
});
./routes/users.js
var express=require("express");
var router=express.Router();
router.get('/',function(req,res){
res.render("./users");
})
module.exports = router;
Check Express guide and examples here:
https://expressjs.com/en/starter/examples.html

ejs includes header but in some page don't load image

Folder list
Hi, I'm new to node, express and ejs; this is a folder list of my project and for some reason when I include the header and footer on home.ejs, I can see the image on the navbar, but if I do the same in terms-condition.ejs, node load the page correctly with the footer and the navbar, but the logo-image isn't shown in the page.
The only difference between home.ejs and terms-condition.ejs is that the last one is in a subfolder of /views.
index.ejs
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
app.get("/", function(req, res) {
res.render("home");
});
app.get("/legal/terms-condition", function(req, res) {
res.render("legal/terms-condition");
});
app.listen(3000, function(){
console.log("Server started on port 3000.");
});
home.ejs
<%- include("common/header") -%>
<div class="box">
Terms and Condition
</div>
<%- include("common/footer") -%>
terms-condition.ejs
<%- include("../common/header") -%>
<div class="container">
<div class="row">
<div class="col-6">
<h1>This is a sample</h1>
</div>
<div class="col-6">
<p>Why ejs not load the logo in the navbar?</p>
</div>
</div>
</div>
<%- include("../common/footer") -%>
here the link to my project on GitHub
You need to prefix the images/Stack_Overflow_icon.svg with / i.g. /images/Stack_Overflow_icon.svg. In your code, did you notice that the styles.css loading correctly because you've prefix it with /.
You're facing this issue because the file terms-condition.ejs is within a folder whereas home.ejs not.
P.S. You should always put node_modules in .gitignore file.

how to create a dynamic webpage using node js?

I am new to node js. i am trying to learn node js. My question is how can we create dynamic webpages using node js?
PHP
<html>
<body>
<?php .......... ?>
</body>
Like in php we can do this way. How can we do in node js.
First off you would start by installing the nodejs framework expressJS
sudo npm install express
For instance, let's say you want to create a form.
<html>
<body>
<head>
This is a simple form
</head>
<body>
<form action="/" method="POST">
<label for="firstName">First Name:</label>
<input name="firstName">
<br>
<label for="lastName">Last Name:</label>
<input name="lastName">
<br>
<button type="submit">send</button>
This what the server side part would look like
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var urlencodedParser = bodyParser.urlencoded({ extended: false});
// Set EJS View Engine**
app.set('view engine','ejs');
// Set HTML engine**
app.engine('html', require('ejs').renderFile);
//set directory
app.set('views', __dirname + '/views');
//static folder
app.use(express.static('staticfolder'));
app.get('/form', function(req, res) {
//open form.html from the views directory
res.render('form');
});
app.post('/', urlencodedParser, function(req, res) {
//retrieve first and lastname
var firstName = req.body.firstName;
var lastName = req.body.lastName;
//open submitted.html after the user has submitted the form
res.render('submitted', {output: req.body.firstName});
});
app.listen(3000);
Page that will be displayed when user submits the form. It is called submitted.html in this case
<html>
<body>
<p> you have submitted the form </p>
<!--firstname entered by user-->
<p> your first name is <%= output %></p>
</body>
</html>
You need a template to dynamically change its content.
Step 1: Create a server with Express Node.JS Framework.
Step 2: Use EJS(Embedded JavaScript) to create a template.
Follow the instructions bellow:
https://shockoe.com/ideas/development/creating-dynamic-web-pages-ejs/

Issue with partials using EJS in express

Just to preface: I've recently been transitioning my web development skills from PHP + HTML/CSS to Nodejs, but have been having trouble with templating.
I'm using Express, and after some research tried to use Pug.js, but found that too complicated for what I'm trying to achieve at the moment, so I moved to ejs as it seemed to be more simple.
What I'm trying to get is to be able to reuse HTML that I have already written for multiple pages on the site - which from what I've found is called 'partials'?
Now to the code I've written so far:
server.js:
var express = require('express');
app = express();
publicFolder = __dirname + '/public';
app.set('view engine', 'ejs');
app.use(express.static(publicFolder, {
extensions: ['html']
}));
app.listen(80, () => {
console.log('Server is online on port 80')
});
index.html: (/public/index.html)
<html>
<body>
<% include ../views/header.ejs %>
</body>
</html>
header.ejs: (/views/header.ejs)
<h1>Test header</h1>
I understand I may be on the completely wrong track, but any help would be greatly appreciated.
Regards
EDIT: I've double checked to make sure it's not a path issue
It might be easier for you to store all your view files as ejs in the same folder and user the path module to set your static files.
server.js:
var express = require('express');
var path = require('path')
app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')
app.listen(80, () => {
console.log('Server is online on port 80')
});
index.ejs
<html>
<body>
<% include header %>
</body>
</html>
Just a consideration. Hope it helps!

Express not seving static images from view/subfolders

I have a problem where my static images work perfectly when linked from /views folder and from /views/partials folder, but when I put a subfolder between /views/courses/partials my image stops working.
I am using
app.use(express.static(__dirname + "/public"));
My file structure:
> app
- app.js
> public
> assets
> images
> icons
- link.png
> views
- landing.ejs
> partials
- header.ejs
> courses
- courses.ejs (images is working when linked from here)
> partials
- lectures.ejs //This file is a partial of courses.ejs (images not working when linked from here)
The path I use is /assets/images/icons/link.png
Here is my app.js if needed
//REQUIREMENTS - requiering files for App.js
var express = require("express"),
app = express(),
passport = require("passport"),
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
flash = require("connect-flash"),
passportSetup = require("./config/passport"),
methodOverride = require("method-override"),
User = require("./models/user"),
Course = require("./models/course"),
middleware = require("./middleware"),
path = require("path");
//REQUIERING ROUTES - requiering routes files
var indexRoutes = require("./routes/index");
var authRoutes = require("./routes/auth");
var adminRoutes = require("./routes/admin");
var messageRoutes = require("./routes/message");
var courseRoutes = require("./routes/courses");
// DATABASE CONNECTION - conecting to mongoDB using enviroment variables
var dbUrl = "mongodb://localhost/example" || process.env.DATABASEURL;
mongoose.connect(dbUrl);
//METHOD OVERRIDE - override http method
app.use(methodOverride("_method"));
//FLASH MESSAGES - use flash messages
app.use(flash());
//BODY PARSER - using bodyparser to easily retrieve http info
app.use(bodyParser.urlencoded({extended: true}));
//STATIC DIRECTORIES - use static directories for clientside linking
app.use(express.static(__dirname + "/public"));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//VIEW ENGINE - default view engine
app.set("view engine", "ejs");
//PASSPORT CONFIGURATION - setting express session secret
app.use(require("express-session")({
secret: "************************",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
//CURRENT USER - sending current user to every route
app.use(function(req, res, next){
res.locals.currentUser = req.user;
next();
});
//ROUTES - all routes are used here
app.use(authRoutes);
app.use(adminRoutes);
app.use(messageRoutes);
app.use(courseRoutes);
app.use(indexRoutes);
//LISTENING PORT - port to listen to
var port = 4000 || process.env.PORT;
//LISTEN - listen on chosen port
app.listen(port, process.env.IP,function(){
//Startup message
console.log("Server has started!");
});
And here is my lectures.ejs file:
<div id="lectures-content" class="page-section--small">
<div class="wrapper--no-padding course-lectures">
<div class="course-lectures__lecture flex">
<div class="course-lectures__left">
<div class="text-area">
<div class="text-area__smallheading">Lecture 1</div>
<div class="text-area__text text-area__text--small">This is the first lecture</div>
</div>
</div>
<div class="course-lectures__right flex">
<div class="course-lectures__number">Lecture: 1</div>
<div class="course-lectures__arrow">
<img class="course-lectures__image" src="/assets/images/icons/link.jpg" alt="">
^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
</div>
</div>
</div>
</div>
</div>
I think there's a mismatch in the filetype of you picture:
link.jpg != link.png
Try this: It may help you
app.use(express.static('./public'));
Make sure that your app.js must be in the same directory,

Resources