Express only serving css file in main page - node.js

I am learning node and using expressjs the problem is that the css file is only working on the main page and not any other page following is the code for the app:
var express = require("express");
var app = express();
// assets
app.use(express.static("public"));
// simple file testing
app.get("/anything/:stuff", function(req, res){
var stuff = req.params.stuff;
res.render("love.ejs", {stuff: stuff});
});
// posts page
var books = [
{title:"Harry Potter",author:"JK Rowling",editions:7},
{title:"Peere Kamil",author:"Humaira Saeed",editions:4},
{title:"Mushaf",author:"Abdullah khan",editions:2}
];
app.get("/books", function(req, res){
res.render("books.ejs",{books:books});
});
app.listen(3000, process.env.IP, function(){
console.log("Serving Now!");
});
The following is the code for the page where it is not working.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="app.css" />
<title>demo app</title>
</head>
<body>
<h1>You fell in love with : <%= stuff %> </h1>
<%
if(stuff.toUpperCase() === "WAQAS"){ %>
<P>GOOD CHOICE HE IS THE BEST</p>
<% } %>
<p>P.S This is the love.ejs file</p>
</body>
</html>
The file is under public directory.

Use an absolute URL for the CSS file, so the browser doesn't look for it relative to the current URL:
<link rel="stylesheet" href="/app.css" />
Explanation: say that you open the URL /anything/helloworld in your browser. When your HTML contains just app.css, without the leading slash in front of it, the browser will try and load /anything/app.css (because without that slash it's relative to the current URL), which doesn't point to your CSS file.
When you add the leading slash, express.static will be able to find the CSS file in public/.

Related

Why res.send( string ) download a file

I have an app where I want to render static html with express.
I know about res.sendFile() but that is not what I want to use. I want to load my files using fs and send them using res.send()
I do something like this :
fileFoo = fs.readFileSync('./html/foo.html', 'utf-8');
fileBar = fs.readFileSync('./html/bar.html', 'utf-8');
app = express()
app.get('/foo', (req, res) => res.send(fileFoo));
app.get('/foo/bar', (req, res) => res.send(fileBar));
With 2 very simple html files
foo.html
<html>
<head>
<title>FOO</title>
</head>
<body>
<h1>FOO</h1>
bar
</body>
</html>
bar.html
<html>
<head>
<title>BAR</title>
</head>
<body>
<h1>BAR</h1>
</body>
</html>
When I go to /foo I got a HTML rendered.
If I click on bar I do not get a new HTML page rendered but I got a file "bar" with no extension downloaded. The file of course content the HTML page.
What is happening ?
UPDATE :
I am actually using a router, not direct app.
And I think this 'download' occure only when I try to reach
router.get('/', (res, req) => res.send(fileBar));

Node.js jsdom set document root

I am trying to load local javascripts with jsdom.
Now I am wondering how I can make jsdom loading the javascripts from "__dirname/../public".
Can someone help me?
My current code is:
var fs = require('fs');
var jsdom = require('jsdom');
jsdom.defaultDocumentFeatures = {
FetchExternalResources: ["script"],
ProcessExternalResources: ["script"],
MutationEvents : '2.0',
QuerySelector : false
};
exports.test = function(req, res) {
var html = fs.readFileSync(__dirname+'/../public/html/lame.html');
var document = jsdom.jsdom(html, null, {documentRoot: __dirname+'/../public/'});
var window = document.createWindow();
window.addEventListener('load', function () {
//window.$('script').remove();
//window.$('[id]').removeAttr('id');
res.send(window.document.innerHTML);
window.close();
});
}
The simple HTML page is:
<html>
<head>
<title id="title">bum</title>
<script type="text/javascript" src="/javascripts/jquery.min.js"></script>
<script type="text/javascript" src="/javascripts/stuff.js"></script>
</head>
<body>
<h1>hello world</h1>
<h2 id="bam">XXX</h2>
</body>
</html>
I've run into the same issue and got it to work. Try these, in order:
documentRoot is not documented. The option which is documented is url. So replace documentRoot with url.
If the above is not enough, then add a base element. I've set my templates like this:
<head>
<base href="#BASE#"></base>
<!-- ... -->
</head>
where #BASE# is replaced with the same value as the one passed to url.
The solutions above are extracted from actual code in use in a test suite.

Can someone explain why this code is working?

So i am using marked (a markdown module) with express, i am not setting the title var or rendering anything and yet the title var is being mutated -i guess- here is the code to my index.js route :
/*
* GET home page.
*/
exports.index = function(req, res, marked){
marked('Why is this even __working__?.');
};
and here is the code to my index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
</body>
</html>
and here is what i am getting in the browser, although i restarted the app so many times!!:
You have misunderstood the connect/express middleware function signature. You have:
exports.index = function(req, res, marked){
But that's not right. It's req, res, next and there's no marked involved. So you aren't rendering markdown, you're passing a string to next() which connect/express treat as an error. Your code does this once you remove the misnamed function parameter confusion:
exports.index = function(req, res, next){
next('Why is this even __working__?.');
}
So connect sees next was passed an error string and express render's the default error page with that as the error message.

Express & EJS - layout.ejs not used

Im trying out EJS as a view engine with Express. It seems that my layout.ejs is not used. I have two views index.ejs and layout.ejs both in my 'views' folder. It seems that index.js is rendered but layout.ejs is not. The layout.ejs file should be including a CSS file but when the page is rendered in the browser this is not there. Any test test text that I place in the layout.ejs file is not output with the response.
Am I missing an additional configuration step?
Thanks!
My server.js code:
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
res.render('index.ejs', {title: 'EJS Engine'});
});
app.listen(8080);
In my layout.ejs I am linking to a single css file which resides in the public folder.
layout.ejs:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<%- body %>
</body>
</html>
index.ejs
<div id="container">
index.html
</div>
Here's the module you need:
https://www.npmjs.org/package/express-ejs-layouts
Do the following:
npm install express-ejs-layouts // install the layout module from the command line
var express = require("express")
,path = require('path')
,fs = require('fs')
,expressLayouts=require("express-ejs-layouts") // add this requirement
, app = express();
app.use(express.bodyParser());
app.use(expressLayouts); // add this use()
app.use(express.static(__dirname));
Now the ejs engine should use your layout.
app.set('view options', { layout:'layout.ejs' });
Place layout.ejs into your views folder.
Alternately you can place layout.ejs into views/layouts folder and then use
app.set('view options', { layout:'layouts/layout.ejs' });
I have a similar issue. In my case I would rather use Jade but I have a requirement for a more "html" style template engine for a particular project. At first I considered express-partials or ejs-locals (as mentioned in a comment by Jonathan Lonowski) or even using html via the pipe or dot syntax within Jade templates (see here for more information about that option and this SO post). I am not able to introduce the additional dependencies for express-partials and ejs-locals into this project. These two projects do look good and might meet your needs.
If you do not want to use these projects, you can do something like the following:
views/layout-head.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The title</title>
</head>
<body>
views/layout-foot.ejs
</body>
</html>
views/index.ejs (or any other page)
<% include layout-head %>
This is the index page - <%= title %>
<% include layout-foot %>
routes/index.js
exports.index = function(req, res){
res.render('index', { title: 'Express' });
}
This is not an optimal solution but it works. Most of my application will be a single page app and I have some other restrictions I have to work within so this works for my needs. This may not the best solution in many cases - especially if you have complex and/or changing layouts.

Can't get stylesheet to work with ejs for node.js

I'm trying to make a simple server with node, express and ejs for the template. I've gotten the server to point to the page, load it, and am even able to generate other bits of code with the include statement. However for some reason the style sheet will not load.
app.js
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
fs = require('fs');
var PORT = 8080;
app.set('view engine', 'ejs');
app.get('/', function(req, res){
res.render('board.ejs', {
title: "anything I want",
taco: "hello world",
something: "foo bar",
layout: false
});
});
app.listen(PORT);
console.log("Server working");
The ejs file is in a directory views/board.ejs
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='../styles/style.css' />
</head>
<body >
<h1> <%= taco %> </h1>
<p> <%= something %> </p>
</body>
</html>
and style.css is in a styles/style.css directory relative to app.js
p {
color:red;
}
I've tried every path that I can conceive of for the href of the link including relative to where my localhost points relative to app.js relative to board.ejs and even just style.css but none seem to work. Any suggestions are greatly appreciated.
Declare a static directory:
app.use(express.static(__dirname + '/public'));
<link rel='stylesheet' href='/style.css' />
in app.js:
you must first declare static directory
app.use("/styles",express.static(__dirname + "/styles"));
in ejs file :
<link rel='stylesheet' href='/styles/style.css' />
Recently I was working with this same thing and my CSS was not working. Finally, I get the trick. My static path was like below,
const app = express();
const publicDirectoryPath = path.join(__dirname, '../src/public');
const staticDirectory = express.static(publicDirectoryPath);
app.use(staticDirectory);
and my folder structure was like
The trick is that express access only defined static path, in my case CSS was outside of public so it was not working and suddenly I move CSS folder inside my public folder and that's it. Works beautifully.
Above example was for only one static path. For multiple static path you can use the code in the below
const app = express();
const publicDirectoryPath = path.join(__dirname, '../src/public');
const cssDirectoryPath = path.join(__dirname, '../src/css');
const staticDirectory = express.static(publicDirectoryPath);
const cssDirectory = express.static(cssDirectoryPath);
app.use(staticDirectory);
app.use('/css/',cssDirectory);
And my generic HTML file is
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index</title>
<link rel="stylesheet" href="../css/styles.css">
</head>
<body>
<h1>this is index page</h1>
</body>
</html>
To set the entry point for your application dependancies like css, img etc add below line into your server.js (or which ever being used).
app.use(express.static(__dirname + '/'))
This tells to get css files from current directory where server.js is present. Accordingly you can define relative path of css in html file.
With Express 4, you can easily set this up by using the following within your app.js file.
app.use('/static', express.static(path.join(__dirname,'pub')));
Place this early in your file, after you created your require constants, and declared your express app.
Its declaring a static directory, with the help of the path object, allowing you to have a place where all of your front-end resources are available. It's also giving it a virtual directory name (/static) that can be used on the front of the site, instead of the physical name you see within your project (/pub).
In your template you can do something like this in your head
<link rel="stylesheet" href="/static/css_bundle.css"/>

Resources