How to include css files for api routers in express? - node.js

I am using express and handlebars. The problem is the pages which have urls like http://localhost:5000/api/posts does not include css files. However, routers like http://localhost:5000 or http://localhost:5000/register work completely fine.
directories
app
-server.js
-routes
-api
-posts.js
-public
-css
-images
-views
-layout
-main.handlebars
-posts.handlebars
in server.js . (only important part)
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => res.render('index'));
app.get('/register', (req, res) => res.render('register'));
app.use('/api/posts', require('./routes/api/posts'));
Since I did include app.use(express.static(path.join(__dirname, 'public'))); in server.js, I thought there should not be any problem with the static files.
However, in main.handlebars <link rel="stylesheet" href="css/main.css"> does not work. On the other hand, <link rel="stylesheet" href="../css/main.css"> did work.
Moreover, it also worked if I changed the app.use('/api/posts', require('./routes/api/posts')); to app.use('/posts', require('./routes/api/posts')); Are there any other ways to solve this problem if I don't want to change the routes here?
The error when css is not included was Refused to apply style from 'http://localhost:5000/api/css/main.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled. However, I do not know how to make the public becomes the default path . for static files since I already included app.use(express.static(path.join(__dirname, 'public')));.

For your css file use href="/css/main.css". What you are using is relative path, check network tab in browser debug. It will load http://localhost:5000/api/css/main.css not http://localhost:5000/css/main.css.
Btw if you want to build a RESTful api, I don't think it should response a css file.

Related

setting express js static files and including them in template files

I have set my static folder to public (in the root of my app folder) within the app.js.
But still the handlebars layout files when linking the css files, could not find the files within the public folder.
// app.js code:
// init app
var app = express();
// view engine
app.set('views',path.join(__dirname,'views'));
app.set('view engine','handlebars');
app.engine('handlebars',expressHandlebars({defaultLayout:'layout'}));
// middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(cookieParser());
// set static folder
app.set(express.static(path.join(__dirname,'public')));
handlebars layout file:
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
First of all you must use absolute path as mentioned by robertklep in comments.
Now the problem, you are using app.set thats the problem, you have to use .use method not .set.
Now about how you should structure your directory, I recommend assigning a directory path like '/public' for accessing public files. It can be done like this :
//app.use not .set
app.use('/public', express.static(path.join(__dirname,'public')));
//see the first argument in above line it assigns which directory path is used to access the public file through URL
After this is done you can access the files you need like this :
<link rel="stylesheet" type="text/css" href="/public/css/bootstrap.min.css"/>

Express serving static files for multiple paths using regex

I've different paths in my app like:
/a
/a/:b
/a/:/b/:c/:d
For paths like /a, I use:
app.use(express.static(path.join(__dirname, 'public')));
For paths like /a/:b, I add another like this:
app.use('/a', express.static(path.join(__dirname, 'public')));
Instead of adding express.static for every path, is there any way to achieve this using a single line of code possibly by using regex.
Something like:
app.use(/\/[a-z]*/, express.static(path.join(__dirname, 'public')));
// BTW, this doesn't work
What would be a good practice to serve static files for multiple paths? Thank you.
You can redirect to add trailing slash:
app.all(/\/[a-z]*/, function(req, res) {
res.redirect('/static/');
});
app.use('/static/', express.static( __dirname + '/public' ));
I've solved this by adding all static links a pre-slash.
For example:
<link href='/lib/csss/bstrap.min.js' />
instead of
<link href='lib/csss/bstrap.min.js' />
NodeJS+Express: serving static files for diffrerent URLs

Node rendered HTML file not finding relative path Scripts

New to node, and have it running pulling in an HTML page using Express and EJS
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
//load up index file
app.get('/', function(req, res){
res.render('index.html');
});
However the HTML includes some relative path JS scripts
<html>
....more...
<script src="js/libs/jquery.js"></script>
<script src="js/libs/underscore.js"></script>
<script src="js/libs/backbone.js"></script>
If i run my HTML page via my original "localhost/myProject" it all works fine. However if i launch my file via Node which is set to "localhost:8080"
app.server.listen(8080);
Then it no longer finds the "/js" directory. Is there some sort of configuration that I am missing, or should i go about this another way?
Update:
Just found this
app.use(express.static( __dirname + '/public' ));
might be what I am looking for, although i need to do some refactoring
you should configure express to server static files, for example, put all the static files under a directory called 'public'
app.configure(function () {
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use('/public', express.static(__dirname + '/public'));
app.use(app.router);
});
then in your html:
<script src="/public/js/libs/jquery.js"></script>

Jade not finding view in different folder

I have a directory like this
/Workspace
/app
app.js
/lib
/public
/styles
*.css
/scripts
*.js
/views
*.jade
from app.js in app, I have the following code:
libPath = __dirname + '/../lib'
... express stuff ...
app.configure(function() {
app.set('view', libPath + '/views')
... express stuff ...
app.use(express.static(libPath + '/public'))
... rest of the app ...
Now, the problem is that Jade can't find any of the views, but all the static assets are found. Thus, app.set('view') isn't working, but express.static is. If I copy the views directory to app, using __dirname + '/views' works fine. Anyone know why this is happening?
doing app.get('view'), I get a directory like this: /Users/jong/Workspace/app/../lib/views. I tried doing the absolute route /Users/jong/Workspace/lib/views as well to no avail. It's just weird that this directory works for static assets but not templates.
You have a mistype, the correct option name is views, not view.
Configure your application like
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set('view options', { layout: true });
But the main root of issue is that you seem to misunderstand how express (and the MVC at all) works.
express sends out the static data to the browser, using your express.static configure directive, once the request url matches the existing static file path.
Otherwise, it tries to find any defined route for the requested path and to execute the associated controller (which may or may not use the template engine in turn).
So, in order to show e.g. the index page (even if it has no parameters), given you have an index.js in your views folder, you have to do something like
app.get('/', function (req, res, next) {
res.render('index', {});
});

express.js less compiler: can not get work

app.js:
app.use(express.compiler({ src: __dirname + '/public', enable: ['less']}));
app.use(express.static(__dirname + '/public'));
In my jade view:
link(rel="stylesheet", type="text/css", href='/app/stylesheets/app.less)
I've got less file in:
public/app/stylesheets/app.less
When I request the page I've got in html head:
<link href="/app/stylesheets/app.less" type="text/css" rel="stylesheet">
And noting in server console.
1) So Why does express even doesn't try to compile app.less? Should it?
2) If everything right: should link in htm be
<link href="/app/stylesheets/**app.less**" ... >
or express should change the file's extension while render?
<link href="/app/stylesheets/**app.css**" ... >
?
It seems that compiler() was removed from connect and it won't be supported anymore, according to TJ Holowaychuck (creator of Connect & Express):
https://github.com/visionmedia/express/issues/877
Update 2013-01-16
As of Express 3.0.0 the framework now includes less-middleware instead of the compiler middleware that used to be in Connect. It works much the same way as the old middleware.
To add it to an existing project, add less-middleware to your package.json and run npm install then add the following to your config:
app.use(require('less-middleware')({ src: __dirname + '/public' }));
app.use(express.static(path.join(__dirname, 'public')));
In your Jade template you reference it as a normal CSS file:
link(rel='stylesheet', type='text/css', href='css/styles.css')
Your directory structure will look something like this:
myapp
+-public
+-css
+-styles.less
less-middleware will look for .less files that have the same name as the .css file that was requested. If it finds one it will compile it and server the resulting CSS.
You'll probably want to exclude compiled CSS files from your source control. If you're using Git you can add .css to your .gitignore file.
You can get LESS compiling to work via middleware, the same way that Stylus currently works.
Edit: Instead of trying to get the [pull request][0] into the main LESS repository it was decided to just do it as a separate package.
Here is how you can use the LESS.js middleware:
var lessMiddleware = require('less-middleware');
var app = express.createServer();
app.configure(function () {
// Other configuration here...
app.use(lessMiddleware({
src: __dirname + '/public',
compress: true
}));
app.use(express.static(__dirname + '/public'));
});
In your jade file you should then be able to use the reference to the css file:
link(rel="stylesheet", type='text/css', href='/app/stylesheets/app.css')

Resources