express.js + stylus: Automatic stylus compiling doesn't work

Sgoettschkes picture Sgoettschkes · Sep 14, 2013 · Viewed 7.7k times · Source

I am running express.js 3.4.0 with stylus 0.37.0 I am trying to get express and stylus work together so when I request a css file which is actually a stylus file somewhere else, express triggers stylus to compile it and then serve it (pretty standard I guess as I see it working in many tutorials).

My file structure:

myApp
  resources
    stylus
      style.styl
  public
    css

My app.js (only relevant lines):

app.use("/static", express.static(__dirname + "/public"));
app.use(stylus.middleware({
    src: __dirname + "/resources/stylus",
    dest: __dirname + "/public/css",
    debug: true,
    force: true,
}));

From what I read, requesting /static/css/style.css should lead to express generating this file from resources/stylus/style.styl and then serving it. This does not work. What works is if I request the file /style.css the file /public/css/style.css is correctly generated, but I get a 404 nonetheless. Afterwards, I can request it through /static/css/style.css as it exists physically now.

Can somebody suggest any steps to fix this? Am I missing something?

Answer

hexacyanide picture hexacyanide · Sep 14, 2013

For the compiling to work, the directory that you're serving from must also exist in the source directory. Since style.styl is in the root of the source, it is also in the root for GET requests. In resources, rename stylus to css, and change your configuration to look like this:

app.use(stylus.middleware({
  src: __dirname + '/resources',
  dest: __dirname + '/public',
  debug: true,
  force: true
}));

Now when you GET /css/style.css, it will compile the stylesheets. Graphically, this is how compiling is structured:

/resources/style.styl       -->   /public/style.css
/resources/css/style.styl   -->   /public/css/style.css

Then, another issue comes up. You want to serve /public with /static.

app.use('/static', express.static(__dirname + '/public'));

You will have to change that line to:

app.use('/static', express.static(__dirname + '/public/static'));

The solution to this would be to structure your application like this:

myApp
├─┬ public
│ └─┬ static
│   └── css
└─┬ resources
  └─┬ static
    └─┬ css
      └── style.styl

Now, when you GET /static/css/style.css, the stylesheets will be compiled from location /resources/static/css/style.styl.

As a result with the file tree shown above and this code:

var express = require('express');
var stylus = require('stylus');
var app = express();

app.use('/static', express.static(__dirname + '/public/static'));
app.use(stylus.middleware({
  src: __dirname + '/resources/',
  dest: __dirname + '/public/',
  debug: true,
  force: true,
}));

On first load /static/css/style.css will 404 but on second load the stylesheets will be there.