Progressive Rendering – how to make your app render sooner

Denis Rechkunov

Progressive Rendering

How to make your app render sooner 
Denis Rechkunov (@pragmader)

Some facts about me

We're going to talk about

Server-side rendering
in general first

Majority of Node.js apps nowadays


(req, res, next) => {
	const urlParts = url.parse(req.url, true);
	getData(urlParts.query.id)
		.then(data => template.render(data))
		.then(html => res.end(html));
}
		

What's wrong with that?

What do your users think?

Some of them are just sad

Some of them are very angry

And some of them know that
progressive rendering exists

How can we fix this?

Instead of sending the
whole HTML buffer at once

We can send
HTML by multiple chunks

And this would be
progressive rendering

Never heard of it,
is it new?

Back in 1997

RFC 2068. HTTP/1.1

"The chunked encoding modifies the body of a message in order to transfer it as a series of chunks, each with its own size indicator, followed by an optional footer containing entity-header fields. This allows dynamically-produced content to be transferred along with the information necessary for the recipient to verify that it has received the full message."

Back in 2005

"The Lost Art of Progressive HTML Rendering" by Jeff Atwood

"One thing I dislike about ASP.NET is that it renders the entire web page in memory before sending one single byte of that page to the browser"

"What's even more galling is that HTML was originally designed to render progressively as content is received"

Netscape 1.0

Netscape 1.0's early beta versions introduced the "progressive rendering" of pages and images, meaning that the page begins to appear and the text can be read even before all of the text and/or images have been completely downloaded.

If we edit the previous code


(req, res, next) => {
	const urlParts = url.parse(req.url, true);
	getData(urlParts.query.id)
		.then(data => template.render(data))
		.then(html => res.end(html));
}
		

(req, res, next) => {
	const urlParts = url.parse(req.url, true);
	getHeaderData(urlParts.query.id).then(headerData => {
			res.write(template.render('header', headerData));
			return getLeftMenuData(headerData.userId);
		}).then(leftMenuData => {
			res.write(template.render('leftMenu', leftMenuData));
			return getMainBlockData(leftMenuData.currentSection);
		})
		.then(mainBlockData => /* etc. */)
		.then(html => res.end());
}
		

And we can use
Node.js streams


(req, res, next) => {
	const urlParts = url.parse(req.url, true);
	const pageStream = new MyReadable(urlParts);
	pageStream.pipe(res);
}

const Readable = require('stream').Readable;
class MyReadable extends Readable {
	constructor(options) {
		 super(options);
	}
	_read(size) {
		this.push('chunk of HTML');
		this.push(null);
	}
}
		

Why progressive rendering is better?

Advantages

Browser loads resources in parallel

But it's not perfect

What about client-side rendering?

Simple as that

Facebook uses placeholders

Is there a library/framework?

Existing solutions

Summary

The point is...

Don't make your users wait
Make your apps render sooner

Thank you!

Denis Rechkunov (@pragmader)
The Gifs were taken from Giphy