Recently, at Sidelab, we developed and deployed signforms.com, an application for signing documents online, in 14 days. The application runs on a node.js back-end, using amazon web services. One interesting thing about the application is that it uses effectively no HTML.
There are a few static html files for the lander site, but once logged in, there is only one .html file. Other than script tags to load the application for the very first time, the file looks like this:
</head> <body> </body> </html>
After that, no HTML is ever sent.
Don’t believe me? Sign up (its free currently), log in, then view source. You will see nothing but JSON.
The front end of SignForms is build using an opensource framework called Gaffa. Once the application has been loaded, all navigation is achieved via requests for JSON resources.
Oh, so it’s client-side templating.
In your browser, Gaffa takes the serialized page, inflates it into objects, then generates the DOM required to display the page, and adds all other functionality such as event handlers, page load, and autosave behaviours that are required.
I’m not a fan of HTML, it’s not something humans should write. One thing that people usually seem to forget is that HTML is a sibling to XML. The majority of people would prefer not to write XML, but have no issues writing HTML. This seems strange to me. The other thing people seem to forget is that HTML is a serialization format for DOM, it is verbose and inflexible.
One commonly seen flow of data for a web application is as follows:
- Write ‘Views’ in HTML
- Add magic strings to tell the server where to put more strings
- Scan massive string, stringify data and concatenate the extra strings to the original string
- Send massive string across the wire
- Don’t cache it because it will change next time.
- Parse massive string
- Correct any invalid HTML, take a best guess as to what it was supposed to be
- Convert strings into DOM
- Render the DOM
The way Gaffa handles navigation is different:
- Write code
- File watcher auto-serializes to JSON
- Serve JSON Page, cache for next time.
- Serve DATA.
- Parse JSON into ‘viewItems’.
- Apply Data to ‘viewItems’.
- render DOM (Or Canvas, or webGL, or google map markers, or any other logical view).
There are a few big advantages:
- Only one HTML page is ever sent, once, and it’s tiny (2KB uncompressed)
- Developers write code, not an XML derivative.
- Application pages are cached indefinitely, and are tiny (17 KB uncompressed and unminified for a feature rich page)
- The server only serves data, reducing load.
- Page-weight is microscopic. (<0.5 MB per page for everything, including all images, css, and data)
- Pages render stupid-fast (~1s for a complicated, data-bound page).
Gaffa achieves this by creating a declarative programming abstraction for the UI. If you want to display a textbox, and bind it’s value to the model, you would create a textbox viewItem:
var myTextbox = new textbox(); myTextbox.value.binding = '[myValue]';
Other views can bind to the same value in the model:
var myLabel = new label(); myLabel.text.binding = '[myValue]';
And the data can be manipulated before displaying it:
myLabel.text.binding = '(join " " "hello person, your value is" [myValue] "which is" [myValue].length "characters long")';
Then you add the viewItems to gaffa:
And you’re done.
Because viewItems are rendered as DOM, you can use CSS to style them as you normally would, and end up with a fast, feature rich web application in a very short period of time.
As to be expected from my previous post, this application forgoes the usual “Don’t think, include” librarys such as jQuery, bootstrap, etc, and instead uses small components that do exactly the job required.
A few libraries/technologies used:
You say that you don’t use a templating language but I think you are wrong. You are using JSON as the markup language which is pretty much worst than html if you ask me.
I’m not sure how that:
is better than that (handlebars):
We don’t write the JSON by hand, we just create objects, which serialize to JSON.
So for your example (taken from the readme i assume) we would code:
var userNameBox = new textbox();
userNameBox.text.binding = ‘[users/0/name]’;
Although, because there is an array index there (users/0/name) it is more likely the textbox was a list ‘template’ which is a viewItem that is added to a list that the list clones for each item in the array it is bound to. There is some overloading of the word ‘template’ here as they mean very different things in handlebars and gaffa.
To do this list based UI, you would code:
var usersList = new list(),
userNameBox = new textbox();
usersList.path = ‘[users]’; // Set up a model scope for children and properties.
usersList.list.binding = ‘’ //Don’t modify the array before displaying
usersList.list.template = userNameBox;
userNameBox.text.binding = ‘[name]’; // This is relative to the parents path.
Years later, have you checked Reactjs out? Looks a lot like what you were trying to achieve.
I’ve had a look at react, but I went in a slightly different direction with http://korynunn.github.io/fastn/