I have used CoffeeScript for a while. Now I need to write a npm package, can I write it in CoffeeScript, or I should compile CoffeeScript into JavaScript?
-
1See also: http://stackoverflow.com/questions/26196595/how-do-i-compile-coffeescript-before-publishing-to-npm – Aidan Feldman Dec 15 '15 at 21:26
5 Answers
I'm going to suggest that you write your package in coffeescript, but only publish it in javascript. I do it like this:
- coffeescript code goes in
src
- code is compiled to
lib
src
is committed to my git repo,lib
is in my.gitignore
lib
is published to npm,src
is in my.npmignore
- the
coffee-script
package is in mydevDependencies
You can take a look at a simple package of mine, refix, for inspiration:
- https://github.com/linus/refix
npm install refix

- 38,647
- 9
- 109
- 104
-
24I'll add that defining an `prepublish` task in your package.json that compiles your coffeescript is a handy way to automate this before your publish -- since we all forget to compile sometimes. See the npm `scripts` doc for more info: https://npmjs.org/doc/scripts.html – smithclay Dec 10 '12 at 06:40
-
10The one point I disagree with is keeping the lib folder in `.gitignore`. It is very handy to keep the lib folder in git so that people can reference your package via a git url. – ghempton May 22 '13 at 01:17
-
4If you have a postinstall task that compiles your coffeescript then you don't need to check in .js to `lib/` in your git repository, and can safely add it to ignore just as Linus suggests here. See - https://github.com/ilkosta/static-jade-brunch for an example of how you could use those hooks (as well as how you might possibly avoid a global install of coffeescript) – Merlyn Morgan-Graham Jun 06 '14 at 07:30
-
While this is probably the more sustainable approach and a good example of best practices, you can also check out http://stackoverflow.com/a/27813782/722758 for a more direct (if somewhat hacky) way to use coffeescript within an npm package. – jrh Jan 07 '15 at 06:43
-
Relevant issue in the Coffeescript repo: https://github.com/jashkenas/coffeescript/issues/2216 – Ehtesh Choudhury Mar 04 '15 at 17:04
-
@Linus i fail to see a .gitignore and a .npmignore in your repository, am i missing something? – kroe Oct 09 '16 at 06:58
-
1@kroe so sorry, that's a bit awkward and quite hilarious. I had never added the files, since dot-files are ignored by the .gitignore... Silly me. Fixed now, thanks! – Linus Thiel Oct 10 '16 at 08:34
You can write NPM modules in coffeescript, but in order for them to be usable by JS users they must be compiled to JS before you publish on NPM.
package.json
makes this easy with their prepublish
script hook which runs the specified script before you publish. Heres an example of a prepublish
NPM hook in zombie.js
https://github.com/assaf/zombie/blob/master/package.json#L16

- 435
- 3
- 9
If a lot of your modules have coffee-script
in their devDependencies
, it's useful to just globally install coffee-script
instead of install it for each module (which takes much longer).
coffee-build is a global version manager for coffee-script
.
Just add these 2 scripts to your package.json
:
{
"name": "my-coffee-module",
"scripts": {
"build": "coffee-build -v 1.11.x -b -o js src",
"postinstall": "npm run build"
}
}
Notice how -v 1.11.x
is not an exact version, which allows implicit upgrades.
The only downfall is that users must npm install -g coffee-build
before they can install your module.

- 18,087
- 14
- 64
- 91
I have written npm packages in CoffeeScript from scratch. I encourage you to use CoffeScript for node as well as for the Browser. However, before you can use or publish your module, you have to compile the source CoffeeScript to JavaScript. That should not hold you back from using CoffeeScript, though.
Tip: While developing, use coffee -cw yourfile.coffee
(command line) to watch the file for changes and compile on save.

- 606
- 4
- 7
While I'm not sure if it's the best approach, technically it is possible to write your package mostly in CoffeeScript.
Basically, you can write a JS file that simply wraps the coffee
command, like so:
bin/howl.coffee
console.log 'Awwwooooo!'
bin/howl.js
#!/usr/bin/env node
var path = require('path');
var exec = require('child_process').exec;
var coffee = path.resolve(__dirname, '../node_modules/coffee-script/bin/coffee');
var howl = path.resolve(__dirname, './howl.coffee');
var command = coffee + ' ' + howl;
exec(command, function(error, stdout) {
if (error) { throw error };
console.log(stdout);
});
Running node howl.js
(or simply howl
when it's installed globally) will now output Awwooooo!
. You can do things like require
other CoffeeScript files and access arguments by passing them from the JavaScript "wrapper" to the CoffeeScript.
Anyway, there may be reasons not to do this, but it has worked for me so far so figured I'd submit this for an additional perspective.
For a simple example project using this technique, check out https://www.github.com/joshuabc/packdown.

- 4,101
- 2
- 22
- 27
-
For your specific example, there is no need to use exec. You can use require('coffee-script/register'), it registers a global handler for requires that automatically compiles any coffee dependency. Howerver that is not a good practice for a library since the global coffee-script can conflict with other versions – Diego Jan 09 '15 at 21:14
-
1Previous example becomes: require('coffe-script/register'); var howl = require('./howl'); – Diego Jan 09 '15 at 21:16
-
Good point Diego. Some more detail on that: `coffee-script/register` depends on [require.extensions](http://nodejs.org/docs/latest/api/globals.html#globals_require_extensions) which is deprecated. According to nodejs.org: *"Since the Module system is locked, this feature will probably never go away. However, it may have subtle bugs and complexities that are best left untouched."* The feature is [unlikely to be removed from coffee itself](https://github.com/jashkenas/coffeescript/issues/3692), but in my opinion the deprecation is a good reason to steer clear. – jrh Jan 12 '15 at 17:19