coffeescript
coffeescript copied to clipboard
Docs: Document best practice for creating a small NPM module
When creating a small npm
package for something like strscan
, what is the modern/CS2/best-practices way to structure the repo? I'm looking for something that has a small Cakefile
and src
, lib
, and tests
directories (if those are recommended).
For example, Sam Stephenson's CoffeeScript based strscan
package from 2010 looks like this:
- https://github.com/sstephenson/strscan-js
Yet, we're 7 years later with many updates to Node, NPM, and now CoffeeScript. Would someone be able to provide a modern best-practices repo for building a simple package that could be included from other CoffeeScript or JS code simply using require 'some-package'
?
If so, it might be nice to have a small reference to this in the official documentation.
Thanks!
I don’t think anything has changed really. Keep your source in one folder, and have compiled output in a lib
or dist
or similar folder, and have your package.json
point to an entry point in the output folder. The same structure is followed by the CoffeeScript repo/NPM module itself.
You can also .gitignore
the output folder to keep it out of your repo, but use .npmignore
to have NPM track it, if you want the output files to be on NPM but untracked by Git.
The same would apply to anyone coding an NPM module in ES2015+ today, who wants their module to be usable in browsers or older versions of Node. I think this is more of a Node question than a CoffeeScript question.
Closing as I don’t think this is something we need to add to the docs, but if someone wants to write up a concise section explaining this and submit a PR, we can discuss adding it.
Someone just emailed me about this, so maybe this is something we should add to the docs. @shreeve, do you feel like tackling a first draft?
👍
migrated from #4856:
I think first we need an example Node module written in CoffeeScript that uses CommonJS, with no transpilation. This is the simplest case.
Next would be the same, but with transpilation; ideally using Babel independently, not via --transpile
. The docs advise using a “proper build chain,” with --transpile
as a convenience, so we should show people what that means; at least as two shell commands, coffee
and babel
, if not something more elaborate with Gulp or Webpack (see #4615).
After that, the ultimate best-practices example would be what this article calls a “dual-mode package,” one that can be imported via CommonJS; transpiled/Babel imports; or the new Node native module loader. This still should require no transpilation. The article recommends code like require('./file')
where the extension is unspecified, and therefore can be resolved at import time to file.js
if the module is being imported as CommonJS or file.mjs
if the module is being imported as .mjs
.
This happens to dovetail really nicely to working with .coffee
files. Imagine a Node app written in CoffeeScript where every require
statement is importing an extension-less file. So for example you have the root, index.coffee
, and it has require './file'
to import file.coffee
. You can run this in dev mode via coffee index.coffee
, and file.coffee
is imported just fine. When it’s time for production, compile it via npx coffee --compile --bare --no-header .
; this will create index.js
and file.js
. Then you can run the JS versions via node index.js
—the require
statement still works, and now it’s importing file.js
instead of file.coffee
, without you needing to do anything. That’s just how the file extensions work. The same trick can apply to .mjs
.