17

I am unable to render less css in my express workspace.
Here is my current configuration (my css/less files are in 'public/stylo/') :

app.configure(function()
{
    app.set('views'      , __dirname + '/views'         );
    app.set('partials'   , __dirname + '/views/partials');
    app.set('view engine', 'jade'                       );
    app.use(express.bodyDecoder()   );
    app.use(express.methodOverride());
    app.use(express.compiler({ src: __dirname + '/public/stylo', enable: ['less']}));
    app.use(app.router);
    app.use(express.staticProvider(__dirname + '/public'));
});

Here is my main.jade file :

!!!
html(lang="en")
     head
         title Yea a title
         link(rel="stylesheet", type="text/css", href="/stylo/main.less")
         link(rel="stylesheet", href="http://fonts.googleapis.com/cssfamily=Droid+Sans|Droid+Sans+Mono|Ubuntu|Droid+Serif")
         script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js")
         script(src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js")
     body!= body

here is my main.less css :

@import "goodies.css";

body 
{
    .googleFont;
    background-color     :  #000000;
    padding              :  20px;
    margin               :  0px;

    > .header
    {
        border-bottom    :  1px solid #BBB;
        background-color :  #f0f0f0;
        margin           :  -25px -25px 30px -25px; /* important */
        color            :  #333;
        padding          :  15px;
        font-size        :  18pt;
    }
}

AND here is my goodies.less css :

.rounded_corners(@radius: 10px)
{    
    -moz-border-radius   :  @radius;
    -webkit-border-radius:  @radius;
    border-radius        :  @radius;
}
.shadows(@rad1: 0px, @rad2: 1px, @rad3: 3px, @color: #999)
{
    -webkit-box-shadow   :  @rad1 @rad2 @rad3 @color;
    -moz-box-shadow      :  @rad1 @rad2 @rad3 @color;
    box-shadow           :  @rad1 @rad2 @rad3 @color;
}
.gradient (@type: linear, @pos1: left top, @pos2: left bottom, @color1: #f5f5f5, @color2: #ececec)
{
    background-image     :  -webkit-gradient(@type, @pos1, @pos2, from(@color1), to(@color2));
    background-image     :  -moz-linear-gradient(@color1, @color2);
}
.googleFont
{
    font-family          :  'Droid Serif';
}

Cool deal. Now: I have installed less via npm and I had heard from another post that @imports should reference the .css not the .less. In any case, I have tried the combinations of switching .less for .css in the jade and less files with no success.

If you can help or have the solution I'd greatly appreciate it.

Note: The jade portion works fine if I enter any ol' .css.
Note2: The less compiles if I use lessc via command line.

Bharathvaj Ganesan
  • 3,054
  • 1
  • 18
  • 32
Paden
  • 181
  • 1
  • 1
  • 7

5 Answers5

16

Gosh, that stuff is very inconsistent in how the paths work, however I found out how you can get it to work.

The first problem is with your paths, both compiler and staticProvider, compiler needs to use /public and is will hook into all requests below that. If you don't do that, the compiler will try to use a path like /public/stylo/stylo.

The second problem lies with the @import in main.less file and the fact that less compiler is stupid and does not handle relative imports.

Using @import "/public/stylo/goodies.css"; in your main.less will make it work.

Filed a Bug for the relative path issue with less:
https://github.com/cloudhead/less.js/issues/issue/177

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112
  • THANKS!! I changed compiler to "app.use(express.compiler({ src: __dirname + '/public', enable: ['less'] }));" But when the html/jade is pointed to a .less file, it does not interpret it to a .css file. Any suggestions? – Paden Jan 11 '11 at 23:59
  • 1
    Ahh, got it to work! My jade file had to point to a .css file, and the less associated will be compiled! THANKS FOR THE HELP!! :D – Paden Jan 12 '11 at 00:05
  • One more thing, the @import should not have an extension. So: "@import "/public/stylo/goodies";" – Paden Jan 12 '11 at 00:09
  • 1
    now that you have it working, is there any way to pass an argument to express.compiler() that would make the output minified? along the lines of: parser.parse('.class { width: 1 + 1 }', function (e, tree) { tree.toCSS({ compress: true }); // Minify CSS output }) – tester Mar 17 '11 at 09:51
  • 1
    Express 3.0.0 now includes a different middleware for compiling LESS. The original `compiler` middleware was removed from Connect which Express is based on. The new middleware is `less-middleware` and works pretty much the same way as the old one, but includes things like compressing the CSS output. – Gregory Bell Jan 16 '13 at 22:02
3

If you want to minify the outputted css, I found that the built in compiler (from the connect module) was missing the compress option. So rather than writing my own middleware compiler for it. I overwrote the connect less compiler in my app.

var express = require('express');
var app = express.createServer();
var less;

express.compiler.compilers.less.compile = function (str, fn) {
    if (!less) less = require("less");                                                      
    try {
        less.render(str, { compress : true }, fn);
    } catch (err) {
        fn(err);
    }
};

app.use(express.compiler({ src: publicdir, enable: ['less'] }));
Matt Sain
  • 169
  • 5
1

The problem is that the compiler only compiles the file if its mtime is changed.

Lets say you have:

// A.less
@import "B.css";

and

// B.less
body {
  background: #f00;
}

I now I modify B.less, A will not be recompiled!

I have a pull request waiting since months, you can use my fork compiler instead of the master one.

https://github.com/senchalabs/connect/pull/167

masylum
  • 22,091
  • 3
  • 20
  • 20
  • Thanks for that insight! That is a terrible bug. I will keep this in mind, but my "a.less" file won't compile either on any request. – Paden Jan 12 '11 at 00:02
  • I just tested this and you are correct. Wow! That's really bad! – Paden Jan 12 '11 at 00:11
  • Imports are typically bad for performance so are avoided. I am assuming that bug slipped through since it is not best practice :-) References: https://developers.google.com/speed/docs/best-practices/rtt#AvoidCssImport http://www.stevesouders.com/blog/2009/04/09/dont-use-import/ – Clint May 05 '12 at 14:59
0

Two projects which could make your life easier

  1. Buildr: The (Java|Coffee)Script and (CSS|Less) (Builder|Bundler|Packer|Minifier|Merger|Checker)

  2. Less4Clients: Express.js extension to render LessCSS (.less) files server-side :)

balupton
  • 47,113
  • 32
  • 131
  • 182
0

I've published a package on GitHub called node-kickstart-example which uses a handy pre-configured express with enabled jade template rendering and less stylesheet processing. Use npm to install kickstart, place your jade templates in views/ and your less files in assets/styles/ and your good to go…

Matt Sain's solution for generating compressed css files with less and express is in included in kickstart.

sbstjn
  • 2,184
  • 1
  • 15
  • 13