coffeescript icon indicating copy to clipboard operation
coffeescript copied to clipboard

Docs: Document best practice for creating a small NPM module

Open shreeve opened this issue 7 years ago • 5 comments

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!

shreeve avatar Sep 09 '17 00:09 shreeve

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.

GeoffreyBooth avatar Sep 09 '17 04:09 GeoffreyBooth

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.

GeoffreyBooth avatar Sep 10 '17 07:09 GeoffreyBooth

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?

GeoffreyBooth avatar Sep 18 '17 19:09 GeoffreyBooth

👍

timm avatar Sep 18 '17 19:09 timm

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.

GeoffreyBooth avatar Jan 16 '18 04:01 GeoffreyBooth