In development I use both Coffeescript and Browserify middleware on my Express server to deliver my client side JS like so:
app.use browserify mount: '/client.js', entry: './client.coffee', watch: yes
Today I was upgrading my dependencies and noticed this on the browserify v2 website:
One of the worst ideas in browserify, the ad-hoc http server middleware to host bundles is finally gone.
Default support for coffee-script is gone. You can still use coffee script in your program, you'll just need to either compile to js or hook the source transformation into the bundle pipeline yourself.
Remember that if you disagree with these cuts which I expect many people will, with the v2 refactoring it's much easier to roll your own vision of how browserify should be using the underlying new libraries as a starting place.
Fair enough.
Only thing is, I have read the docs for the new API and I'm at a bit of a loss how to actually go about implementing my own middleware. In fact I can't even get a basic standalone example working using browserify.add() and browserify.bundle(), let alone as express middleware.
I could just continue to use v1 but as this project is still in development I'd like to keep my dependencies up to date. Any suggestions greatly appreciated.
I've got this far:
browserify = require 'browserify'
coffee = require 'coffee-script'
through = require 'through'
app.get '/client.js', (req, res) ->
b = browserify()
b.add './client.coffee'
b.transform (file) ->
write = (buf) ->
data += buf
end = ->
@queue coffee.compile(data)
@queue null
data = ''
return through(write, end)
b.bundle {}, (err, src) ->
res.send src
This works, except where I used to say require './module' it appears I now have to require './module.coffee'. This isn't really ideal, I don't want to have to update every require in my app.
I got this working:
browserify = require('browserify-middleware')
coffeeify = require('coffeeify')
express = require('express')
app = express()
browserify.settings('transform', [coffeeify])
app.get('/client.coffee', browserify('./client.coffee'));
app.listen(3230);
But it may not solve the needing to require("X.coffee") problem.
If you like grunt for development, I've developed this task : https://github.com/amiorin/grunt-watchify
It caches the dependencies and watches the filesystem. Because of this the build is very fast. You can use it with grunt-contrib-watch and grunt-contrib-connect or alone. You can find a Gruntfile.js example in the github repository.
If you don't use grunt, you can use the original watchify from @substack : https://github.com/substack/watchify
You can use coffee of course with the transform.
The way to have coffee-script compilation middleware for browserify is either via a transform module with the -t flag, or a transform command with the -c flag. They have their limitations, but they'll do the trick for simple coffeescript compilation. With either flag, each required file gets run through a process (for example, compiled to javascript from coffeescript), before it's analysed and concatenated into the output bundle
In fact, there's now documentation on the browserify readme on how to do it exactly for coffeescript:
https://github.com/substack/node-browserify#btransformtr
The easiest way in your case would be simply to use the command:
browserify -c 'coffee -sc' main.coffee > bundle.js
assuming your entrypoint coffeescript file was called main.coffee.
Substack has also created a coffeeify npm module that wraps up this, but it's a coffee-script version behind the current (no source maps, for example).
At this point you have two transformer options, both of which support source maps.
They are identical, except that the latter only re-compiles coffee files that actually changed which speeds up the development process.
In both cases you need to turn on source maps, by either passing a --debug flag if you are using the command line or supplying {debug: true } to the bundle function in case you are using a build script.
Also make sure to enable source maps in your browser.
I blogged about all this so if you need more details, you should find all the information you need here.
I wrote a dirty broweserify middleware coffee compiler thing (does js and underscore templates too). Its not amazingly great but it works.
https://github.com/pr1ntr/bundlr
usage is simple enough
var bundlr = require('bundlr');
app.use(bundlr({options}))
options:
src = location of bootstrap js or coffee
dest = (if you want it to write a file where you want it)
route = the route or path to get it to compile
debug = true/false if you want it to not compress and add source maps
cache = if you want the server to cache response (for production env)
write = pass true if you want it to write the file to the destination