GithubHelp home page GithubHelp logo

emkay / choo Goto Github PK

View Code? Open in Web Editor NEW

This project forked from choojs/choo

0.0 1.0 0.0 507 KB

:steam_locomotive::train::train::train: - sturdy 4kb frontend framework

Home Page: https://choo.io/

License: MIT License

JavaScript 100.00%

choo's Introduction

choo

๐Ÿš‚๐Ÿš‹๐Ÿš‹๐Ÿš‹๐Ÿš‹๐Ÿš‹
Fun functional programming
A 4kb framework for creating sturdy frontend applications

The little framework that could. Built with โค๏ธŽ by Yoshua Wuyts and contributors

Table of Content

Features

  • 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
  • minimal tooling: built for the cutting edge browserify compiler
  • isomorphic: renders seamlessly in both Node and browsers
  • very cute: choo choo!

Example

var html = require('choo/html')
var choo = require('choo')

var app = choo()
app.use(logger)
app.use(countStore)
app.route('/', mainView)
app.mount('body')

function mainView (state, emit) {
  return html`
    <body>
      <h1>count is ${state.count}</h1>
      <button onclick=${onclick}>Increment</button>
    </body>
  `

  function onclick () {
    emit('increment', 1)
  }
}

function logger (state, emitter) {
  emitter.on('*', function (messageName, data) {
    console.log('event', messageName, data)
  })
}

function countStore (state, emitter) {
  state.count = 0
  emitter.on('increment', function (count) {
    state.count += count
    emitter.emit('render')
  })
}

Want to see more examples? Check out the Choo handbook.

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 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 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.

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.

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.

Reordering lists

To be implemented. (See yoshuawuyts/nanomorph#8)

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.

var el = html`<div>node</div>`

// tell nanomorph to not compare the DOM tree if they're both divs
el.isSameNode = function (target) {
  return (target && target.nodeName && target.nodeName === 'DIV')
}

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.

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.

Setting up browserify transforms can sometimes be a bit of hassle; to make this more convenient we recommend using bankai with --optimize to compile your assets for production.

FAQ

Why is it called choo?

Because I thought it sounded cute. All these programs talk about being "performant", "rigid", "robust" - I like programming to be light, fun and non-scary. choo embraces that.

Also imagine telling some business people you chose to rewrite something critical for serious bizcorp using a train themed framework. :steam_locomotive::train::train::train:

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.

Does choo use a virtual-dom?

choo uses nanomorph, which diffs real DOM nodes instead of virtual nodes. It turns out that browsers are actually ridiculously good at dealing with DOM nodes, 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.

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 as a global transform or using bankai directly.

$ browserify -g yo-yoify

Is choo production ready?

Sure.

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 first :sparkles:

app = choo([opts])

Initialize a new choo instance. opts can also contain the following values:

  • opts.history: default: true. Listen for url changes through the history API.
  • opts.href: default: true. Handle all relative <a href="<location>"></a> clicks and call emit('render')
  • opts.timing: default: true. Enables calls to the 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.

app.use(callback(state, emitter))

Call a function and pass it a state and emitter. emitter is an instance of nanobus. You can listen to messages by calling emitter.on() and emit messages by calling emitter.emit().

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

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'). You can emit replaceState which will overwrite the current entry in the browser history, but be very careful as this removes the option of navigating back!

Note render will only have an effect once the DOMContentLoaded event has been fired.

app.route(routeName, handler)

Register a route on the router. Uses 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. Routing via pushState will not work until the DOMContentLoaded event has been fired.

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.

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.

app.mount(selector)

Start the application and mount it on the given querySelector. Uses 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.

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.

choo/html

Create DOM nodes from template string literals. Exposes bel. Can be optimized using yo-yoify.

Installation

$ npm install choo

See Also

  • bankai - streaming asset compiler
  • stack.gl - open software ecosystem for WebGL
  • yo-yo - tiny library for modular UI
  • bel - composable DOM elements using template strings
  • tachyons - functional CSS for humans
  • sheetify - modular CSS bundler for browserify

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

Backers

Become a backer, and buy us a coffee (or perhaps lunch?) every month or so. Become a backer

License

MIT

choo's People

Contributors

angelogulina avatar bendrucker avatar clkao avatar dmotz avatar emilbayes avatar fyrkant avatar greenkeeperio-bot avatar gsf avatar haroenv avatar latentflip avatar lchski avatar mafintosh avatar markmontymark avatar martinvd avatar mattijsbliek avatar mattmcfarland avatar mickaelandrieu avatar okuryu avatar paulsonnentag avatar perguth avatar reminyborg avatar ruudud avatar sethvincent avatar tgfjt avatar timwis avatar toddself avatar velds avatar yoshuawuyts avatar zeke avatar zigomir avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.