How to make Stylus update CSS in the right directory? - node.js

Using Node.js + Express, but for some reason cannot get css to work properly. I have the following two folders:
/public/css/lib - where .css files should go
/public/css/src - where .styl files are
And the following configs:
app.configure(function() {
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger({
format: 'dev'
}));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('whatever'));
app.use(express.session());
app.use(app.router);
app.use(require('stylus').middleware({
src: __dirname + '/public/css/src',
dest: __dirname + '/public/css/lib',
compress: true,
force: true,
compile: function(str, path) {
return stylus(str)
.set('filename', path)
.set('warn', true)
.set('compress', true);
}
}));
app.use(express.static(path.join(__dirname, 'public')));
});
But I get no .css file auto-generated when starting the app or making changes to .styl files, or going to /css/lib/app.css.
What am I doing wrong?

Related

Express mode configuration, issue with loading partials

The server find the views in "development" mode but not in "production" mode. Instead of the real views it shows me the 404 view.
For instance, with this route "/login":
It work : with development code (CASE 1), GET views/login.html provide the real login content
It doesn't work : with production code (CASE 2), GET views/login.html provide the content of my 404 view
In order to test in development mode both configurations, I just swith code manually. Here is some of my Express configuration:
// Express Configuration
app.configure('development', function(){
// CASE 2: PRODUCTION CONFIG TO TEST
app.use(express.favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
/* CASE 1: REAL DEVELOPMENT CONFIG
app.use(require('connect-livereload')());
app.use(express.static(path.join(__dirname, '.tmp')));
app.use(express.static(path.join(__dirname, 'app')));
app.use(express.errorHandler());
app.set('views', __dirname + '/app/views');
*/
});
app.configure('production', function(){
app.use(express.favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
});
app.configure(function(){
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
// Router needs to be last
app.use(app.router);
});
// Controllers
var api = require('./lib/controllers/api'),
controllers = require('./lib/controllers');
// Angular Routes
app.get('/views/*', controllers.partials);
app.get('/*', controllers.index);
Here are the architecture which is used in dev mode:
->app
---->scripts
---->views
------>login.html
------>404.html
Here are the architecture in prod mode and the folders used (after "grunt build"):
->public
->views
--->login.html
--->404.html

Node-sass is not auto-compiling in latest node/express

Using node (0.10.15) and express (3.3.4), along with the latest node-sass, and I can't get my scss files to compile. My app.js file looks like this:
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, sass = require('node-sass');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(
sass.middleware({
src: __dirname + '/public/sass',
dest: __dirname + '/public',
debug: true,
outputStyle: 'compressed'
})
);
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
What am I missing to get sass to auto-compile?
If it matters, I'm using supervisor to monitor changes.
Middlewares are executed in the order they are attached to the app. The node-sass middleware only compiles scss files to css, it does not serve them. The static middleware is able to serve the compiled css files, however, it can’t do so as long as the css files are not compiled yet. If you switch static and sass middlewares, everything should work as expected:
app.use(
sass.middleware({
src: __dirname + '/public/sass',
dest: __dirname + '/public',
debug: true,
outputStyle: 'compressed'
})
);
app.use(express.static(path.join(__dirname, 'public')));
Now the following happens when you request /style.css:
sass notices a request for a css file. If the dest file (__dirname + '/public' + '/style.css') is up-to-date, it does nothing. Otherwise, it looks for the src file (__dirname + '/public/sass' + '/style.scss') and compiles it, if it exists.
static notices a request for a static asset. If the requested file (path.join(__dirname, 'public') + '/style.css') does exist, it is served.
I also had serious problems setting this up with Koa (koa.js) and koa-sass. Eventually I figured out the problems. node-sass is 'too clever' for it's own good:
app.use(sass({
src: __dirname + '/public/sass',
dest: __dirname + '/public/css',
debug: true,
outputStyle: 'compressed',
prefix: '/stylesheets'
}));
I was getting a 500 when it tried to access /public/sass/stylesheets/styles.css- but I didn't have 'stylesheets' in my path: My html template file was looking at /stylesheets/styles.css so I had to remove the prefix with prefix: '/stylesheets'.
Next I had a problem with the scss file - I had accidentally copied an old .styl file and it was trying to use nib - which I found after discovering the debug: true setting.
As soon as I replaced it with a valid css or scss file it compiled and rendered using koa-static.
Although this is a koa-sass issue, koa-sass just wraps node-sass with a generator so it belongs here (IMO).

How to configure express.js/jade to process html files?

I would like to configure jade engine to handle .html files in my views folder. Here is my currentserver configuration:
app.configure(function(){
var pub_dir = __dirname + '/public';
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ secret: nconf.get("site:secret") }));
app.use(everyauth.middleware());
app.use(require('less-middleware')({ src: pub_dir, force:true }));
app.use(express.static(pub_dir));
app.use(app.router);
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
});
https://github.com/visionmedia/express/blob/master/examples/ejs/index.js
app.engine('.html', require('jade').__express);
Make sure you already have jade in your node_modules
npm install --save jade
In express 4.x, you can simply set the view engine to jade.
app.set('view engine', 'jade')

layouts in expressjs

I want to use 2 layouts for main page and admin page
What should i configure my code to do that?
here is my current code configure
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(express.static(__dirname + '/public'));
app.use(express.cookieParser());
app.use(express.session({secret: 'secrect', store: MemStore({
reapInterval: 60000 * 10
})}));
app.use(app.router);
});
I usually set layout to false globally, so I know exactly what layout I use where (so no default layout):
app.set('view options', { layout: false });
Then in my routes I can set a layout per route like so:
res.render('my_page', { layout: 'my_layout' });
Read more about Express layouts and templates engines

Failed to include nib to my expressjs/nodejs site?

I followed the example here to add nib to my site:
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, nib = require('nib');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ secret: 'your secret here' }));
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(nib());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
But when I start the server I get this error:
500 TypeError: Object #<IncomingMessage> has no method 'include'
at Object.handle (/home/alex/apps/foo/node_modules/nib/lib/nib.js:51:11)
at next (/home/alex/apps/foo/node_modules/express/node_modules/connect/lib/http.js:201:15)
at Object.handle (/home/alex/apps/foo/node_modules/stylus/lib/middleware.js:187:7)
at next (/home/alex/apps/foo/node_modules/express/node_modules/connect/lib/http.js:201:15)
at /home/alex/apps/foo/node_modules/express/node_modules/connect/lib/middleware/session.js:323:9
at /home/alex/apps/foo/node_modules/express/node_modules/connect/lib/middleware/session.js:342:9
at Array.0 (/home/alex/apps/foo/node_modules/express/node_modules/connect/lib/middleware/session/memory.js:52:9)
at EventEmitter._tickCallback (node.js:126:26)
Any suggestions to fix this?
try this in your "development" mode since you don't want to have stylus compiling at run time in a production environment:
app.configure('development', function(){
var stylusMiddleware = stylus.middleware({
src: __dirname + '/stylus/', // .styl files are located in `/stylus`
dest: __dirname + '/public/', // .styl resources are compiled `/css/*.css`
debug: true,
compile: function(str, path) { // optional, but recommended
return stylus(str)
.set('filename', path)
.set('warn', true)
.set('compress', true)
.use(nib());
}
});
app.use(stylusMiddleware);
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express['static'](__dirname + '/public'));
});
that's my usual setup with nib and stylus. and with this set up you'd need to move up your require("stylus") to the top as stylus = require("stylus"), similar to your require("nib").
you will have to have your general configure method list after the development one.

Resources