primus-live

Live reload with Jade/Stylus/CoffeeScript/Markdown support

npm install primus-live
44 downloads in the last week
48 downloads in the last month

Primus Live

This is a simple development setup for Node.js apps, with minimal dependency on other packages and maximal freedom to organise the app's source files:

  • uses Primus to manage a WebSocket connection between server and client
  • automatic WebSocket reconnect with back-off (handled by Primus)
  • uses Connect to serve all static files in the app/ folder
  • can compile Jade (.jade) and MarkDown (.md) files to HMTL (.html)
  • can compile Stylus (.styl) files to CSS (.css)
  • can compile CoffeeScript (.coffee) files to JavaScript (.js)
  • clients do not care about this, they just fetch .html, .css, and .js files
  • the server tells each client to reload HTML or refresh CSS when a file changes
  • the server will restart itself whenever a source code file changes
  • scans for plugins to include custom host- and/or client-side logic
  • simple application modularity: each plugin is a subfolder in the app/ folder
  • auto-installs npm and Bower package dependencies in top-level folder
  • will run make for all the subfolders which contain a Makefile
  • no temporary files are saved to disk (other than what the above tools use)

Primus Live is not needed for production, deploy your app in any way you like.

Quick start

Enter these commands to create and launch a new app with Primus Live:

mkdir mydemo mydemo/app
cd mydemo
echo '{"name":"mydemo"}' >package.json
npm install primus-live --save
echo "require('primus-live');" >index.js
node .

The server can now be accessed on its default port at http://localhost:3333/.

Included example

This simple demo connects and reports tick events from the server. It uses Jade, Stylus, and CoffeeScript (HTML, CSS, and JavaScript would also work):

app/index.jade

!!!
html(lang='en')
  head
    meta(charset='utf-8')
    title Primus Live Example
    link(rel='stylesheet',href='/style.css')

  body
    h1 Server time
    p#tick

    script(src='/primus/primus.js')
    script(src='/app.js')

app/style.styl

body
  margin 50px

app/app.coffee

primus = new Primus

primus.on 'data', (data) ->
  if typeof data is 'number'
    el = document.getElementById 'tick'
    el.innerHTML = new Date(data)

app/launch.coffee

module.exports = (app) ->

  app.config.plugin.tick =
    server: (primus) ->
      setInterval ->
        primus.write Date.now()
      , 1000
    client: (primus) ->
      primus.transform 'incoming', (packet) ->
        if typeof packet.data is 'number'
          console.log 'tick', packet.data

  app.on 'running', ->
    console.info "server listening on port :#{app.config.port}"

Startup

Launch the example as follows and then go to http://localhost:3333/:

  npm install
  cd example
  node ..

It will keep running, compiling (in memory) and serving files as needed. Touch or change any of the files in the app/ folder to see live-reload in action.

primus.js

This transport-specific wrapper (here engine.io) is generated by Primus. It also includes the client-side code of all plugins, so they can be initialised when the Primus connection object is created on the client.

Plugins

If there are subfolders in './app', these will be used to define additional plugins. Put host-side code in a file named 'host.coffee' (or .js), and put client-side code in a file called 'client.coffee' (or .js) and it automatically gets picked up, i.e. launched on the server and/or sent and run on the clients.

The host-side code must export a single function taking 'app' and primus as arguments - this will be called as part of the Primus initialisation sequence.

The client-side code can be anything, it is sent over and run as is (note that this happens before the client-side Primus instance gets created).

If there is a package.json file in the plugin folder, then all dependencies will be installed in the top level before the live server starts running. If a bower.json file is found, then those dependencies will get installed too. Version numbers are not yet honoured, the latest versions will be installed.

Lastly, if a Makefile is found, then make will be called (no further args).

Your own app

See the Quick start section above for getting started.

Load primus.js followed by a new Primus(); on each page load to keep a real-time bi-directional WebSocket connection open, including the automatic live-reload. This is is particularly easy to do with single-page applications.

Live-reload is implemented by sending true or false over the WebSocket (as JSON). These two values should be ignored in your own code when listening for data events on the primus object.

app/launch.{coffee,js}

If this file exists, it will be loaded before the scanning and loading of plugins starts. It is called with the Connect app object as argument.

  • set app.config.transport to change the engine.io default for Primus
  • set app.config.port to change the server port of the app (default 3333)
  • set app.config.firstLoad to the list of modules to load before the rest

Event 'setup'

This event on app fires after all plugins have been loaded, but before the server and Primus objects are created (which calls the host-side plugins).

The app.config.plugin object can still be adjusted at this point, this will affect the actual list of host- and client-side plugins installed by Primus. Keep in mind that the client functions will be stringified before use, they cannot contain any host-side variable closures.

Event 'running'

This event on app fires once the server is running and accepting connections. All the host-side plugins have been installed at this point. The client-side scripts will be loaded in the browser(s) as part of the connection process.

The event handlers will also get one arg: the primus object on the server.

Standalone use

The Primus Live package is not required for production use, i.e. when you don't want to "preflight" npm / bower installations and don't need to restart the server because no source code changes will be made. In this case, copy the worker.coffee file into your own project and run it as coffee worker.

For high-end scenarios, the scripts could all be pre-compiled and served using a fast static file server such as nginx, with a dedicated WebSocket server to provide just the real-time side of things (this hasn't been tried yet).

License

MIT

npm loves you