Bootstrapping a JavaScript Library July 27th, 2017

I felt compelled to write this because I’ve read many experienced programmers complain about the quality/quantity of npm packages in ways that are not helpful. Instead of providing a solution to the problem, this discourages new library authors to get started and this is unfair for the whole community: Imagine how many good packages we are losing! Imagine how many potential OSS collaborators we lost because they are worried about screwing up!

If you want to write your first JavaScript library, please don’t be afraid, in this post I will try to walk you through the process.

Before starting, I’d like to make clear that the main rule governing this guide is simplicity.

Writing and publishing a node package should be a painless process, but It’s possible to go overboard with all the tools available to enhance your workflow. While these tools are extremely helpful, they slow you down at the beginning.

The premise is to start small, and add tools as you need them.

You’ll need to have node.js, an updated version of npm and Git. At the time of this writing I’m using:

node.js v8.2.1

npm v5.3.0

All the code is contained in a single folder:

+-- mylib | +-- index . js | +-- test . js | +-- // other files

The index.js file is the entry point of your application, this is what the consumers of your library get when they require() / import it.

file is the entry point of your application, this is what the consumers of your library get when they / it. The test.js file contains your tests.

file contains your tests. There are other files lying around, all related to the configuration and documentation of your project.

note: As your project grows in complexity you may want to organize the code a bit differently. In that case, the convention is to create a folder called src or lib to contain your multiple source files, and a folder named test for your tests.

For now, go ahead and create a folder to contain your project along with the index.js and test.js files.

Every project has a package.json file, which contains metadata related to the project that is used by npm in order to identify the project as well as handle the project’s dependencies; npm comes with a handy command ( npm init ) to help you generate your package.json in an interactive way.

When running the command, you’ll be prompted to fill a couple of values that describe the project. Besides the basic stuff (package name, author, etc), there are two things to look at:

Try to be thoughtful about the versioning of the package, when possible always try to follow semantic versioning.

The license under which you’re making your package available. Jeff Atwood has a good post on the subject. The MIT license is a good option.

For now, leave the test command and git repository entries empty, you are going to fill them later. This is what initializing a project with npm init looks like:

§ npm init This utility walks you through creating a package.json [ ... ] package name: ( mylib ) version: ( 1.0.0 ) 0.1.0 description: This is a short description of my library! entry point: ( index.js ) test command: git repository: keywords: relevant, keywords, here author: Roberto Dip license: ( ISC ) MIT

If everything went right you should have a package.json file at the root of the project.

If you are not sure what version control is or why you need it for your project, please read this tutorial.

Version control is intended for files that people edit. Generated files should not be committed to version control. For example, do not commit binary files that result from compilation, such as .o files or .class files. Also do not commit .pdf files that are generated from a text formatting application; as a rule, you should only commit the source files from which the .pdf files are generated.

Michael Ernst, Version control concepts and best practices





You tell Git to ignore certain files in the project by creating a file called .gitignore . This file contains series of patterns letting Git know which files or folders you don’t want to track.

There are multiple templates out there if you’re lazy to type, but for now, this is more than enough:

# Temporary files created by OSX *.DS_Store # Files related to development node_modules

Since you have done progress, it is a good idea to start tracking your changes. First, init your repository:

§ git init Initialized empty Git repository in projects/mylib/.git/

Now add and commit your files:

§ git add . § git commit -m "Initial commit" [ master ( root-commit ) 88b12fb ] Initial commit 2 files changed, 18 insertions ( + ) create mode 100644 .gitignore create mode 100644 package.json

To set up your test suite, you need:

A library to perform assertions. At least for now, the built-in assert is more than enough.

is more than enough. A tool to run and report assertions. I like the simplicity of mocha

note: If in the future your tests grow in complexity, you can switch to any of the magnificent test libraries that JavaScript has.

The only thing you need to do is to install it via npm:

§ npm install --save-dev mocha

To make your life easier, you can run tell npm how to run your tests when you type the npm test command by filling up the test script in your package.json :

"scripts" : { "test" : "mocha" }

note: There is no black magic here, the scripts object allows you to define arbitrary commands with npm run <command> , since the test command is used so frequently, npm allows you to omit run and call the test command directly.

In your test.js file:

// Require the assertion library const assert = require ( 'assert' ) // Require you library const mylib = require ( '.' ) // Describe you library describe ( 'MyLib' , function () { describe ( '#hello()' , function () { it ( 'should return a string representing a greeting' , function () { assert . equal ( mylib . hello (), "Hello!" ) }) }) })

And now, run the test with the command that you have previously defined:

§ npm test

If everything is right, the test fails (what a strange thing to say). This is because your library needs to export a hello() method. Open index.js and define it:

module . exports = { hello () { return 'Hello!' } }

And now the tests pass. The important thing to note here is the fact that you can easily require and invoke your library’s methods, allowing you to test different outputs. It is always a good idea to cover as many edges as you can, this will make your code more solid in the long term, and will make you more confident when making future changes.

As you have done more progress, you should commit those changes:

§ git add . § git commit

tip: it’s not always a good idea to git add . and git commit right next, I encourage you to check safer alternatives like adding git diff and git add -p to the mix.

In the README you let the world know what your project does, how to contribute, how to use it, and any additional information that you want your future contributors to know. A Beginner’s Guide to Creating a README is a good source to learn how a good README looks like.

While you have the freedom to write it in any format, the standard format is markdown. If you’re having a hard time with the syntax, here is a tutorial and here is a complete reference.

tip: dillinger.io is an online markdown editor that lets you preview what are you editing in real time.

note: some project files are named with UPPERCASE letters. This is an old convention that I’ve decided to stick with, the rationale is that makes the files easier to find for somebody new in the project.

Once you have a README.md file, don’t forget to commit:

§ git add README.md § git commit -m "Add a README"

As soon as people start using your package they will find bugs, improvements, new features, etc. (that’s the beauty of open source software). So, it’s a good idea to make your code public to the world, allowing other people to contribute.

You can do this through Git, publishing your repository in a hosted git server like GitHub, GitLab or Bitbucket. It doesn’t really matter where the project is hosted, you can always switch later on.

In order to publish the source you need to:

Create an account in any of the services mentioned above. Create a repository.

Grab the URL of your repository and push your changes.

§ git remote add origin [ your-url-here ] § git push origin master

And since you have your repository URL at hand, fill the git entry in your package.json :

{ "git" : "[your-url-here]" }

While publishing sounds scary, the process boils down to:

Login ( npm login ) or register ( npm adduser ) as npm user. Run npm publish to publish your package. Enjoy!

There are more detailed instructions at the npm docs.

The idea of this guide is to get you started developing your package. As for distribution is concerned, the process may vary a little based on which environments you want to support (node.js, the browser or both). By following this guide your package will be ready to run on node.js or the browser (depending on how you write your code). If you want to support both environments check out these resources, and if you still have questions feel free to reach me on Twitter or email.