2016-05-25 04:28:20 +09:00
<h1 align="center">choo</h1>
2016-05-10 23:23:33 +07:00
2016-05-25 04:28:20 +09:00
<div align="center">
:steam_locomotive::train::train::train::train::train:
</div>
<div align="center">
2016-05-25 04:45:49 +09:00
<strong>Fun functional programming</strong>
2016-05-25 04:28:20 +09:00
</div>
<div align="center">
2017-03-21 03:00:45 +01:00
A <code>4kb</code> framework for creating sturdy frontend applications
2016-05-25 04:28:20 +09:00
</div>
2016-05-13 12:49:22 +07:00
2016-05-25 04:28:20 +09:00
<br />
2016-05-10 23:23:33 +07:00
2016-05-25 04:28:20 +09:00
<div align="center">
2016-05-25 04:45:49 +09:00
<!-- Stability -->
<a href="https://nodejs.org/api/documentation.html#documentation_stability_index ">
<img src="https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square"
alt="API stability" />
</a>
<!-- NPM version -->
<a href="https://npmjs.org/package/choo">
<img src="https://img.shields.io/npm/v/choo.svg?style=flat-square"
alt="NPM version" />
</a>
<!-- Build Status -->
<a href="https://travis-ci.org/yoshuawuyts/choo">
<img src="https://img.shields.io/travis/yoshuawuyts/choo/master.svg?style=flat-square"
alt="Build Status" />
</a>
<!-- Test Coverage -->
<a href="https://codecov.io/github/yoshuawuyts/choo">
<img src="https://img.shields.io/codecov/c/github/yoshuawuyts/choo/master.svg?style=flat-square"
alt="Test Coverage" />
</a>
2016-06-04 20:11:26 +02:00
<!-- Downloads -->
<a href="https://npmjs.org/package/choo">
<img src="https://img.shields.io/npm/dm/choo.svg?style=flat-square"
alt="Downloads" />
</a>
2016-05-25 04:45:49 +09:00
<!-- Standard -->
2017-03-23 01:51:12 -07:00
<a href="https://standardjs.com">
2016-05-25 04:45:49 +09:00
<img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square"
alt="Standard" />
</a>
2016-05-25 04:28:20 +09:00
</div>
2016-07-03 14:56:24 +02:00
<div align="center">
<h3>
2017-03-21 03:00:45 +01:00
<a href="https://choo.io">
Website
</a>
<span> | </span>
2017-03-21 16:56:33 +01:00
<a href="https://github.com/yoshuawuyts/choo-handbook">
2016-07-03 14:56:24 +02:00
Handbook
</a>
2016-07-10 18:38:27 +02:00
<span> | </span>
2017-03-21 03:00:45 +01:00
<a href="https://github.com/YerkoPalma/awesome-choo">
Ecosystem
</a>
2016-07-10 18:38:27 +02:00
<span> | </span>
2017-03-21 03:00:45 +01:00
<!-- <a href="https://github.com/trainyard/choo-cli"> -->
<!-- CLI -->
<!-- </a> -->
<!-- <span> | </span> -->
2016-07-03 14:56:24 +02:00
<a href="https://github.com/yoshuawuyts/choo/blob/master/.github/CONTRIBUTING.md">
Contributing
</a>
2016-07-10 18:38:27 +02:00
<span> | </span>
<a href="https://webchat.freenode.net/?channels=choo">
Chat
</a>
2016-07-03 14:56:24 +02:00
</h3>
</div>
2016-05-25 04:28:20 +09:00
<div align="center">
<sub>The little framework that could. Built with ❤︎ by
<a href="https://twitter.com/yoshuawuyts">Yoshua Wuyts</a> and
<a href="https://github.com/yoshuawuyts/choo/graphs/contributors">
contributors
</a>
</div>
2017-03-21 03:00:45 +01:00
## Table of Content
- [Features ](#features )
- [Example ](#example )
- [Philosophy ](#philosophy )
- [Optimizations ](#optimizations )
- [FAQ ](#faq )
- [API ](#api )
- [Installation ](#installation )
- [See Also ](#see-also )
- [Support ](#support )
2016-05-21 22:44:03 +09:00
2016-05-10 23:23:33 +07:00
## Features
2017-03-21 03:00:45 +01:00
- __minimal size:__ weighing `4kb` , `choo` is a tiny little framework
- __event based:__ our performant event system makes writing apps easy
- __small api:__ with only 6 methods there's not much to learn
2016-05-10 23:23:33 +07:00
- __minimal tooling:__ built for the cutting edge `browserify` compiler
2016-06-22 10:48:41 +01:00
- __isomorphic:__ renders seamlessly in both Node and browsers
2016-05-10 23:23:33 +07:00
- __very cute:__ choo choo!
2016-07-03 14:56:24 +02:00
## Example
2016-06-01 01:03:25 +02:00
```js
2017-03-25 10:09:23 +01:00
var html = require ( 'choo/html' )
var choo = require ( 'choo' )
2017-03-21 03:00:45 +01:00
2016-12-11 19:35:29 +01:00
var app = choo ()
2017-03-21 03:00:45 +01:00
app . use ( logger )
app . use ( countStore )
app . route ( '/' , mainView )
app . mount ( 'body' )
2016-06-01 01:03:25 +02:00
2017-03-21 03:00:45 +01:00
function mainView ( state , emit ) {
2016-12-11 19:35:29 +01:00
return html `
2017-03-21 03:00:45 +01:00
<body>
<h1>count is ${ state . count } </h1>
<button onclick= ${ onclick } >Increment</button>
</body>
2016-12-11 19:35:29 +01:00
`
2016-05-10 23:23:33 +07:00
2017-03-21 03:00:45 +01:00
function onclick () {
emit ( 'increment' , 1 )
2016-12-11 19:35:29 +01:00
}
}
2016-05-10 23:23:33 +07:00
2017-03-21 03:00:45 +01:00
function logger ( state , emitter ) {
emitter . on ( '*' , function ( messageName , data ) {
console . log ( 'event' , messageName , data )
})
}
2016-12-11 19:35:29 +01:00
2017-03-21 03:00:45 +01:00
function countStore ( state , emitter ) {
state . count = 0
emitter . on ( 'increment' , function ( count ) {
state . count += count
emitter . emit ( 'render' )
})
}
2016-07-03 14:56:24 +02:00
```
2017-03-21 03:00:45 +01:00
Want to see more examples? Check out the [Choo handbook][handbook].
2016-07-03 14:56:24 +02:00
## Philosophy
We believe programming should be fun and light, not stern and stressful. It's
cool to be cute; using serious words without explaining them doesn't make for
better results - if anything it scares people off. We don't want to be scary,
we want to be nice and fun, and then _casually_ be the best choice around.
_Real casually._
We believe frameworks should be disposable, and components recyclable. We don't
2017-04-07 22:21:40 +02:00
want a web where walled gardens jealously compete with one another. By making
the DOM the lowest common denominator, switching from one framework to another
2017-04-07 22:22:47 +02:00
becomes frictionless. `choo` is modest in its design; we don't believe it will
be top of the class forever, so we've made it as easy to toss out as it is to
pick up.
2016-07-03 14:56:24 +02:00
2017-04-07 22:21:40 +02:00
We don't believe that bigger is better. Big APIs, large complexities, long
files - we see them as omens of impending userland complexity. We want everyone
on a team, no matter the size, to fully understand how an application is laid
out. And once an application is built, we want it to be small, performant and
easy to reason about. All of which makes for easy to debug code, better results
and super smiley faces.
2016-07-03 14:56:24 +02:00
2017-03-21 03:00:45 +01:00
## Optimizations
Choo is reasonably fast out of the box. But sometimes you might hit a scenario
where a particular part of the UI slows down the application, and you want to
speed it up. Here are some optimizations that are possible.
2016-05-19 13:26:11 +09:00
2017-03-21 03:00:45 +01:00
### Reordering lists
To be implemented. (See [yoshuawuyts/nanomorph#8 ](https://github.com/yoshuawuyts/nanomorph/issues/8 ))
2016-05-24 05:44:15 +09:00
2017-03-21 03:00:45 +01:00
### Caching DOM elements
Sometimes we want to tell the algorithm to not evaluate certain nodes (and its
children). This can be because we're sure they haven't changed, or perhaps
because another piece of code is managing that part of the DOM tree. To achieve
this `nanomorph` evaluates the `.isSameNode()` method on nodes to determine if
they should be updated or not.
2016-07-05 18:52:51 +02:00
2016-07-20 18:30:19 -07:00
```js
2017-03-21 03:00:45 +01:00
var el = html `<div>node</div>`
2016-12-11 19:35:29 +01:00
2017-03-21 03:00:45 +01:00
// tell nanomorph to not compare the DOM tree if they're both divs
el . isSameNode = function ( target ) {
return ( target && target . nodeName && target . nodeName === 'DIV' )
2016-06-20 23:57:46 -04:00
}
```
2016-12-11 19:35:29 +01:00
2017-03-21 03:00:45 +01:00
### Pruning dependencies
We use the `require('assert')` module from Node core to provide helpful error
messages in development. In production you probably want to strip this using
[unassertify][unassertify].
2016-07-21 21:59:01 +02:00
2017-03-21 03:00:45 +01:00
To convert inlined HTML to valid DOM nodes we use `require('bel')` . This has
overhead during runtime, so for production environments we should unwrap this
using [yo-yoify][yo-yoify].
2016-07-21 21:59:01 +02:00
2017-03-21 03:00:45 +01:00
Setting up browserify transforms can sometimes be a bit of hassle; to make this
more convenient we recommend using [bankai][bankai] with `--optimize` to
compile your assets for production.
2017-02-07 13:59:18 +01:00
2016-05-21 22:44:03 +09:00
## FAQ
2016-05-22 20:54:39 +09:00
### Why is it called choo?
Because I thought it sounded cute. All these programs talk about being
2016-07-03 14:56:24 +02:00
_"performant"_ , _"rigid"_ , _"robust"_ - I like programming to be light, fun and
2016-05-22 20:54:39 +09:00
non-scary. `choo` embraces that.
Also imagine telling some business people you chose to rewrite something
2017-03-21 03:00:45 +01:00
critical for serious bizcorp using a train themed framework.
2016-05-22 20:54:39 +09:00
:steam_locomotive::train::train::train:
2016-07-03 14:56:24 +02:00
### Is it called choo, choo.js or...?
It's called "choo", though we're fine if you call it "choo-choo" or
"chugga-chugga-choo-choo" too. The only time "choo.js" is tolerated is if /
when you shimmy like you're a locomotive.
2016-05-23 14:40:52 +09:00
2016-05-21 21:59:03 +09:00
### Does choo use a virtual-dom?
2017-03-21 03:00:45 +01:00
`choo` uses [nanomorph][nanomorph], which diffs real DOM nodes instead of
virtual nodes. It turns out that [browsers are actually ridiculously good at
dealing with DOM nodes][morphdom-bench], and it has the added benefit of
working with _any_ library that produces valid DOM nodes. So to put a long
answer short: we're using something even better.
2016-05-21 21:59:03 +09:00
2017-03-21 03:00:45 +01:00
### How can I support older browsers?
Template strings aren't supported in all browsers, and parsing them creates
significant overhead. To optimize we recommend running `browserify` with
[yo-yoify][yo-yoify] as a global transform or using [bankai][bankai] directly.
2016-05-24 22:11:21 +09:00
```sh
2017-03-21 03:00:45 +01:00
$ browserify -g yo-yoify
2016-05-24 22:11:21 +09:00
```
2016-05-11 15:26:27 +07:00
2017-03-21 03:00:45 +01:00
### Is choo production ready?
2016-05-22 02:15:33 +09:00
Sure.
2017-03-21 03:00:45 +01:00
## API
This section provides documentation on how each function in `choo` works. It's
intended to be a technical reference. If you're interested in learning choo for
the first time, consider reading through the [handbook][handbook] first
:sparkles:
### `app = choo([opts])`
Initialize a new `choo` instance. `opts` can also contain the following values:
2017-03-29 10:43:42 +02:00
- __opts.history:__ default: `true` . Listen for url changes through the
2017-03-21 03:00:45 +01:00
history API.
- __opts.href:__ default: `true` . Handle all relative `<a
href="<location>"></a>` clicks and call ` emit('render')`
2017-03-29 10:43:42 +02:00
- __opts.timing:__ default: ` true`. Enables calls to the
[window.performance][window-performance] timing API. Timing calls will not
run in browsers that don't support it out of the box. The timing marks are
` choo:renderStart`, ` choo:renderEnd`. The resulting diff is stored as
` choo:render`.
2017-03-21 03:00:45 +01:00
### ` app.use(callback(state, emitter))`
Call a function and pass it a ` state` and ` emitter`. ` emitter` is an instance
of [nanobus](https://github.com/yoshuawuyts/nanobus/). You can listen to
2017-03-31 11:22:59 +02:00
messages by calling ` emitter.on()` and emit messages by calling ` emitter.emit()`.
2017-03-21 03:00:45 +01:00
Choo fires messages when certain events happen:
- __` .on('DOMContentLoaded')`__: when the DOM has succesfully finished loading
- __` .on('render')`__: when the DOM re-renders
- __` .on('pushState')`__: when the history API is triggered
2017-04-11 15:36:27 +03:00
The ` render` event should be emitted (` emitter.emit('render')`) whenever you want the app to re-render the DOM - it won't happen on its own except when you navigate between routes.
The ` pushState` can be emitted to navigate between routes: ` emitted.emit('pushState', '/some/route')`.
2017-05-19 14:20:39 +02:00
Note ` render` will only have an effect once the ` DOMContentLoaded` event has been fired.
2017-04-11 15:36:27 +03:00
2017-03-21 03:00:45 +01:00
### ` app.route(routeName, handler)`
2017-03-21 16:56:33 +01:00
Register a route on the router. Uses [nanorouter][nanorouter] under the hood.
Params can be registered by prepending the routename with ` :routename`, e.g.
` /foo/:bar/:baz`. The value of the param will be saved on ` state.params` (e.g.
` state.params.bar`). Wildcard routes can be registered with ` *`, e.g. ` /foo/*`.
The value of the wildcard will be saved under ` state.params.wildcard`.
Using hashes to delimit routes is supported out of the box (e.g. ` /foo#bar `).
When a hash is found we also check if there's an available anchor on the same
page, and will scroll the screen to the position. Using both hashes in URLs and
anchor links on the page is generally not recommended.
New routes can be triggered through ` emitter.emit('pushState', <routename>)`.
By default we also catch and match all ` <a href="">` clicks against the router.
This can be disabled by setting ` opts.href` to ` false` in the constructor.
2017-04-11 15:36:27 +03:00
Routing via ` pushState` will not work until the ` DOMContentLoaded` event has been fired.
2017-03-21 16:56:33 +01:00
2017-04-13 15:41:09 +01:00
If you need choo to ignore a particular route, you can add ` data-no-routing`
attribute with ` <a href="" data-no-routing>`. This is especially useful for
directing outside the choo app.
2017-03-21 16:56:33 +01:00
Querystrings (` ?foo=bar`) are ignored when matching routes. They should be
extracted from the ` window.location` object on render events, from either a
custom event listener or the matched views.
2017-03-21 03:00:45 +01:00
### ` app.mount(selector)`
2017-03-21 16:56:33 +01:00
Start the application and mount it on the given ` querySelector`. Uses
2017-03-29 02:04:24 -07:00
[nanomount][nanomount] under the hood. This will _replace_ the selector provided
with the tree returned from ` app.start()`. If you want to add the app as a child
to an element, use ` app.start()` to obtain the tree and manually append it.
2017-03-21 03:00:45 +01:00
### ` tree = app.start()`
Start the application. Returns a tree of DOM nodes that can be mounted using
` document.body.appendChild()`.
### ` app.toString(location, [state])`
Render the application to a string. Useful for rendering on the server.
2017-04-03 03:53:17 +02:00
### ` choo/html`
2017-03-21 03:00:45 +01:00
Create DOM nodes from template string literals. Exposes
[bel](https://github.com/shama/bel). Can be optimized using
[yo-yoify][yo-yoify].
2016-06-29 08:06:04 -07:00
2016-05-10 23:23:33 +07:00
## Installation
` ``sh
$ npm install choo
` ``
2016-05-22 20:54:39 +09:00
## See Also
2017-03-21 03:00:45 +01:00
- [bankai](https://github.com/yoshuawuyts/bankai) - streaming asset compiler
2016-05-22 20:54:39 +09:00
- [stack.gl](http://stack.gl/) - open software ecosystem for WebGL
2016-06-26 00:34:00 +02:00
- [yo-yo](https://github.com/maxogden/yo-yo) - tiny library for modular UI
- [bel](https://github.com/shama/bel) - composable DOM elements using template
strings
2016-07-03 14:56:24 +02:00
- [tachyons](https://github.com/tachyons-css/tachyons) - functional CSS for
humans
- [sheetify](https://github.com/stackcss/sheetify) - modular CSS bundler for
` browserify`
2016-05-22 20:54:39 +09:00
2016-08-27 14:28:09 +02:00
## Support
Creating a quality framework takes a lot of time. Unlike others frameworks,
Choo is completely independently funded. We fight for our users. This does mean
however that we also have to spend time working contracts to pay the bills.
This is where you can help: by chipping in you can ensure more time is spent
improving Choo rather than dealing with distractions.
### Sponsors
Become a sponsor and help ensure the development of independent quality
software. You can help us keep the lights on, bellies full and work days sharp
and focused on improving the state of the web. [Become a
sponsor ](https://opencollective.com/choo#sponsor )
<a href="https://opencollective.com/choo/sponsor/0/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/1/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/2/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/3/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/4/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/5/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/6/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/7/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/8/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/9/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/10/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/10/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/11/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/11/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/12/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/13/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/14/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/15/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/16/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/17/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/18/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/19/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/20/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/21/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/22/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/23/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/24/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/25/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/26/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/27/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/28/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/choo/sponsor/29/website" target="_blank"><img src="https://opencollective.com/choo/sponsor/29/avatar.svg"></a>
### Backers
Become a backer, and buy us a coffee (or perhaps lunch?) every month or so.
[Become a backer ](https://opencollective.com/choo#backer )
<a href="https://opencollective.com/choo/backer/0/website" target="_blank"><img src="https://opencollective.com/choo/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/1/website" target="_blank"><img src="https://opencollective.com/choo/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/2/website" target="_blank"><img src="https://opencollective.com/choo/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/3/website" target="_blank"><img src="https://opencollective.com/choo/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/4/website" target="_blank"><img src="https://opencollective.com/choo/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/5/website" target="_blank"><img src="https://opencollective.com/choo/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/6/website" target="_blank"><img src="https://opencollective.com/choo/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/7/website" target="_blank"><img src="https://opencollective.com/choo/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/8/website" target="_blank"><img src="https://opencollective.com/choo/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/9/website" target="_blank"><img src="https://opencollective.com/choo/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/10/website" target="_blank"><img src="https://opencollective.com/choo/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/11/website" target="_blank"><img src="https://opencollective.com/choo/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/12/website" target="_blank"><img src="https://opencollective.com/choo/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/13/website" target="_blank"><img src="https://opencollective.com/choo/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/14/website" target="_blank"><img src="https://opencollective.com/choo/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/15/website" target="_blank"><img src="https://opencollective.com/choo/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/16/website" target="_blank"><img src="https://opencollective.com/choo/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/17/website" target="_blank"><img src="https://opencollective.com/choo/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/18/website" target="_blank"><img src="https://opencollective.com/choo/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/19/website" target="_blank"><img src="https://opencollective.com/choo/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/20/website" target="_blank"><img src="https://opencollective.com/choo/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/21/website" target="_blank"><img src="https://opencollective.com/choo/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/22/website" target="_blank"><img src="https://opencollective.com/choo/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/23/website" target="_blank"><img src="https://opencollective.com/choo/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/24/website" target="_blank"><img src="https://opencollective.com/choo/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/25/website" target="_blank"><img src="https://opencollective.com/choo/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/26/website" target="_blank"><img src="https://opencollective.com/choo/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/27/website" target="_blank"><img src="https://opencollective.com/choo/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/28/website" target="_blank"><img src="https://opencollective.com/choo/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/choo/backer/29/website" target="_blank"><img src="https://opencollective.com/choo/backer/29/avatar.svg"></a>
2016-05-10 23:23:33 +07:00
## License
[MIT ](https://tldrlegal.com/license/mit-license )
2016-12-11 19:35:29 +01:00
[bankai]: https://github.com/yoshuawuyts/bankai
2016-07-03 14:56:24 +02:00
[bel]: https://github.com/shama/bel
2016-09-02 21:02:41 -04:00
[browserify]: https://github.com/substack/node-browserify
2016-10-23 00:16:33 -07:00
[budo]: https://github.com/mattdesl/budo
[es2020]: https://github.com/yoshuawuyts/es2020
2016-07-05 18:52:51 +02:00
[handbook]: https://github.com/yoshuawuyts/choo-handbook
2016-10-23 00:16:33 -07:00
[hyperx]: https://github.com/substack/hyperx
[morphdom-bench]: https://github.com/patrick-steele-idem/morphdom#benchmarks
2017-03-21 03:00:45 +01:00
[nanomorph]: https://github.com/yoshuawuyts/nanomorph
[nanorouter]: https://github.com/yoshuawuyts/nanorouter
2017-03-21 16:56:33 +01:00
[nanomount]: https://github.com/yoshuawuyts/nanomount
2016-10-23 00:16:33 -07:00
[yo-yo]: https://github.com/maxogden/yo-yo
2017-03-21 03:00:45 +01:00
[yo-yoify]: https://github.com/shama/yo-yoify
[unassertify]: https://github.com/unassert-js/unassertify
2017-03-29 10:43:42 +02:00
[window-performance]: https://developer.mozilla.org/en-US/docs/Web/API/Performance