I've recently started learning EJS and Express.
Here is my app.js file :
let app = express();
app.set('view engine', 'ejs');
app.get('/', (req, res) => {
res.render('index');
});
app.get('/fallinlovewith/:thing',(req,res)=>{
var name = req.params.thing;
res.render('love',{name:name});
});
app.listen(3000, () => console.log('Example app listening on port 3000!'));
And here are my index.ejs and love.ejs files :
index.ejs :
<h1>This is succesful !</h1>
love.ejs :
<h1>You fell in love with :</h1>
<p>This is from love.ejs folder</p>
My code is able to render index.ejs file but not love.ejs .
love.ejs shows the following text instead of the normal heading and paragraph.
This is what is being displayed at http://localhost:3000/fallinlovewith/dipti
I don't know what these "question mark" symbols denote.
I'm stuck here . Can someone help ?
Try specifying the language and the charset in the html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
...
Related
I am setting up a web server with exprss.js and socket.io. I set up a static folder so I can link my stylesheets without having to send every single file. But I am getting this error
Refused to apply style from 'http://localhost:3000/public/styles/index.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
this is my app.js file
const express = require("express");
const app = express();
var server = require('http').Server(app);
var io=require('socket.io')(server);
app.use(express.static('public'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/views/index.html');
});
io.on('connection', function(socket){
socket.emit('chat message', {hello: 'world'});
socket.on('chat message', function (data){
console.log(data);
});
});
server.listen(3000);
the index.html page looks like this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link type="text/css" rel="stylesheet" href="/public/styles/index.css">
</head>
<body>
<p>yo</p>
</body>
</html>
the file structure is the following
|-public
|-styles
-index.css
|-views
-index.html
-app.js
I think there is something wrong with my server setup
This is my first time using node
You get this error usually when there is no CSS file under that link.
When you use app.use(express.static('public')); directly express serves everything under root endpoint.
So you can use <link type="text/css" rel="stylesheet" href="/styles/index.css">.
If you would like to use /public/xxx.css you can use
app.use('public', express.static('public'));
When you use static, the original folder is not included in the path url, try something like this :
<link type="text/css" rel="stylesheet" href="/styles/index.css">
I'm working on a project in which I have a simple web server hosted with node.js (see code below) and I want to be able to dynamically load the code form html files and modify them each time someone makes a request. I've already putted some marker in my code ${likeThis} and I just need the code to put a string in the right place.
Here is my server code:
const express = require('express');
const app = express();
app.get('/', function (req, res) {
res.send('Hello World');
})
app.listen(8080);
});
And here is an example page in which I want to change the value ${sampleText} with the plain text "hello world!!!":
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
<title>Titler</title>
</head>
<body>
${sampleText}
</body>
Mind that there might be more of the same or different kind of value all over the html page.
On the user side I'd expect this:
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
<title>Titler</title>
</head>
<body>
Hello world!!!
</body>
There are several ways to use live data in pages returned from express. All of them utilize a "template" into which you inject "data". These include:
pug
mustache
handlebars
Another option would be to use NodeJS/ES6 template strings, such as:
const express = require('express')
const app = express()
// Text to insert into template
const sampleText = 'hello world!!!'
// Template to accept sampleText
const result = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Titler</title>
</head>
<body>
${sampleText}
</body>
</html>
`
app.get('/', function (req, res) {
res.send(result);
})
app.listen(8080);
Backticks ("`") are used to define template strings in Node where "${expression}" is used to insert any evaluable JavaScript expression into a template, like:
const result = `The contents of file ${filepath} are: ${fs.readFileSync(filepath).toString()}`
For more information, see Using Template Engines with Express
and for an exhaustive list of template engines that work "out of the box" with Express see Template Engines
i ll illustrate with Mustache, you need webpack for communication between front-side and web-server, but since webpack is headache i ll use mustache CDN.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="message"></div>
//we are gonna render the message into this div tag.
//this is a javascript code
//make sure script tags are at the bottom
<script id="message-template" type="text/html">
<div class="message">
{{message}} . //yes double curly brackets
</div>
</script>
//CDN link, Mustache pack files are stored here and we import from there
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.1/mustache.min.js"></script>
//for src add path of index.js in your app
<script src="./index.js"></script>
</body>
</html>
index.js
//select the div that you wanna place the message
const $message = document.querySelector("#messages");
//select the script tag in
const messageTemplate = document.querySelector("#message-template").innerHTML;
const html = Mustache.render(messageTemplate, {
//I hardcoded the message here, but as you learn, you will catch a dynamic data, put it here and display in your html page
message:"hello world",
});
$message.innerHTML(html);
After a bit of work(very flew actualy) i monaged to make this function that allows me to find the strings and replace them with the correct text, i will publish it hoping someone else in the future migth need it:
function substituteString(input, stringToChange, substitute) {
var n = 0;
while (true) {
n = input.indexOf(stringToChange, n);
if (n == -1) { break; } else {
input = input.replace(stringToChange ,substitute);
}
}
return input;
}
Easier than i was thinking
Working on frontend and backend using NodeJs for server side and ejs template for frontend. Came across a feature while using ejs scriplets to display data send from server while loading page.
Used <%console.log()%> over ejs, thought this log will be seen on inspect element logs, however got message over server terminal. How did this information is send over to server without any form submit or API call?
Server app.js:
/*jshint multistr: true, node: true, esversion: 6, undef: true, unused: true, varstmt: true*/
"use strict";
// NPM Modules
const express = require('express'),
path = require('path');
const app = express();
// Setup views directory, file type and public filder.
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.render('index', {message:'Welcome'});
});
const port = process.env.PORT || 3000;
console.log('server listening at http://127.0.0.1 over port: ', port);
app.listen(port);
EJS template index.ejs:
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<!-- All these CSS files are in plublic directory, as we had made all the content of public directory available for anyone from app.js -->
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="/css/app.css" />
<link rel="shortcut icon" href="logo.jpg" />
<title>Sign-Up/Login Form</title>
</head>
<body>
<%console.log(message)%>
<%=message%>
<%console.log("anything")%>
</body>
</html>
How can all the <%console.log()%> are send over server terminal and <%=message%> is displayed over browser. Even <%console.log("anything")%> is displayed over server terminal even though this has nothing to do with server. How ejs scriplets communicate with server and not browser?
Had anyone else tried this before or observed it.
Your question is about how ejs templates work. This is an answer for that question. I think you might also have something wonky going on with your express setup causing you problems.
EJS is a server-side rendering system. It's job is done before the html is sent to the client, so it has nothing to do with the browser.
The scriptlets inside <% %> run on the server to insert content into the template before sending to the client.
If you want to print something out on the browser console, don't put it in a scriptlet, just put it into a <script> tag, like this:
<script>
console.log("foo");
</script>
If you want the browser console to print something generated by the server, you could use ejs to put the value of message into what it generates:
<script>
console.log("<%=message%>");
</script>
The server will put the value of message into a console.log() statement that gets delivered to the browser.
This example prints "Wellcomes" to the browser console:
server:
const bodyParser = require('body-parser'),
express = require('express'),
path = require('path');
const app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.render('index', { message: 'Wellcomes' });
});
const port = process.env.PORT || 3000;
const listener = app.listen(port, function() {
console.log('platform listening on', listener.address().port);
});
index.ejs:
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Sign-Up/Login Form</title>
</head>
<body>
<script>
console.log("<%=message %>");
</script>
</body>
</html>
If you show page source in your browser, you should see:
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Sign-Up/Login Form</title>
</head>
<body>
<script>
console.log("Wellcomes");
</script>
</body>
</html>
I'm trying to learn express. I'm using FS to load my HTML Page. The only thing I could find on this with a google search was using ASP.NET instead of Express.
Server.js:
var express = require('express');
var path = require('path');
var fs = require('fs');
var app = express();
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname+'/')))
app.get('/', function(a,b,c){
fs.readFileSync('index.html');
});
app.post('/testaction', function(a,b){
console.log(a.body.log);
fs.readFileSync('Logged.html');
});
app.listen(3000);
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<form method="post" action="http://localhost:3000/testaction">
<h1>Log This:</h1>
<input type="text" name="log"/>
<input type="submit", value="Press Me!"/>
</form>
</body>
</html>
In order to serve files you don't have to use fs. Example:
app.get('/', function(req, res, next) {
res.render('index');
});
If you need to redirect, you can use:
res.redirect('/staticFile.html');
Remove these lines:
app.get('/', function(a,b,c){
fs.readFileSync('index.html');
});
This line is middleware and it applies to all routes on every request:
app.use(express.static(path.join(__dirname+'/')))
It's purpose is to serve static files from whatever path you provide. In this case you're serving from the root directory so you can navigate to all your code files like http://localhost:3000/package.json for example.
It applies to all HTTP methods, get post put etc...
When you write app.get('/' you override that middleware with a new route and try serving only one file. Just drop that code and you'll server everything statically from the directory you specified above.
If you don't want to serve your code files, put your static files in a different folder such as "site" and set your static path to that folder, for example:
app.use('/', express.static(__dirname + '/site'));
Whenever I try loading my AngularJS webpage (on a node js + express server) through http://localhost:3000, Internet Explorer just tries to download it with a random name and no file extension, instead of showing the actual page.
I can't even check the console for errors, because the download attempt seems to start before even trying to load it as a webpage.
The website works perfectly on both Firefox and Chrome. I am using Internet Explorer 11, so it's not even an old version.
I tried running my index through the W3 Validator, and the only errors it points out in the DOM are the Angular directives and tags (which are not really errors).
I tried changing the DOCTYPE from just a simple <!DOCTYPE html> to this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-loose.dtd">
And this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
... and this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
To no effect.
As suggested in other questions, I also tried serving my page as "text/plain" rather than "text/html" in my node server, but that didn't help either.
Here's the html for my index:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="it">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<!-- Angular Material CSS now available via Google CDN; version 1.0.7 used here -->
<link rel="stylesheet" href="./modules/angular-material/angular-material.min.css"/>
<link rel="stylesheet" href="./css/style.css"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"/>
<link rel="icon" href="icons/favicon.ico" type="image/x-icon"/>
<base href="/"/>
<title>Area Clienti</title>
<script src="./modules/angular/angular.js" type="text/javascript"></script>
<script src="./modules/ngstorage/ngStorage.js" type="text/javascript"></script>
<script src="./modules/angular-aria/angular-aria.min.js" type="text/javascript"></script>
<script src="./modules/angular-animate/angular-animate.min.js" type="text/javascript"></script>
<script src="./modules/angular-material/angular-material.min.js" type="text/javascript"></script>
<script src="./modules/angular-ui-router/release/angular-ui-router.min.js" type="text/javascript"></script>
<script src="./modules/ui-router-extras/release/modular/ct-ui-router-extras.core.min.js" type="text/javascript"></script>
<script src="./modules/ui-router-extras/release/modular/ct-ui-router-extras.dsr.min.js" type="text/javascript"></script>
<script src="./modules/ui-router-extras/release/modular/ct-ui-router-extras.sticky.min.js" type="text/javascript"></script>
<script src="./modules/pdfmake/build/pdfmake.min.js" type="text/javascript"></script>
<script src="./modules/pdfmake/build/vfs_fonts.js" type="text/javascript"></script>
<script src="./modules/angular-messages/angular-messages.min.js" type="text/javascript"></script>
<script src="http://ngmaterial.assets.s3.amazonaws.com/svg-assets-cache.js" type="text/javascript"></script>
<script src="./js/client.js" type="text/javascript"></script>
</head>
<body ng-app="App" ng-controller="AppCtrl" ng-view ui-view ng-cloak layout="row">
</body>
</html>
The script tags were in the body before, I tried putting them in the head to see if that would have helped, but it didn't.
What might be the issue here? And why is it so painful to make stuff work on IE?
EDIT: here's the server code.
var express = require("express");
var fs = require('fs');
var xml2js = require("./node_modules/xml2js");
var auth = require("./authenticator.js");
var bodyParser = require('body-parser');
var app=express();
//app.use(express.static('pages'));
var server = app.listen(3000, function(){
var host = server.address().address;
var port = server.address().port;
});
var jsonParser = bodyParser.json(); // to support JSON-encoded bodies
var urlencodedParser = bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
});
app.get('/', function(req, res){
sendFile(res, './index.html', getHeader('text/plain'));
});
app.use('/font/', express.static('./font/'));
app.use('/modules/', express.static('./node_modules/'));
app.use('/css/', express.static('./css/'));
app.use('/views/', express.static('./views/'));
app.use('/img/', express.static('./img/'));
app.use('/js/', express.static('./js/'));
function sendFile(res, path, header){
fs.readFile(path, function(err, content){
if(err) {
console.log("\nErrore caricando " + path + " - err: " + err);
//pageNotFound(res, "error");
}
else sendToClient(content, res, 200, header);
});
}
function getHeader(type){
return {"Content-Type": type};
}
function sendToClient(data, res, code, type){
res.writeHead(code, getHeader(type));
(type === "text/html" || type === "text") ? res.end(data, "utf-8") : res.end(data);
}
Plus a bunch of other POST and GET services which I think are not relevant
UPDATE: I managed to get it to say something in the developer console. This is the error:
(translation: impossible to open http://localhost:3000/)
It still tries to download the page.
UPDATE 2:
I managed to find out what the issue was: for some reason, the Content-Type header content was being interpreted as an object rather than the string it actually was, so IE couldn't render the page.
It now renders the index, but Angular-UI-Router doesn't seem to work.
It appears as though ui-router can't load sub states (it can switch between normal states though, since I was able to log in and be transferred to my dashboard page, which is a different state)
(Everything is still working perfectly fine on Chrome and Firefox)
Could it be sending you a file because you're using .sendFile():
app.get('/', function(req, res){
sendFile(res, './index.html', getHeader('text/plain'));
});
instead of using .render() to render the page?
app.get('/', function (req, res) {
res.render('index.html');
})
Try using Express's use() to always send via sendFile() the index.html after any HTTP action using the * wildcard. Make sure this goes after any other API REST routes or similar. This helps ensure that the Angular app within index.html is not constantly reloaded by other pages being rendered. This way any other API routes send/receive the data you need and only if nothing else is matched, will the index.html be loaded. Below is a structure that worked for me for an Express + Angular 2 application.
File Structure:
api
foo
foo.js
bar
bar.js
public
fonts
css
img
index.html
server.js
Server JS:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// fonts, css, images are stored in respective folders within folder "public"
app.use(express.static(path.join(__dirname, 'public')));
// some RESTful endpoints
app.use('/api/foo', fooRoutes);
app.use('/api/bar', barRoutes);
app.use('*', (req, res) => res.sendFile(path.join(__dirname, 'public', 'index.html')));
// error handling middleware
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});