express js not serving the static css files from router - css

I am actually facing this problem in another bigger project but, I have made a simple one so as to explain it easily
Tree Structure of my project is as follows
demo
|____admin
| |____admin.js
|____node_modules
|
|____static
| |____bootstrap.min.css
| |____headerStyle.min.css
|
|____views
| |____admin
| | |____admin_home.ejs
| |
| |____partials
| |____admin_header.ejs
|
|____index.js
|____package-lock.json
|____package.json
please bear with me, I am going to post the code of some of important files
code in 'index.js' is this
let express = require('express');
let app = express();
let path = require('path');
app.use(express.static(path.join(__dirname, 'static')));
app.set('view engine', 'ejs');
app.get('/',function(req,res)
{
res.render('./admin/admin_home');
});
let admin = require('./admin/admin.js');
app.use('/admin',admin);
app.listen(9000,function(){
console.log('listening to port : 9000');
});
Code in 'admin/admin.js' is this
let express = require('express');
let router = express.Router();
router.get('/',function(req,res)
{
res.render('./admin/admin_home');
});
router.get('/adminhome',function(req,res)
{
res.render('./admin/admin_home');
});
module.exports = router;
Code in 'views/admin/admin.ejs' is this
<%- include('../partials/admin_header.ejs') %>
<h1>Admin Home</h1>
I am having problem with express js static file serving.
For the following URL's the webpages are rendered with all the styles from css files
http://localhost:9000
http://localhost:9000/admin
they are served from these paths
http://localhost:9000/bootstrap.min.css
and
http://localhost:9000/headerStyle.css
but for the following URL webpages are rendered with plain html with out serving the css syles
http://localhost:9000/admin/adminhome
the error is
Failed to load the resources: the server responded with 404
css files are served from these paths
http://localhost:9000/admin/bootstrap.min.css
and
http://localhost:9000/admin/headerStyle.css
and the 'Link' tags in 'vies/partials/admin_header.ejs' are as follows
<link rel="stylesheet" type="text/css" href="bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="headerStyle.css">
versions of the modules are as follows
ejs:^2.5.7
express:^4.16.2
path:^0.12.7
my nodejs version is
v8.5.0
Please help me in finding the solution for this problem. Thank You

as quoted by Roland Starke, the hrefs of the styles were relative to the url I was visiting. I can make them absolute just by adding a ' / ' like
href="/bootstrap.min.css"

You should add a line to index.js
app.set('views', path.join(__dirname, 'views'));

Related

Getting my CSS modules to work on my Express app

I've been using CSS just fine on one file for some time now with my current project, but it's gotten very long and harder to manage. So now I'm looking to put my CSS into modules to make editing easier. I've never done this on an Express app, only Wordpress. I've tried to use postcss like I do with Wordpress, but it does not seem to be working at all, and I'm not really understanding the npm documents for express.
Any help would be lovely.
My app.js file
var express = require("express"),
app = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var fs = require('fs');
var postcss = require('postcss');
var atImport = require('postcss-import');
//Post CSS congig
var css = fs.readFileSync("/Users/myname/Desktop/Lookalike/public/stylesheets/style.css", "utf8");
postcss()
.use(atImport())
.process(css, {
from: "public/stylesheets/style.css"
})
.then(function (result) {
var output = result.css
console.log(output)
})
//Mongoose config
mongoose.connect("mongodb://localhost:27017/lookalike", {
useNewUrlParser: true
});
//Body parser config
app.use(bodyParser.urlencoded({
extended: true
}));
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
//Routes
var homeRoute = require("./routes/home");
//Require routes from other files
app.use("/", homeRoute);
app.listen(process.env.PORT || 3000, process.env.IP, function () {
console.log("Lookalike server has started");
});
The head of my header file
<!DOCTYPE html>
<html>
<head>
<title>Lookalike</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
<link rel ="stylesheet" href="/stylesheets/style.css">
</head>
My CSS module file
#import "/modules/front-page";
#import "/modules/discography";
#import "/modules/follow";
#import "/modules/store";
#import "/base/baseline";
My file config looks something like this
/public
/images
/stylesheets
/base
/baseline.css
/modules
/fontpage.css
/discography.css
/follow.css
/store.css
All you're missing in your postcss is not writing output to your destination. Following the docs it's simple.
Note that you should either name your input css and output css differently or put them in different folders (preferred)
postcss()
.use(atImport())
.process(css, {
from: "public/stylesheets/style.css"
})
.then(function (result) {
var output = result.css
console.log(output)
fs.writeFileSync("/Users/myname/Desktop/Lookalike/public/stylesheets/finalstyle.css", result.css) // <-- need a different name to differentiate input css and the output from postcss
if ( result.map ) {
fs.writeFileSync('/Users/myname/Desktop/Lookalike/public/stylesheets/finalstyle.css.map', result.map)
}
});
You could use the async version of fs.writeFileSync. I used sync version to be in sync with the code in you've posted.

Webpack-React with server-side-rendering: linking to css file in server template with hash name

I'm preparing a starter for react from scratch, here is the code: https://github.com/antondc/react-starter
I managed to set up bundling for client and server, with css modules and less, and now I'm with server side rendering. I'm doing that with a js template:
// src/server/views/index.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>INDEX.EJS</title>
<link rel="stylesheet" type="text/css" href="assets/index.css">
</head>
<body>
<div id="app"></div>
<script src="/assets/bundle.js"></script>
</body>
</html>
As you see, the link to the css file is harcoded there. But in my Webpack configuration I have this file name hashed, because I want to prevent caching from browsers when I update the code on development.
I am wondering how can I link the css file there. Now in the template I have href="assets/index.css, but the css file is in /dist/assets/d47e.css.
It would be great if would be possible to do something like href="assets/*.css, but is not possible, so what is the common approach for a problem like this one?
Thanks!
It depends.
Step 1: Get the current asset name
To get the current name of the generated webpack css/js files, you can use the assets-webpack-plugin. This will (with default config) generate an assets.json file in your output folder with essentially this structure:
{
"bundle_name": {
"asset_kind": "/public/path/to/asset"
}
}
Step 2a: Your html is rendered from a template (pug/jade/what ever)
// in your render code
const assets = require('<webpack-output-folder>/assets.json');
// ...
res.render('template', {
scripts: [{src: `${WEBPACK_PUBLIC_PATH}/${assets.myEntryPointName.js}` }],
links: [{href: `${WEBPACK_PUBLIC_PATH}/${assets.myEntryPointName.css}` rel: 'stylesheet' }],
});
// in your template (example for pug)
// ...
each link in links
link(rel=link.rel href=link.href)
// ...
each script in scripts
script(src=script.src)
// ...
Step 2b: Your html is static
You need to update the html (using a script) with the information from the asset.json file. This script needs to be run after webpack. Something like
const assets = require('<webpack-output-folder>/assets.json');
const fs = require('fs');
const css = /assets\/[a-z0-9]*\.css/i;
const js = /assets\/[a-z0-9]*\.js/i;
fs.readFile('<yourhtml>.html', (err, data) => {
// ... (error handling)
const updatedCss = data.replace(css, assets.myEntryPointName.css);
const updatedJs = updatedCss.replace(js, assets.myEntryPointName.js);
fs.writeFile('<yourhtml>.html', updated, (err) => {
// ... (error handling)
});
});
You can use HTMLWebpackPlugin to generate an HTML file that will have your JS and CSS output inserted.

add static css file with express.js

I have a .css file generated with koala from a .scss file and I added it in my index.html. The page won't serve my file and I learned that its due to me not adding the file on my express server as static. I tried to follow the different options listed on the express server documentation http://expressjs.com/es/starter/static-files.html:
1)
app.use(express.static('public'));
as I used:
app.use(express.static('styles/css'));
2)
app.use('/static', express.static('public'));
as I used:
app.use('/static', express.static('styles/css'));
3)
app.use('/static', express.static(__dirname + 'public'));
as I used:
app.use('/static', express.static(__dirname + '/styles/css'));
But non is working I tried different combinations and i must have been doing something wrong.
This is my folder path:
project
src
styles
bower_components
css
app.css
sass
app.sass
app.js
index.html
package.json
server.js
webpack.config.js
This is my express server.js file:
const path = require('path');
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const config = require('./webpack.config');
const app = express();
const compiler = webpack(config);
const middleware = webpackDevMiddleware(compiler, {
noInfo: true,
publicPath: config.output.publicPath,
stats: { colors: true },
});
app.use(middleware);
app.use(webpackHotMiddleware(compiler));
app.get('*', (req, res) => {
const renderHtml = () => middleware.fileSystem
.readFileSync(path.join(compiler.outputPath, 'index.html'))
.toString();
res.send(renderHtml());
});
app.use('/static', express.static(path.join(__dirname, '/styles/css')))
app.listen(3000, '0.0.0.0', function (err) {
if (err) {
console.log(err);
return;
}
console.log('Listening at http://0.0.0.0:3000');
});
I need to know in this particular example how should I use the express static line to make it work. What I'm doing wrong? Thank you in advance for any help.
My first guess would be that your app.get('*' ...) is the culprit. Since you use the wildcard * it matches every possible URL.
And since you put app.use('/static', ...) after that, I think it's gonna be ignored.
My two cents:
Try putting app.static(...) before app.get('*', ...).
If you use app.static('/static', express.static(path.join(__dirname, '/styles/css'))) then in your HTML your <link> tag should look like: <link rel='stylesheet' href='/static/your-css-file.css' type='text/css'>
Otherwise simply use app.use(express.static(__dirname)) and in your HTML you should have <link rel='stylesheet' href='/styles/css/your-css-file.css' type='text/css'>
Overall, keep in mind that the order in which you declare your middlewares with app.use(...) matters.

Node.JS with Express and SASS - Compiled CSS file not applied

I'm new to NodeJS and I'm using Express to serve my pug files/view. Furthermore I'm using "express-sass-middleware" to compile and serve the scss/css files. Everything works very well but unfortunately, the CSS are not applied.
My app.js files looks like:
var express = require('express');
var sassMiddleware = require('express-sass-middleware');
var app = express();
app.set('view engine', 'pug');
app.get('/css/bootstrap.css', sassMiddleware({
file: 'css/bootstrap.scss', // the location of the entry point,
// this can also be a directory
precompile: true, // should it be compiled on server start
// or deferred to the first request
// - defaults to false
}));
app.get('/', function (req, res) {
res.render('index', {
varTitle: 'Hello World'
});
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
And my simple css file looks like:
// $icon-font-path: /3rdparty/fonts;
// #import 'bootstrap/bootstrap';
// #import './node_modules/bootstrap-sass/assets/stylesheets/bootstrap/variables';
body
{
background-color: green;
font-size: 100px;
}
My index.pug file is:
doctype html
html(lang='en')
head
title= varTitle
link(ref='stylesheet' type='text/css' href='/css/bootstrap.css')
body
h1= varTitle
Now, when I start my webserver using "node app.js", accessing http://localhost:3000, I see "Hello World" but unfortunately the body background isn't green and the text is also not 100px. That means that the css file is not applied. But when I access http://localhost:3000/css/bootstrap.css, I see the valid, css file.
Anyone know what I'm missing here? I'm a bit confused that I see the CSS source when accessing it directly but the browser doesn't apply the css styling. I already tried different browsers without any success. None of them applying the css file.
You have typing error in index.pug file for loading css file. You had mentioned ref whereas it should be rel.
link(rel='stylesheet' type='text/css' href='/css/bootstrap.css')
Happy to help you.
you don't seem to be serving the static files from your nodejs server code. You have to add your css dir in order to allow access from your html code:
app.use('/static', express.static('public'))
Now, you can load the files that are in the public directory from the /static path prefix.
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html

node.js - can't load css when param express.js too long

I'm writting a application by Node.js,express.js,ejs....
I'm using this code to use ejs and load css:
app.engine('.html', require('ejs').__express);
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
app.use(express.static(__dirname + '/views'));
This is my dir struct
myapp
--Controller
----admin.js
--db
----db.js
--views
----admin
------user.html
------addUser.html
----css
------style.css
--app.js
Html load css like this
<link href="../css/style.css" rel="stylesheet">
And i had used css for my web. when i use params :
app.get('/admin/users', admin.users);
app.get('/admin/add', admin.add);
url are:
loocalhost:1080/admin/users
loocalhost:1080/admin/add
then my css active. but when i use param:
app.get('/admin/users/add', admin.add);
url is:
loocalhost:1080/admin/users/add
then my css not active.
so how to fix it??
Please help.
Avoid making your CSS links relative. So specify them like so:
<link href="/css/style.css" rel="stylesheet">

Resources