Let's start with an example.
Say you have a simple web application which displays the pictures of cats, and people can vote on how cute a cat is. (Honestly, this is the kind of app I'd like to work on)
Now, there are two methods to achieve this:
Client-Side Rendering -- the client, that is, the browser somehow gets the data, forms the DOM nodes, manipulates the DOM and displays the elements (rendering);
Server-side Rendering -- the server sends a pre-rendered (i.e., all the steps I outlines above been executed on the server-side) page, and that is displayed to the user.
With the upcoming craze of JavaScript frameworks like Angular 2 and React, this is the trend most developers follow. Essentially, any Client-Side rendered application can be broken down into two parts:
backend -- the side of the application which does not interact with the user directly; I say 'directly' because at the base level, it's the one which does the heavy lifting: executes tasks like saving data in the database, fetching the data, authenticating a user;
frontend -- the side of the application which the user interacts with; fetches the data from the server (through a transport), and displays it to the user;
transport -- the link between the frontend and the backend: the mode of transport for the data from and to the backend; an example would be JSON over REST.
So, say in Angular, I can have the following simple application skeleton:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Cute Cat App</title>
<!-- Script tags to import Angular; Links for CSS, etc. -->
</head>
<body ng-app="app" ng-controller="MainAppController as ctrl">
<div>
<ul>
<li ng-repeat="cat in ctrl.cats">
<img src="{{ cat.imgSrc }}" alt="{{ cat.name }}" />
{{ cat.name }}
</li>
</ul>
</div>
</body>
</html>
Then in my application's main JavaScript file I can have
angular.module( 'app', [ ... dependencies ... ] );
angular
.module( 'app' )
.controller( 'MainAppController', [ '$http', function( $http ) {
$http.get( 'http(s)://<API_URL>/cats' ).then( data => {
this.cats = data.cats;
} ).catch( err => {
// Some cool error-handling voo-doo
} );
} ] );
The GET URL probably returns something like the following:
{
cats: [
{
name: 'Mittens',
imgSrc: 's3.ap-northeast-2.amazonaws.com/mycutecats/<GU…'
}
...
]
}
So, to summarize:
Fetch the data from the backend;
Parse the data;
Manipulate the DOM with the data (with libraries like React, this is WICKED fast)
Very simple put, in this model, the server provides with a page which is already populated with the data. One method which I have used (guilty) is using a templating engine, and then churing out a ready-to-be-rendered page.
Imagine, something like this:
....
server.route( {
method: 'GET',
path: '/cats',
handler: ( request, reply ) => {
/* For the sake of this example, imagine that the constant `data` is already
populated with the data; similar to the JSON I have in the previous example */
const cats = ...;
reply.view( 'cats', cats );
}
} );
In the end, a page like this is provided to the browser:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Cute Cat App</title>
<!-- Script tags to import frameworks; Links for CSS, etc. -->
</head>
<body>
<div>
<ul>
<li ng-repeat="cat in ctrl.cats">
<img src="s3.ap-northeast-2.amazonaws.com/mycutecats/<GU…" alt="Mittens" />
Mittens
</li>
</ul>
</div>
</body>
</html>
So, the browser does not do anything fancy, apart from displaying some static (according to the browser) web content.
Again, if you need advice/tips in anything related to any of the techniques, feel free to comment! Anything, really. From deployment, to maintainance.
I hope this helps! :)