Reference for How to Write an Open Source JavaScript Library
The purpose of this document is to serve as a reference for:
How to Write an Open Source JavaScript Library course by Kent C. Dodds
Watch the series at egghead.io, if you haven't.
- Introduction to How to Write an Open Source JavaScript Library
- Setting up GitHub
- Configuring npm and creating a package.json
- Creating the library and adding dependencies
- Pushing to GitHub
- Publishing to npm
- Releasing a version to GitHub
- Releasing a new version to npm
- Publishing a beta version
- Setting up Unit Testing with Mocha and Chai
- Unit Testing with Mocha and Chai
- Automating Releases with semantic-release
- Writing conventional commits with commitizen
- Committing a new feature with commitizen
- Automatically Releasing with TravisCI
- Automatically running tests before commits with ghooks
- Adding code coverage recording with Istanbul
- Adding code coverage checking
- Add code coverage reporting
- Adding badges to your README
- Adding ES6 Support
- Adding ES6 Support to Tests using Mocha and Babel
- Limit Built Branches on Travis
- Add a browser build to an npm module
Direct link to the video tutorial
-
micro libraries
- pros
- small enough to reason about the code
- easy to test as there is less code
- easy to reuse via
npm install
- cons
- managing dependencies as there could be too many
- pros
-
objective of the course / learn to
- create a Git repository
- host it on GitHub
- create the library
- publish it to npm
- create a full test suite for it using
- karma
- mocha
- chai
- set up continuous integration
- add ES6 or ES2015 using Babel
- integrate webpack
- distribute this as both browser and node consumable
Direct link to the video tutorial
- create a GitHub account, if you don't have one
- sign in to your account and create a new repository
- follow the instructions displayed after creating the repository, to push your code to that repository
- that's all! GitHub setup is complete
Direct link to the video tutorial
- install node if not already installed
- configure npm locally to make publishing a little easier, for example
$ npm set init-author-name "Sarbbottam Bandyopadhyay"$ npm set init-author-url "https://sarbbottam.github.io/"$ npm set init-author-email "sarbbottam@gmail.com"$ npm set init-license "MIT"
- these will be used as defaults values during
npm init - verify configuration
$ cat ~/.npmrc
- refer https://docs.npmjs.com/misc/config for more information
- recommended setting
save-exactproperty, it tellsnpmto use the exact version of the packages, rather than a version range, while saving dependency to package.json.- it safeguards when semver is not followed properly or there's a mistake in a release.
- create a npm account, if you don't have one at npmjs.com
$ npm add-user, to add your account- enter username, password, and email when prompted
- it will create your
auth tokenand add it to~/.npmrc $ npm initwill prompt for desired information and createpackage.jsonat the end$ npm init --yeswill create apackage.json, with the defaults, with out prompting
Direct link to the video tutorial
- create the
mainfile - install required dependencies
- use
-Sor--saveto save it asdependencyatpackage.json - use
-Dor--save-devto save it asdevDependencyatpackage.json
- use
- create the functionality
Direct link to the video tutorial
- create a
.gitignoreat therootof the project, to list all the ignored files and directories $ git add <file-name>to stage the changes- alternatively
$ git add --allto stage all the changes
- alternatively
$ git committo commit the changes$ git push origin <repo-name>to push the changes to GitHub(origin)$ git remote -vwill display all the availableremoteand their correspondingurl
Direct link to the video tutorial
$ npm add-user, if you have not already- add
package.json/filesto whitelist the set of files to be published - you can also add
.npmignorefile to ignore files/directories, that might fall under from whitelist $ npm version <patch|minor|major>, if you have already published to npmpatchfor bug fixminorfor new featuremajorfor breaking changes
npm packornpm linkto validate the module to be publish$ npm publish- verify the released package at
npm.im/<package-name>
Direct link to the video tutorial
- add a version tag to git repository
- to associate the version released at npm to the corresponding code
tagin git, points to a specific commit$ git tag <version><version>released to npm
$ git push --tags- GitHub will consider the tag as release and will make it available under
releasestab
- GitHub will consider the tag as release and will make it available under
- draft new release
- fill out the release form with the tag version
Direct link to the video tutorial
- make necessary updates
- update the
package.json/version$ npm version <patch|minor|major>patchfor bug fixminorfor new featuremajorfor breaking changes
committhe changestagthe commit.- push changes to GitHub
- push the tags to GitHub
$ npm publish
Direct link to the video tutorial
- make changes
- manually update the package version in
package.json- add
-beta.0to the end of the version
- add
$ git checkout -b <branch-name>for the beta version$ git tag <packge-version-beta.0>$ git push origin <branch-name>$ git push --tags$ npm publish --tag beta- verify published versions
$ npm info
Direct link to the video tutorial
-
$ npm i -D mocha chai, to install and add them todevDependencies -
create a test file
require(chai)requirethe file to be tested
var expect = require('chai').expect; var functionality = required('./path/to/index.js'); describe('functionality', function() { it('should validate the functionality', function() { expect(true).to.be.true; }); });
-
update
package.json/script.test{"scripts": { "test": "mocha path/to/test/file" } }- add
-wto watch for changes
-
$ npm testto run test
Direct link to the video tutorial
- use the
globaldescribefunction anditfunction to describe the tests and what they should do - validate functionalities by assertions using
expect
Direct link to the video tutorial
semantic-releaseautomates the releasing and frees you from redundant manual steps.$ npm i -g semantic-release-clito installsemantic-release-cliglobally$ semantic-release setup- it will take you through the interactive prompt
- it will create a
travis.ymlif the CI system chosen, is travis. - it will update
package.json/scriptw.r.trelease - it will remove the
versionfrompackage.json- as the version will be determined dynamically from the commit messages
- this
scriptwill be executed onsuccess - update
travis.ymlto run tests prior releasing - update the
package.json/versionto0.0.0-sematically-released, to avoidnpmwarning
Direct link to the video tutorial
- commit message convention
$ npm i -D commitizen cz-conventional-changelog- install
commitizenglobally or add./node_modules/binto systemPATHto usegit czinstead ofgit commit - alternatively you could use
npm scripts,{"scripts": { "commit": "git-cz" } }
- install
- configure
commitizenvia{config": { "commitizen": { "path": "cz-conventional-changelog" } } }
Direct link to the video tutorial
- make changes to
sourceandtest - use
commitizento commit with conventional message - push the changes to GitHub
Direct link to the video tutorial
- travis build is automatically setup by semantic-release
- if for some reason it is not enabled, manually sync github repo and enable travis build at
https://travis-ci.org/profile/<user-name>
- if for some reason it is not enabled, manually sync github repo and enable travis build at
- if the build is successful, travis will run
semantic-release - depending on the commit messages,
semantic-releasewould- push a new version to npm
- push a new tag and release to github along with change history since the previous version
Direct link to the video tutorial
$ npm i -D ghooksto install and add it topackage.json/devDependencies- configure
ghooksvia the{"config": {"ghooks": { "hook-name": "command-to-execute" } } }
Direct link to the video tutorial
$ npm i istanbul- update
package.json/script.test{"scripts": { "test": "istanbul cover -x test-file-name-pattern _mocha -- path/to/test/file -R spec" } }
$ npm testwill run the test and generate coverage information atcoverage/folder- add
coverageto.gitignorefile
Direct link to the video tutorial
- create a script called
check-coverageto verify coverage for statements, branches, functions, and lines.{"scripts": { "check-coverage": "istanbul check-coverage --statement 100 --branches 100 --function 100 --lines 100" } }
- add
npm run check-coveragetotravis/script - you can also add it to
git hooks{"config": {"ghooks": { "pre-commit": "npm test && npm run check-coverage" } } }
Direct link to the video tutorial
- signup for codecov.io
$ npm i codecov.io -D- create a script called
report-coverageto report coverage to codecov.io.{"scripts": { "report-coverage": "cat ./coverage/lcov.info | codecov" } }
- add
npm run report-coveragetotravis/after_success - after successful build the reports will be pushed to
codecov.io/github/<user-name/organization-name>/<repo-name> - check out codecov browser extension
Direct link to the video tutorial
- check out shields.io
- add badges via
[](link to the service)- for example:
[](https://travis-ci.org/<user-name/organization-name>/<repo-name>)
- for example:
- you can also pass the
stylequery param to customize the style of the badgehttps://img.shields.io/...svg?style=flat-square
Direct link to the video tutorial
- need a transpiler to write code with latest JavaScript specs
- use babel
$ npm i -D babel-clito install and add it topackage.json/devDependencies- create a script called
buildto transpile ES6/ES2015 code to ES5{"scripts": { "build": "babel --out-dir dist src" } }- you can use
-dinstead of--out-dir - use
--copy-filesto copy dependencies{"scripts": { "build": "babel --copy-files --out-dir dist src" } }
- checkout babel/setup/cli for further details
- add a script called
prebuildto clean thedistdirectory prior building{"scripts": { "prebuild": "rimraf dist" } }$ npm i -D rimrafto install and add it topackage.json/devDependencies
- install desired babel presets/plugin and add it to
package.json/devDependencies$ npm i -D babel-preset-es2015$ npm i -D babel-preset-stage-2- checkout babel/pluglin for further details
- create babel config
- either in a
.babelrcfile or inpackage.json/babel .babelrc-$ echo '{ "presets": ["es2015", "stage-2] }' > .babelrcpackage.json-{ "babel" : { "presets": ["es2015", "stage-2] } }
- either in a
$ npm run buildwill create the transpiled code indistfolder- update
package.json/mainto referdist - add
npm run buildtotravis.yml/script - add
dist/to.gitignore
Direct link to the video tutorial
npm i -D babel-registerto install and add it topackage.json/devDependencies- pass
babel-rgisteras the compiler tomochaand updatepackage.json/scripts.test- `{"scripts": { "test": "mocha path/to/test/file --compilers js:babel-register" } }``
$ npm i -d nycto install and add it topackage.json/devDependencies- add a script called
cover- `{"scripts": { "cover": "nyc npm test" } }``
- update
ghookandtravis/scriptrunnpm run coverinstead ofnpm test - replace
istanbulwithnycatpackage.json/scripts.check-coverage{"scripts": { "check-coverage": "nyc check-coverage --statement 100 --branches 100 --function 100 --lines 100" } }
- add
.nyc_outputto.gitignore
Direct link to the video tutorial
- add
branchestotravis.yml
branches
- only
- masteronlyfor whitelisting andexcludefor blacklistingbranch-name(master) could also be aregex- travis will continue to build for pull requests
Direct link to the video tutorial
$ npm i -D webpack- create
webpack.config.babel.js- for example, checkout getting-started/#config-file
- add
libraryTarget: 'umd'tooutput - add
library: <library-name>tooutput - add
devtool: 'source-map'to main config - install
loaders$ npm i -D babel-loader
- rename the current
package.json/script.buildtopackage.json/script.build:main - add
"build:umd": "webpack --output-filename <output-file-name>.umd.js"topackage.json/script - add
"build:umd:min": "webpack --output-filename <output-file-name>.umd.min.js" -ptopackage.json/script-pfor production build, minify the code
"build": "build:main && build:umd && build:umd:min"topackage.json/script- alternatively
$ npm i -D npm-run-all"build": "npm-run-all build:*"topackage.json/script
- update
readmeto point tohttps://unpkg.com/<package-name>@<version>/path/to/umd/file