-
Notifications
You must be signed in to change notification settings - Fork 0
Description
The vdom-streaming-serializer is a library for serializing virtual DOM objects into chunks of strings that can be written into an HTTP response.
Serializers
A serializer takes a data structure and turns it into a format that can be transferred betweens processes and then reconstructed later (called deserialization) back into the data structure from which it originated. See the Wikipedia article for more information.
A DOM serializer is a serializer that takes DOM objects (such as Elements) and turns them into HTML strings.
A basic DOM serializer looks like this:
function serialize(element) {
if(element.nodeType === Node.TEXT_NODE) {
return element.nodeValue;
}
var out = '<' + element.localName;
var attr;
for(var i = 0, len = element.attributes.length; i < len; i++) {
attr = element.attributes[i];
out += attr.name + '=' + attr.value;
}
out += '>';
for(var i = 0, len = element.childNodes.length; i < len; i++) {
out += serialize(element.childNodes[i]);
}
out += element.localName + '/>';
return out;
}
serialize(document.documentElement);To server-render applications DoneJS uses the can-simple-dom library which provides DOM-like objects and includes it's own serializer which can be viewed here for reference.
Streaming
Streaming is a way to deliver data incrementally. If you've ever used Netflix you've used streaming.
Similar to how Netflix can stream video over the internet, the a web server can stream HTML to the browser over HTTP. In Node.js you can write to an HTTP request's response stream like so:
var http = require('http');
var hostname = '127.0.0.1';
var port = 3000;
var server = http.createServer(function(request, response){
response.statusCode = 200;
response.setHeader('Content-Type', 'text/html');
response.write("<h1>My homepage</h1>");
setTimeout(function(){
response.write("<p>Hello world!</p>");
response.end();
}, 50);
});
server.listen(port, hostname);In the above example we write some HTML into the response, wait 50 milliseconds, write some more HTML, and then end the response. You can imagine how this technique might be useful:
- If you need to make a request to a database to retrieve data before rendering some HTML.
- If you need to make a request to an external API.
- If you have an incoming stream containing a list of items to render.
- A slower database query that is not needed until the user has scrolled down the page.
If you are familiar with MVC, Model-View-Controller, much of the controller's job is to get the models ready to hand over to the view. Streaming is a method that allows you to do this work incrementally, showing your users something while you wait for all of the db requests to complete.
This project
This project combines the two above ideas, taking a DOM serializer and making it so that it can stream chunks of HTML into an HTTP response.
A streaming serializer works similar to the above example DOM serializer, except that when it encounters a Node that is marked as being asynchronous, it will flush any HTML it has already generated and wait for that Node to be complete.
Nodes will be marked as being async using a Symbol like so:
var ASYNC = Symbol.for('async-node');
element[ASYNC] = new Promise( ... )The streaming serializer will do something like this:
if(element[ASYNC]) {
// Call the `flush` method to write any existing HTML
// that has been accumulated.
this.flush();
element[ASYNC].then(function(){
// Now we can continue serializing from where we left off
});
}This will allow HTML to be delivered as incremental chunks:
chunk 1
<h1>Todos page</h1>
<ul>
chunk 2
<li>Go to the grocery</li>
chunk 3
<li>Walk the dog</li>
chunk 4
</ul>
<footer>Thanks for visiting my page!</footer>
What's Next
Hopefully this introduction provides an idea of what this project hopes to achieve. Next check out these issues to learn more.