Isomorphic Javascript Libraries

If you are a frontend (fullstack) developer, you know how painful it is to create a reusable javascript library, which can be used in most projects.

The major pain is a set of module bundlers and loaders (webpack, requirejs, browserify, jspm...), a set of module formats (commonjs, ES6 modules, amd, ...) and a set of workflows (adding libraries using <script> tag)...

Towards isomorphic js packages

So, I have decided to spent some time and create a project setup, which will allow to start hacking some javascript without going crazy.

Main goals are:

  1. Distinct and explicit builds for different module formats
  2. Sane default settings with these usage patterns in mind:
    • bower + standalone include using <script> tag
    • bower + AMD
    • npm + browserify + commonjs
    • npm + NodeJs + commonjs
    • jspm + systemjs + es6
    • requirejs support
    • webpack support
  3. Tests, coverage and CI integrated
  4. Code style checks integrated

Seamless workflow

To make life easier I have also created a project generator template for loom utility.

This thing helps to create a library on github in no time.

I've generalized the workflow like that:

  1. Generate the project setup
  2. Write ES6 code with ES6 modules in mind
  3. Write tests
  4. Commit all the stuff
  5. Bump the version (automated tools preferred, see mversion)
  6. Push it to github
  7. Enable Travis-CI and Coveralls integration
  8. Relax and enjoy the result :)

Under the cover

Package managers

bower

  • separate module file (bower.json)
  • flat structure (dependency hell)
  • main cannot be specified (useless)
  • can't be used with iso apps
  • format agnostic (commonjs/amd)

jspm

  • uses package.json
  • main can be specified
  • can't be used with iso apps
  • separate format (systemjs)

npm

  • uses package.json
  • hierarchical structure (scoped dependencies)
  • main can be specified
  • can be used for iso apps
  • separate format (commonjs)

Bundlers

browserify

  • can remap dependencies, but with plugins (tedious)
  • commonjs-friendly (amd through plugins)

requirejs

  • can remap dependencies (see paths and packages)
  • amd-friendly (commonjs through shimming)

webpack

  • can remap dependencies (see aliases)
  • amd/commonjs/es6 friendly

systemjs

  • can remap dependencies (see map)
  • es6/amd/commonjs friendly

global

  • requires global (UMD)
  • requires standalone builds
    • Very Bad Thing and But Inevitable Evil

ES6 Modules and code

If you have a thoughtful look at those properties and keep in mind, that almost all of them will become obsolete in some time, you will understand that it is a good idea to start writing ES6 code right now.

Distinct builds

To make the installation process easier, you can make an explicit build for different module systems, but those builds should be automated.
This is a good use case for 6to5 and webpack.

Tests and coverage

If you keep in mind those programmers, who have a real life, you want to make testing and code style checks automated and easy.

Also, you may want to have a code coverage available. You may need it for reporting, or just to play safe. Sometimes those numbers are even useful :)

Commit protection

I prefer to stay safe from corrupting the build and repo state, so I have added a git hook, which makes sure that:

  1. All builds are created and ready to be committed
  2. Code is clean and adheres to style guide
  3. You have an actual style guide :)
  4. If code is not clean, it should be autocorrected