Faster & Cleaner Module Workflow
I’ve noticed when writing lots of small modules that the process of creating new modules and repositories can be a little tedious and error-prone. Automating the process makes things more efficient, produces consistent and clean repositories, and also forces me into the mindset of documenting and testing early on.
Here are some suggestions, tools and scripts that have improved my workflow. I’m going to presume OSX throughout this article, since I don’t use Windows.
example readme for a small module
terminal basics #
The best way to improve efficiency when working with npm modules is to get more familiar with terminal commands. You might already know cd
and ls
, but here’s a few other goodies:
tab
key will auto-complete a path to the next folder; double-tap to list all paths that match the inputup/down
arrow keys to repeat previous commandsCtrl + A
andCtrl + E
to jump to the start/end of your current inputtouch README.md
will create a new file calledREADME.md
if it doesn’t already existmkdir -p foobar
creates a new folder calledfoobar
if it doesn’t already existopen .
opens the current folder in the Finderpbpaste > text.txt
pastes the current clipboard contents into a new file calledtext.txt
terminal tools #
There’s also some really handy utilities to improve efficiency in terminal. rupa’s z script is like a super-charged cd
. It jumps to the given regex match, and remembers the most used patterns. So you could type z proj
to jump to ~/Documents/projects
.
Another one is opening your IDE at the current folder. Sublime users tend to use subl.
So a typical series might look like:
z proj
mkdir foobar
cd foobar
subl .
And, of course, there are lots of tools like iTerm2 that act as replacements.
npm commands #
Once you’re comfortable with jumping around your file system and creating new files/folders, you can start speeding up your module creation process.
The easiest thing you can do is learn which npm commands will create and modify package.json
for you:
# setup a bare-bones package.json
npm init
# can be used to bump version number and git commit
npm version patch|minor|major
# remember to use a flag when installing!
npm install foobar --save
npm install foobar --save-dev
With npm init
you get a basic package.json
, but not much more. Most modules will also want:
.gitignore
so you aren’t committing node_modules etc.npmignore
so you aren’t pushing tests/bundles to npmREADME.md
formatted for discoverability/SEOLICENSE.md
so that companies can justify using your module to their legal teamsindex.js
or some aptly named entry pointtest.js
to provide unit tests and give more confidence about the strength of the code- more detail in
package.json
(like GitHub repo) for better discoverability
module-generator #
This is where module-generator comes into play (originally forked from hughsk). You can, of course, fork it yourself to meet your needs, or find/write another module generator. The idea is to automate the tedious boilerplate for new modules.
To install:
npm install module-generator -g
After setting up your config, the process looks like this:
mkdir my-module
cd my-module
module-generator
This prompts for package details and sets up the essential stuff (readme, MIT license, gitignores, etc). Most importantly, it gives your modules a consistent “look and feel” and ensures they have all the details needed for discoverability and SEO.
It also produces a stability badge, which can be a useful hint to those depending on your module:
unit testing #
Unit testing your code is essential when you start working with small and re-usable modules; it will give other users more confidence in your code and also allow you to catch errors as you introduce new features and patches.
I use tape to support front- and back-end code. It’s much more light-weight and Unixy than jasmine/mocha/etc, requires less boilerplate, works in the browser, and integrates easily with other tools (like Git hooks).
Since I use it on almost all my modules, module-generator
supports a --test
or -t
flag:
module-generator --test
This installs the latest verison of tape
, saving it as a devDependency, creates an empty index.js
, and generates basic test.js
that looks like this:
var myFunkyModule = require('./')
var test = require('tape').test
test(/* description inserted here */, function(t) {
t.end()
})
Which allows you to start developing immediately with your tools of choice:
#run once
node test
#run continuously
nodemon test
#run in browser on localhost:9966 with LiveReload
budo test --live
pushing to GitHub #
The next “tedious step” in the process of creating new modules is to push your module to GitHub. For this you can use the ghrepo tool, which pushes your folder to GitHub and pulls some details from your package.json
.
#install tool globally first time around
npm install ghrepo -g
#push current folder to a new GitHub repo
ghrepo -m "first commit"
more aliases #
Two other common tasks worth automating is a readme update, and publishing an npm patch.
You can add these to .bash_profile
to get them when you next login to terminal. Shell aliases are another way of automating tasks you find yourself repeating a lot.
alias gitreadme='git add README.md; git commit -m "udpating readme"; git push'
alias npmpatch='npm version patch;npm publish;git push;git push --tags'
further thoughts #
Hopefully we can continue to build more high-level tools that integrate all of these automations, improving efficiency and reducing human error.
To take the automation a step further, module tools could be integrated into an IDE, acting on a source file or even single function. Essentially it would “rip it out” of the application code, pushing it to its own npm folder and repo, and auto-document the readme based on code comments. Then, it would npm install
the modularized version in place of where it was previously taken out.