Loosely Coupled Web App Skeleton
This is how I generally start small webapps - with a basic structure and file layout, nothing too complex. I've done this 4 or 5 times lately, each time growing the structure a bit, and in the interests of avoiding repetition, I thought I'd save the definitive app skeleton for me (and others!) to use as a starting point.
Naming this sort of thing is hard - I chose "loosely coupled" as that's the main philosophical deviation from most webapp samples - I don't want html generated on the server and manipulated on a client a-la Rails - I want to use the server to handle data, the client to render the data, and keep them relatively separate.
I'm also focused on new browsers - supporting what is loosely termed "html5 and css3" - older browsers may work, but they'll get a big red warning message. If I'm writing a small webapp, I can reasonably assume my audience have a new browser.
See also Yet Another Mongo Browser (yamb) which I built to drive-out the skeleton features - it is likely to deviate from the basic skeleton fairly quickly, but is another point of reference. (not yet on github, will be there soon)
- ease of development
- ease of comprehension
- ease of testing
- loose coupling, so I can change clients and servers easily
- avoid complex frameworks! There are lots of frameworks that offer some or all of what I'm doing, but: ** they tend to dominate your app, so you can't switch easily ** which framework will "win" is a bit of a lucky dip - don't want to be tied to an unused framework ** they get in the way of understanding how the technology works ** they add a pile of effort to support old browsers, I'm happy to ignore them
- clear delineation of state management (see below)
- tend towards static html to make offline apps easier in the future
- use the power of the shiny new web technologies available
- respect YAGNI - don't spend effort supporting things you might need some day. If you are building an enterprise app that definitely needs the stuff below, don't use this skeleton, use Rails or the like.
There are lots of places a web app can store state - here's my philosophy: (in rough order from permanent to transient)
- long-term storage and anything security-critical should live on the server: ** global permanent state is in a server-side database. For some apps, this won't be needed! ** financial stuff, private stuff (except for temporary private stuff) and external APIs need (usually) to come from the server also
What isn't handled
- old browsers - ie8 should be OK (though not heavily tested), the rest are out of scope
- databases - just because everyone has their favourite, and it should be pretty easy to put your own favourite behind the server's json APIs
- REST - you can do restful json APIs by hand, I just haven't built any here. Or you could use Rails.
- communications between client and server are mostly json over http
- the server logic is in ruby via sinatra
- modern web features are detected via modernizr.js
- css is built at compile-time from scss via sass
- precompiling of scss/coffeescript is separate from the app - it's done via command-line scripts (see watch_all.sh)
- Sinatra is used for gluing everything together
- Bundler for handling Ruby gem dependencies
- Web pages are static html and resources (may add option one day to build from templates at compile-time)
- I'm using MongoDb via MongMatic as a database - initially I used the file system, but it's actually simpler to use a database it shouldn't be too hard to substitute any other database - this is just a sample. And MongoMatic is the simplest driver!
The basic architecture, front-to-back, is:
- web pages are static html
- the view layer is built using jquery plus several plugins: -- jquery.bbq is used to manage url hash state -- mustache.js is used for view templates -- probably more things to come here
- anything dynamic needed from the server is fetched asynchronously via json-over-http calls
- for future offline application building, try to handle the situation where no server is available gracefully
- i.e. cache data in browser storage. This also makes offline apps a possiblity. See [http://diveintohtml5.org/storage.html]
- it also lets you run without a database at all for simple apps
What about sammy.js?
see separate TODO.md file