zappa

Fork me on GitHub

v0.2.x “Peaches en Regalia”

Zappa was conceived almost a year ago as a crazy experimentalist hack to explore possibilities in the then forming and rapidly changing Node.js/CoffeeScript “platform”. Since then this “platform” matured a great deal, and it’s high time zappa is consolidated into something really usable, and more in tune with today’s node development ecosystem.

So the 0.1.x series is hereby retroactively codenamed “Jazz from Hell”, and work shall begin on 0.2.x “Peaches en Regalia”.

An initial beta for 0.2.0 is already available. To check it out, just run in your project directory:

npm install zappa@0.2.0beta

Or to follow the bleeding edge:

git clone git@github.com:mauricemach/zappa.git && cd zappa
cake build
npm link

Then in your project:

npm link zappa

In this first release, the main themes are:

Documentation

Three important pieces of documentation are introduced with this release. They’re all under heavy development!

Examples were also updated and added (see /examples).

A website will follow, before the final 0.2.0 release.

Fixing performance

Peaches is a rewrite from scratch, with the main goal from the beginning of not getting in the way of express’ performance. It’s 100% free of the with keyword, so it’s also kosher, FDA approved, carbon-neutral and all that.

The rough benchmark that accompanies the beta points to speed being now very close to that of “raw” express:

MacBook Air 3,2 (2 gigs RAM) ab -n 2000 -c 50

zappa: 2038.49 req/s express: 2075.79 req/s

This for rendering a simple jade template and layout in production mode.

But then, there are lies, damn lies, and benchmarks. Suggestions and contributions to more meaningful measurements are very welcome.

Getting out of your way

In peaches, zappa takes inspiration from the way CoffeeScript enhances JavaScript, providing alternative, progressive levels of syntactic sugar over the standard APIs, using abstractions more sparingly.

A zappa application should be closer to a summarized version of a “normal” node app. The underlying libraries’ implementations are used whenever possible, and familiar terms from them are preferred.

If you can do it with “raw” express/socket.io, you should be able to do it when using zappa too, only faster.

New features: client-side API and code sharing

All work and no play makes zappa a dull module! Even though Peaches is mainly about consolidation and cleanup, it also brings the beginnings of two important missing pieces in the zappa puzzle. A matching client-side API, and client-server code sharing.

Sharing code

If you use shared '/foo.js' -> instead, the block of code will be both evaluated on the server and served to the client. Ex.:

shared '/shared.js': ->
  def sum: (a, b) ->
    a + b

  if window
    alert 'Running on the browser!'
  else
    console.log 'Running on the server!'

client '/index.js': ->
  get '#/': -> console.log sum 5, 8

get '/': -> console.log sum 3, 6

Nice, now please show me some freaking code!

With all this standardization talk you’d expect zappa apps to now look a lot different from they did in Jazz. But in practice, the basic structure remains the same:

require('zappa') ->
  include 'sub'
  
  def foo: 'bar'
  
  helper role: (name) ->
    redirect '/' unless @user.role is name
  
  get: '/': 'hi'
  
  get: '/': ->
    @foo = 'bar'
    render 'index'
    
  coffee '/index.js': ->
    alert 'hi'
    # socket.io code here.

  at connection: ->
    broadcast "#{@id} connected"

  at hello: ->
    emit 'reply', foo: 'bar'
  
  view index: ->
    h1 @foo
    
  view layout: ->
    doctype 5
    html ->
      head ->
        title 'Foo'
        script src: '/socket.io/socket.io.js'
        script src: '/index.js'
        link rel: 'stylesheet', href: '/index.css'
      body @body
  
  css '/index.css': '''
    font-family: sans-serif;
  '''

At sub.coffee:

    
# Could also be `module.exports.include`.
@include = ->
  get '/sub': -> render 'sub'

  view sub: ->
    p 'Sub module included'

The actual big difference is what you can do now:

    
zappa = require 'zappa'

chat = zappa.app ->
  set 'view engine': 'jade'
  app.register '.jade', zappa.adapter 'jade'
  
  io.set 'log level', 1

  enable 'serve jquery'
  
  use 'cookieParser', 'bodyParser'

  configure development: ->
    use errorHandler: {dumpExceptions: yes}

  shared '/shared.js': ->
    def sum: (a, b) -> a + b

  get '/': ->
    @foo = 'bar'
    render 'index'
    
  at connection: ->
    broadcast 'joined', {id}

  client '/index.js': ->
    connect()
    
    at joined: ->
      alert "#{@id} joined us."

  view index: '''
    h1= foo
  '''

  view layout: '''
    !!! 5
    html
      head
        title A Jade template!
        script(src='/socket.io/socket.io.js')
        script(src='/zappa/jquery.js')
        script(src='/zappa/zappa.js')
        script(src='/shared.js')
        script(src='/index.js')
      body!= body
  '''

wiki = zappa.app ->
  get '/': 'wiki'
  # wiki code here...

zappa 80, {chat, wiki}, ->
  use express.vhost 'chat.com', chat.app
  use express.vhost 'wiki.com', wiki.app

What’s next?

Before a final 0.2.0 release, at least these are still meant to be worked on: