A guide to publishing JavaScript open source projects

So you’ve just completed development of your first JavaScript library, and you think it could help the rest of the world. You’ve heard people discuss the “open source movement” or “GitHub profiles,” but you’re still a novice at this whole sharing software thing.

Maybe you’re still in school and you want to start building an online portfolio. Or maybe you’ve started working for a company like Conductor, which encourages its developers to contribute back to the open source community (see Hoard and Kangaroo). This post will bring you up to speed on the tools and technologies you can use to publish a trustworthy, open source JavaScript library.

There are several important steps you need to take to go from having source code on your computer to having other people trust and use your library in their own projects. This post is organized around that process.

For this exercise, you’ll be looking at backbone.freeze, a simple library I wrote to support immutable collections to Backbone.js. I’m assuming that you have a local version of your library, and that the code is in a place where it’s ready to publish.

The files of the library as they are at the beginning

The files of the library as they are at the beginning

Hosting (or, putting the “source” in “open source projects”)

The first step toward getting people to use your code is to, well, make your code available online! The popular location to host code these days is GitHub, so this guide will use that, but you can use whatever site you’re comfortable with.

Getting your code online (or, sharing is caring)

If you don’t already have a GitHub profile, take a break from this post to create one. Got one? Good! Now create a new repository.

Our nice clean new repo

Our nice clean new repo

Now get your code up to GitHub. This post assumes a familiarity with git (or another version control system). If you’re not sure how to do this, check out this guide.

At this point you should have a nice repository full of code you’ve written. Pat yourself on the back for putting your first open source project up. While you’re at it, this is a good time to flesh out your README.md, so people can tell what your project does.

Repository in initial state

Repository in initial state

Licensing (or, giving people permission to use your code)

When you decide to make your code available online, one question you’ll need to answer is, “How are other people allowed to use this?” Further down in this post, you’ll actually add a license to the project. However, now’s a good time to start thinking about it. For more information on licenses, check out this site. I chose the MIT license for backbone.freeze because it’s very permissive, and because it’s very popular for JavaScript projects hosted on GitHub – which means that other JavaScript developers will have no trouble understanding what they can and can’t do with my code.

Adhering to community standards (or, making a project people will actually use)

Imagine you’re Mr./Ms. Innocent JavaScript Programmer, and that you stumble across this repository. You think to yourself, “Hey, this fills a need I have!” As a member of the JavaScript open source community, you know there are certain standards of quality for open source projects. You’re unlikely to use this code unless it conforms to those standards…

So let’s get your code up to those standards!

Two standards that are particularly relevant to the JavaScript community are dependency management and testing.

Dependency management

 

When your project depends on external libraries or modules, you need a simple way to manage those dependencies. Of course, you could simply copy and paste the source code of another library into the source code of your project, but that makes it hard to deal with changing versions and making sure that your dependencies in turn come with all of their dependencies. That’s where a dependency manager can make your life much easier. It allows your users to call ‘install [library]’ to pull down all the dependencies of the latest version of your library or any other library their code depends on.

In JavaScript, one popular dependency manager is npm. This post will use npm as the dependency management layer, but you can use any other you feel comfortable with.

If you don’t have npm, take a moment to install it. (Instructions here.)

First, you’ll need to set up a new npm project using the command ‘npm init‘. Make your best guess at the options, with the knowledge that you will likely change some of them later.
npm init
If you take a look at the configuration options for backbone.freeze, you’ll see two important things. The first is the license. Remember those license considerations I asked you to think about above? This is the place to fill that in.

Also, you’ll notice that there’s a test command. You can ignore that for now, or just put in “gulp test” – I’ll explain what that means in a moment.

Now you’re ready to move on to tests.

Testing

 

Tests are an easy way for a user to see how your library works in practice, and be confident that your code does what you claim it does, even for edge cases. So let’s write some tests for your plugin!

Installing packages

 

First, though, you’ll need to set up the tooling you’re going to use to write the tests. This tutorial will use the following:

Now that you’ve got npm, you’re ready to install them.

npm install --save-dev mocha chai

(Mocha is a JavaScript testing framework. Chai is a JavaScript expectation library that will be useful for the tests.)

Setup

 

Before things get too cluttered in your directory (and between the new package.json file and the node_modules directory, it’s probably feeling a little packed) it’s time to follow the standard convention and move your actual source code into a directory called ‘src’.

In addition, you’re going to use another little extra bit of organizational magic, and create a directory called ‘spec’, into which you will carefully place all your tests.

To ensure that all your tests have Chai available to them, you need to create a file called “setup.js” in your spec directory. In that file, you need to set up Chai for expectations.

You can verify that all the above worked by typing ‘mocha “spec/*.js”‘ and seeing a successful test run (with 0 tests).
08 mocha test

Write all the tests!!!

 

Take a moment to write your tests. They should all go in the spec directory.

If you’ve never written tests before, take a look at the tests for backbone.freeze. I’m just going to grab a cup of coffee while you write those tests…

…All done? Good. Now when you run the ‘npm test’ command again, you should see that all your specs are run – and pass. (If they don’t pass, fix that before moving on!)
09 npm test with tests
Now that you’ve done that, push the new code up to GitHub.

Doing some automation

 

Most JavaScript developers use some form of workflow automation to make the process of writing and running tests a little easier. There are several commonly-used tools for this, but this post will use gulp. You’ll use it for several things in this tutorial, but right now it’ll help kick off the tests. First, install gulp and the gulp mocha plugin.

npm install --save-dev gulp gulp-mocha

You’ll need to add a gulpfile.js to your parent directory that contains the following lines:

That file says it will be looking at a directory named “gulp,” so you’ll need to create it. Inside that directory, create an index.js file, which is the entry point for all JavaScript files executed by gulp. Then create a folder called “tasks” – index.js should reference all the files in that directory so that gulp is aware of them.

Now for the last bit of copy-pasta. Inside your task directory, create a test task that will kick off all your tests for you:

You’ll notice that the test.js gulp task references your spec directory, and loads your setup.js file.

After all this, your directory should look something like:
07 folder structure

Remember the point in the post where I mentioned the presence of “gulp test” in the npm init step? Here’s where that comes in. Open up package.json in your favorite text editor, and make sure it has a snippet that looks like this:

"scripts": {
  "test": "gulp test"
},

This line in your package.json tells npm exactly how to execute your tests.

Here’s a good test to make sure you did everything correctly: from your project’s directory, run ‘npm test’ and make sure you see the same test output you did before.

Continuous integration (or, making sure everyone knows your latest change didn’t break anything)

 

Now that you have a comprehensive test suite, you need a way to assure your users that the new versions you release won’t break any functionality. This is where continuous integration comes in. “Continuous integration” means that the code will be tested continuously. (Or as continuously as the code changes – i.e., on every commit made.)

There are many tools you can use to do this. This post will use a wonderful tool called Travis CI that provides free continuous integration to any public GitHub project.

The first thing you need to do is add a travis-ci configuration file to your repo. This file will tell Travis what language your project is written in. From there, Travis can intuit the command it should run to execute your tests.

Head over to travis-ci.org and link it with your GitHub account. Then navigate to the repository page and click on the top right where it says your name. You should see a list of public repositories on your GitHub account. Slide the slider for your ldibrary to “on.” It may take a little while, but eventually, Travis will run your tests, and let you know that the build is passing. 10 travis passing You’ll probably want to embed the build information in your GitHub page so a potential user can see at a glance that your code is stable and trustworthy. If you click on the image next to your repository name (at the top where it says “build | passing”) you should see a popup. Select “Markdown” and copy the text in that box. You can paste that in your README.md file and push it back up to GitHub. If you did this correctly, your GitHub page should now look like this:

11 travis on github

Note how you can see at a glance that it’s passing all tests

Compatibility (or, making sure everyone can use your library)

 

Now that you’ve published a JavaScript project with reliable tests and continuous integration, you want to make sure everyone can use it. In JavaScript, some people use AMD (RequireJS) to load libraries or modules, and some people use CommonJS (Node.js). And some people bring in every file explicitly with script tags. It’s hard to maintain compatibility with all of these import strategies at once.
Luckily, there’s a library called webpack that makes all of this easy! It ensures that your library is packaged so that it’s usable by everyone, no matter what module system they use (or don’t use, as the case may be). You’re also going to need a tool called “del” to delete files.

npm install --save-dev gulp-webpack del

Here’s how the packaging process works: you’re going to create a directory called “dist” (short for distribution) which is where the “compatibalized” version of your library will live. You’re going to need a gulp task to create that, as well as a gulp task to clean that directory. Let’s start with the clean task.

That wasn’t so bad! You just create a task that deletes the dist folder. Now for the dist job.

Fill in the bracketed sections with the file name of the entry point to the library and the final name of the output file, respectively. You can make sure everything works by running ‘gulp dist’ and ‘gulp clean’ from the command line and checking to see that the folder and file are created and removed.

12 dist clean output

Note how after the dist task there’s a dist folder, and after the clean task it’s gone.

Now your library is ready for widespread use! The only thing left to do is…

Publishing (or, making sure that everyone can get your code)

 

There are two popular ways to obtain a JavaScript library – well, technically three, but you’re going to ignore straight up downloading the .js files from the GitHub page, because that bit is already ready to go: Bower and npm.

Remember the earlier step where you set up your project to work with a dependency manager? Some day soon, Mr./Ms. Innocent JavaScript Programmer will be able to type ‘install [your library]’ into their favorite dependency manager, and it will Just Work!

In these next steps, you’ll be requesting that your code be incorporated into the public repositories of these two commonly-used dependency managers, making it available to all other developers.

Setup

 

Bower and npm each rely on a config file. (npm’s is package.json.) Since you don’t have a Bower config file yet, the first thing you’ll need to do is write a gulp task that generates one for you. “Why?” you may ask. Because you don’t want to have to maintain two different configuration files. Once you’re ready to publish you should be able to run ‘gulp dist’ to prepare all of the artifacts for distribution.

You’ll need to install two more libraries for this.

npm install --save-dev gulp-rename gulp-json-editor

Now you’re ready for this:

Modify the gulp.task line of gulp/tasks/dist.js to include the following section (additions in italics):

gulp.task('dist', ['bower'], function () {

This ensures that the Bower task is invoked whenever dist is run.

Now you need to actually publish your code to these two repositories. First, you’ll need to choose a name for your library that’s not already in use. Search the npm registry and the Bower registry to make sure the one you want isn’t taken. (If it is, you’ll need to change your package.json.)

Before you publish your code, update your documentation to let your users know how to obtain the code. Add this to your README.md (with your library’s name filled in):

#Installing
Freeze is available on npm and Bower as "backbone.freeze"
```
bower install backbone.freeze
OR
npm install backbone.freeze
```

Note that there are conventions around the kinds of packages that get published to npm and Bower. Depending on the code you’re releasing, you may not want to publish to both repositories. For more information about choosing the right dependency management system, check out this StackOverflow post.

npm

 

npm publishing is simple – just set your npm author information:

npm set init.author.name "Your Name"
npm set init.author.email "you@example.com"
npm set init.author.url "http://yourblog.com"
npm adduser

Then type ‘npm publish ./’.

That’s it! You’re officially published on npm!

Bower

 

Publishing a package to Bower is a little more complicated.

First, create a tag in your project’s git repository.

'git tag -a [VERSION] -m "released [VERSION]"'

…where “[VERSION]” is the current version number in your package.json.
Next, push that tag up to GitHub.

'git push origin [VERSION]'

Then register your project with Bower.

'bower register [PACKAGE NAME] [GIT ENDPOINT]'

…where “[PACKAGE NAME]” is the name of your library (for me, it’s “backbone.freeze”) and “[GIT ENDPOINT]” is the url to the .git file on github (for me, it’s “git://github.com/benmanbs/freeze.git”).
Now that your package is registered, whenever you push a new tag to your GitHub remove, it will automatically be updated on Bower.

Last Notes

 

You might benefit from a little script I wrote.

Put these two files in your library’s parent directory: publish.sh, update_version.rb.

The script takes a version type (major, minor, or patch), bumps the version number in your package.json, generates a bower.json and a dist, and publishes to both npm and Bower.

Now that you’ve gone to the trouble to learn all this from scratch, here’s a skeleton project I created that includes the standard framework I described above.

If you have any trouble getting this process working, feel free to email me.

And, if you find yourself needing immutable collections in Backbone, check out backbone.freeze!

About Benjamin Shai

Benjamin Shai is a tech lead at Conductor. When he's not in front of a computer screen, he's getting lost in a good book, playing music, or sporting a bow tie.

Related Posts

4 comments

  1. Another great addition is the use of jscs which checks for code style differences.

  2. The padding on your website on mobile is kind of rediculous. Remove some please. My eyes hurt.