Yet Another Web App

Years now, it seems, I’ve been building countless web apps using mostly the same technologies and some variations. Time to make an official platform?

Stack

  1. Socket.IO (Express.IO or Zappa?)
  2. LevelDB
  3. CoffeeScript
  4. CoffeeCup and Stylus
  5. Cake…
  6. Git for deployment
  7. jQuery…
  8. Responsive web design, Page…

Socket.IO

  1. It just works. Performance is everything dreamed of. Obviously, some annoyances and complications, too: API, debugging… Nu, still better than WebRTC, RPCs, and idiotic MVC trend.
  2. WebSockets (WS): state of the art technology of web apps. See Reactive Manifesto. Many (Meteor, React…), though, needlessly encumber development by hiding WS behind restrictive, obfuscated “data binding” or pubsub APIs. SIO rulz!
  3. Each C/S interaction assigned a message and (optional) response. Whole range of app/domain-specific customization exposed, and API is trivial: emit(), on(). With Express.IO:
    # Server side:
    app.io.route 'delete',(req)->
    	db.del req.data,(err)->
    		req.io.respond not err
    
    # Client side:
    sio.emit 'delete',id,(r)->if r then p=null
    

    And even nicer with Zappa:

    @on 'picked word':->
    	[i,w]=@data
    	@emit 'end round'

    (But having to sometimes use “=>” sucks!)

  4. I love it that SIO reconnects automatically…
  5. Sessions?!
  6. Broadcasting…

LevelDB

  1. As I’ve written before, it solves the “nobody reads Knuth anymore” problem. Do the simplest thing that could possibly work — persistence. The rest is all data structures and algorithms — domain/application specific! And everything can be done in O(1) complexity. Nu, mostly.
  2. Open it. It’s in-process, locked, no silly OS level IPC, or worse, networking! — just plain old efficient FS.
    db=level 'data'
    
  3. Saving, synchronously:
    app.post '/upload',(req,res)->
    	#...
    	db.put k,v,(err)->
    		if err then res.json 500,'Error: something went wrong.'
    		else res.json 200,'OK, saved it.'
    
  4. Returning a list (result set), sync — at once, one HTTP response:
    when 'dumpdb'
    	s=db.createReadStream()
    	dump={}
    	s.on 'data',(d)->dump[d.key]=d.value
    	s.on 'end',->res.json 200,dump
    
  5. But, what I really wanted to do, is return the results one by one over Socket.IO! Pull stream? Anyway, messy mechanism, which I guess all “reactive”, “data binding” frameworks solve: incremental loading (minimize latency), pre-fetching, etc. Would be nice to not consume “state” on server (for, like, a cursor), and (some) consistency — except, BASE: I strongly believe in escalating the consistency problem to the app!
  6. Sublevels, aka buckets: prefixing keys manually is tedious, error prone — because repetitive, noisy, confusing (like, separate namespaces).
    app.io.route 'profile',(req)->
    	di='p!'+req.data.id
    	# Find profile, else create it.
    	db.get di,(err,v)->
    		if err?.notFound then v={}
    		#...
    		db.put di,v,(err)->
    			req.io.respond v
    

    (I wanted to loop (stream) over several types of records, but, in retrospective, either bypassing the sublevel wrapper or looping separately on each sublevel, would’ve been safer, cleaner, semantic.)

  7. Callback pyramids of hell? Need to find a nice promises API…
  8. lev, as external tool for debugging and maintenance, would’ve been nice if its TUI didn’t break. And have to kill the server to use it. Multilevel…?

CoffeeScript: DSLs FTW!

  1. Some of annoyances, but as near a domain specific language (DSL) as I can get: I’ve built entire apps weighing 500LOCs — including both server and client side code (both in coffee), HTML (in CoffeeCup or Jade), CSS (in Stylus). Less than a $#@! Angular widget.
  2. Would’ve been nice if could inline client side CoffeeScript: especially during hackathons, inlining JS (and CSS) saves me from having to run a rebuild or recycle (stop&start) the server — when both sides coded in same file, with Zappa.

Cake

  1. Crazy ecosystem, can’t keep up — I want to do apps, not DevOps!
  2. But, it’s clean and flexible. Almost. Nu, at least not the Grunt disaster which is almost as horrible as the XML of ossified Java dinosaurs. Go extinct already!
  3. Make, the ancestor of build automation: inhuman syntax, primitive beyond help, but straight to the point. Cake and friends should be the solution.

Responsive web design

  1. Remains a major pain; I blame UX/UI people. And CSS, obviously — it’s a terrible system.
  2. Page.js: cleanest API for handling hashchange and history?



Comments are closed.