Stylus and CoffeeScript middleware automatically compile any Stylus and CoffeeScript code for you without having to restart your app, eg you can edit a .styl file and just refresh the page in your browser and your changes will be there. I find this to be very convenient while developing, but would that severely effect the end-user's page load time in production?
My Express setup is usually something like this (CoffeeScript):
app = express()
app.set 'views', __dirname + '/views'
app.set 'view engine', 'jade'
compile = (str, path) -> return stylus(str).set 'filename', path
app.use stylus.middleware {
src: __dirname + '/stylus',
dest: __dirname + '/assets/css',
compile: compile
}
app.use coffee {
src: __dirname + '/coffee',
dest: __dirname + '/assets/js',
encodeSrc: false
}
app.use express.static __dirname + '/assets'
It will definitely be slower than serving the pre-compiled files statically (if Stylus and CoffeeScript don't support caching which I don't know). The question is, whether this matters. And this depends on the intensity of the traffic your app receives.
In general, I would suggest to pre-compile your files and serve it statically. For the deployment, I would suggest to use something like Gulp.js and watch your files. With gulp your files can be automatically compiled on file changes which is most of the time better than compiling it when the files are requested.
My express (3.X) server looks like:
express = require "express"
app = express()
app.configure ->
app.use express.static(__dirname + '/public')
app.use app.router
console.log __dirname + '/public'
app.get "*", (req, res) ->
res.sendfile "index.html"
app.listen 1234
console.log "Server listening on port 1234"
I'm using it for an AngularJS project, so if anything is in the /public folder, I want it served directly. My /public folder has a scripts and templates folder in it.
However, when I go to http://localhost:1234/public/scripts/app.js, I get the contents of index.html
In this scenario, /public is your webroot. You need to change your reference to http://localhost:1234/scripts/app.js.
I have a project that uses Nib and Stylus on Express server, and after some changes this compilation process from .styl to .css didn't work anymore, I was looking in documentation of Nib, Stylus and Express but I can't find an answero to problem because my code, file directory and settings seems ok. But still doesn't compile.
Code:
express = require("express")
coffee = require("coffee-script")
stylus = require("stylus")
jade = require("jade")
nib = require("nib")
app = express.createServer()
port = process.env.PORT || 3000
app.use app.router
app.use express.methodOverride()
app.use express.bodyParser()
app.set "views", __dirname + "/views"
app.set "view engine", "jade"
app.use stylus.middleware(
src: __dirname + "/src"
dest: __dirname + "/public"
compile: (str, path) ->
stylus(str).set("filename", path).set("warn", true).set("compress", false).set("paths", [ require("stylus-blueprint") ]).use nib()
)
app.listen port
After looking into documention, Github issues, I can't understand what changes have been made to stop working. So, my question, how or what I should be looking for to try resolve this problem?
Thanks for the help in advance.
It would be useful if you provided a error output/log and a cakefile.
Also you might want to look into using connect-assets. A good example of usage is in the express-coffee template.
I have a simple Express server that is serving up some static files. Here is the server:
var express = require('express');
var app = express.createServer();
// Configuration
app.configure(function() {
app.use(express.bodyParser());
app.use(express.staticCache());
app.use(express.static(__dirname + '/public'));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
// 404
app.get('*', function(req, res) {
res.send('not found', 404);
});
app.listen(3000);
In my public directory I have a file called index.html. Firing up node app.js and then browsing to localhost:3000/index.html shows the static file as expected. Navigating to localhost:3000/ind or localhost:3000/ind\ shows the 404 page as expected.
However, navigating to localhost:3000/index.html\ (note the trailing backslash) crashes my node server with:
stream.js:105
throw er; // Unhandled stream error in pipe.
^
Error: ENOENT, no such file or directory '/home/bill/projects/app/public/index.html\'
Why is the node server crashing instead of just serving up the 404 page? I thought since the file does not exist, the static middleware would just skip it and pass the request on to the routes. I got around it by creating a custom middleware that returns 404 if a trailing backslash exists in the request URL, but I'd like to figure out if I'm missing something here. Thanks!
The reason for this behavior seems to be the difference in how fs.stat and fs.createReadStream handle trailing backslashes.
When the string 'path/to/public/index.html\\' is given to fs.stat in the static middleware, it is ignored (running stat index.html\ on the command line checks for a file named index.html, you'd have to run stat index.html\\ for index.html\). So fs.stat thinks the file was found because it thinks you're asking for index.html, and doesn't call the next middleware handler.
Later, that string is passed to fs.createReadStream which thinks it's looking for index.html\. It doesn't find that file and throws said error.
Since the functions treat the backslash differently, you can't really do anything but use some middleware to filter out those requests.
What I would like to do is add the following to me already running coffeescript written server
app.get '/test.js', (req, res) ->
render coffee somecoffeefile.coffee
Is something like this possible with NodeJS, Express, and Coffeescript?
Thanks!
Jose
Good news: This is already comes with Connect (and therefore Express, which extends Connect) as a plugin! It's not well-documented; in fact, I wrote something similar myself (connect-coffee) before I was informed that such a thing already existed.
Here's how you'd go about setting it up with Express:
# Notice the following code is coffescript
# You must add the parens for the app.use method to use in js
coffeeDir = __dirname + '/coffee'
publicDir = __dirname + '/public'
app.use express.compiler(src: coffeeDir, dest: publicDir, enable: ['coffeescript'])
app.use express.static(publicDir)
Now when, say, http://yourapp/foo.js gets requested, if no such file exists in your public directory, foo.coffee will automatically be compiled, and the resulting foo.js will be served. Note that it's important for static to be set up after compiler.
Update: As of Connect 1.7, the compiler middleware has been removed. Partly because of that, and partly to provide a more Rails 3.1-like experience, I've created a new middleware called connect-assets. Install it with npm, then set it up like so:
app.use require('connect-assets')(directory)
where directory is the folder your CoffeeScript files are in (the default is assets). Simple, right? Try it out and let me know what you think.
CoffeeScript = require 'coffee-script'
app.get '/test.js', (req, res) ->
render CoffeeScript.compile coffeeSourceCode
For some reason, the compiler isn't working anymore, so I did this:
fs = require 'fs'
coffee = require 'coffee-script'
app.use express.static "#{__dirname}/static"
app.get '/:script.js', (req, res) ->
res.header 'Content-Type', 'application/x-javascript'
cs = fs.readFileSync "#{__dirname}/coffee/#{req.params.script}.coffee", "ascii"
js = coffee.compile cs
res.send js
Now you can code up coffee/animal.coffee and in your html, do a standard script src='/animal.js'. This hides the implementation detail. The coffeescript is not accessible because "/coffee" dir is not exposed as a static path.
Notes:
This is, of course, a CoffeeScript Node app. I assume if you're using CS for client scripts, you're using it for your server too!
The "static" line is optional. My point is you can happily keep "js" files in the static dir, e.g. library files like jquery.min.js.
Like most Node/Express examples, this is good for development; but for production, you should send cache headers, compress it, and ideally some form of reverse-proxying to avoid reading the file and compiling it each time.
For those of us using the latest version of Connect and Express, I've just published a new module, npm install connect-coffee-script, which compile coffee script files on the fly. Documentation and a sample are provided as well as an introduction article.
Here's an exemple from the readme:
var coffeescript = require('connect-coffee-script');
var connect = require('connect');
var app = connect();
app.use(coffeescript({
src: __dirname,
dest: __dirname + '/public',
bare: true
}));
app.use(connect.static(__dirname + '/public'));
app.listen(3000)
If you would like to use a great existing plugin I would recommend Trevor Burnham's Connect-Assets. It helps compiling, minifying and concatenating .js and .coffee-files and optimizes how the files are being served (a far-future expires header with invalidation using the file's md5-hash). Well written plugin.
coffee-middleware did exactly what I wanted to - minimal setup, no generated files, and not sloppy.
When it gets a request for somescript.js it will check if there is a somescript.coffee. If there is, it will compile it and send it over.
Install it:
npm install coffee-middleware
To use, just add
app.use require('coffee-middleware') src: "#{__dirname}/your/web/root"
before whatever you use to serve static files.
Simple example that serves files in a "public" directory, complies coffeescript before sending it over, and does colored logging:
app = require('express')()
app.use require('morgan') 'dev'
app.use require('coffee-middleware') src: "#{__dirname}/views"
app.use require('serve-static') "#{__dirname}/views"
app.listen 80
To use above code:
mkdir coffeeServer
cd coffeeServer
npm install morgan coffee-middleware serve-static
npm install coffee-script -g
echo 'app = require("express")()
app.use require("morgan") "dev"
app.use require("coffee-middleware") src: "#{__dirname}/views"
app.use require("serve-static") "#{__dirname}/views"
app.listen 80' > server.coffee
coffee -c server.coffee
mkdir views
cd views
echo 'console.log "Hello world!"' > script.coffee
cd ..
node server.js
You can copy the whole bunch into the terminal and it will setup and run the server.
To test:
curl XXX.XXX.XXX.XXX/script.js
That last bit should spit out
(function() {
console.log("Hello world!");
}).call(this);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0LmpzIiwic291cmNlcyI6WyJzY3JpcHQuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQUEsRUFBQSxPQUFPLENBQUMsR0FBUixDQUFZLGNBQVosQ0FBQSxDQUFBO0FBQUEifQ==NHS0076
Good luck!
I think you should compile COFFEE files only once, especially with production mode
If you want use coffee with Express 3, or with any web framework look to this repo ExpressOnSteroids You can use this solution, or create your own with Cakefile from this project
You can use Coffee4Clients to render coffee assets to javascript on the fly with your express server.
Update: Coffee4Clients has been killed in favour of DocPad which pre-compiles your assets.