Skip to content

Instantly share code, notes, and snippets.

@mikeal
Last active December 20, 2015 06:18
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeal/6084298 to your computer and use it in GitHub Desktop.
Save mikeal/6084298 to your computer and use it in GitHub Desktop.
Been rather busy....

Because I've been so busy lately I haven't really had a chance to talk about anything I've built or been using, but i've been publishing so many new modules it's worth going back over.

Real quick, Getable is a mobile/desktop ordering and fullfillment application for commercial construction. Think mobile amazon/ebay for large construction jobsites.

First off, everything is realtime, using engine.io with everything but long polling turned off. We tried leaving websockets on but there were some nasty bits that made the connection die and not come back on iPhone which we just couldn't debug in time so we turned it off.

Engine.io is a great module as it just provides a simple duplex stream-like (more on this later) interface that upgrades itself when available. This meant that in order to get some use out of it I had to write a few modules.

eiojson sends JSON messages rather than strings bidirectionally. eioemitter is an event emitter that emits to the other side of the duplex. eiomethods is a new take on RPC. With eiomethods only the server exposes methods and it exports them dynamically, which means that it has to be used in conjunction with eioemitter most of the time. This lets us dynamically expose different methods for different users and to maintain state in closures on the server for each of those connections.

In order to distribute relevant changes to all impacted clients we sit on the CouchDB _changes feed using couchwatch and send the messages to relevant clients with eiorooms.

While all of these realtime modules are built for and tested against engine.io they should work with any duplex stream. None of them actually depend on engine.io and all add functionality to a socket object by mutating it so they should work just as well with anyone who implements as much of the stream interface as engine.io (which isn't a complete implementation but is enough for my needs in this case).

For authentication we use hawk by Eran Hammer (previous author of OAuth and OAuth2) and it is definitely the easiest and most secure authentication I've ever used. Because everything is over a realtime channel we authenticate the channel using authenticateMessage rather than signing the headers.

All of the frontend is built with browserify which has been great. A good portion of our client code is also built for and tested in node.js which is made all that much easier by using the same patterns in the frontend as the backend. In a few cases we bundle a frontend resource seperately from its node.js package, which we do use during client testing in node, which was really painful with relative resources and the declarative features in package.json browserify ships with. Instead, I wrote broquire to dynamically load resources in node but assume they are already available in the global scope on the frontend.

I don't know much about it because I haven't written any of it but we're also using TJ's rework for adding features to CSS and concatenting them together in to a single resource. I prefer adding features we need rather than using a full DSL for CSS.

The backend resources like our dynamically built frontend js, css, and static content are cached indefinitely using jaws and content is invalidated when changed using couchwatch again.

A lot of deployment systems are out there and many of them are quite nice. I'm partial to what substack has been doing but during our beta phase we want continuous deployment for staging and production but without a lot of distribution or parellelism. We want a single process we can keep a good eye on while we work out all the initial bugs and issues. So, I wrote flipover which has a one-to-one relationship with a child process that is "active" and being proxied to. It uses hostproxy for the public facing side, finds a port with getport and lauches a child process on it using childport. Now the "merge" button in GitHub is a deploy button for the staging and master branches.

Because we're generating all our resources dynamically and won't tolerate a build step pre or post deploy we find it best to test/generate the necessary live resources in a new deploy before sending resources to it. flipover allows for a test step and we use webtouch to find and spider all the required resources in html and css for our application before resolving the callback that will flip to the new process.

This week we finally tackled the appcache monster. A very scary and dangerous feature of the offline web it is also somewhat necessary if you want consistently speedy performance on unreliable mobile networks. The safest and most sustainable way I could think of to generate a cache manifest was similar to how we test a new deploy, by spidering the required resources found in html and css, so I used webtouch in a new module called appcached which also includes the combined md5 of every file as a comment which solves a lot of the manifest invalidation problems you get with appache.

None of this would be possible without the immense value available in the node.js ecosytem. In addition to those already mentioned TJ's css-parse and Matthew Mueller's cheerio underly webtouch's spidering. Our entire frontend stack is built on substack's browserify and couldn't exist without it. And async and lodash are peppered throughout our code, just to name a few more.

@bingeboy
Copy link

Dang kid, tearing it up... Thanks for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment