Dr. Greg Bernstein
Updated March 9th, 2021
A way of mixing code with text or a markup language to produce custom documents.
They may be specific to a particular programming language, e.g., JavaScript, Python, Ruby, and may be specific or independent of a particular markup language, e.g., HTML.
Server side HTML page rendering
Static site Generation
Client side HTML page rendering
The Mako python template engine is used by reddit.com where it delivers over one billion page views per month.
Metalsmith and Wintersmith are examples of two modern Node.js static site generators that utilize templates.
The popular Angular and Vue front end frameworks utilize templates.
Too many choices of template engines
Wide variety of syntax
We’ll restrict ourselves to some basic features of one of the “popular” template engines that has multiple language implementations.
{{blah}}
where blah
is any JavaScript variable.extends
and block
if
, for
include
other files within a templateFrom the NunjucksTemplateExamples1.zip /views/hello.njk
:
<main>
<h1>Hello {{name}}</h1>
<h2>Welcome to {{class}}</h2>
{% if teacher %}
<h3>Have fun <strong>teaching!</strong></h3>
{% else %}
<h3>Have fun learning all about <em>Web Systems!</em></h3>
{% endif %}
</main>
From examples user.json
:
{
"name": "Dr. B",
"class": "CS651",
"teacher": true
}
From examples fileRender1.js
used to run the template engine
const nunjucks = require('nunjucks');
const user = require('./user.json');
const fs = require('fs'); // The file system module
// Tells nunjucks where to look for templates and set any options
nunjucks.configure('views', { autoescape: true });
let outString = nunjucks.render('hello.njk', user); // data as a JS object
fs.writeFileSync('./output/hello.html', outString);
console.log("Wrote file");
Will be found in examples /output/hello.html
<main>
<h1>Hello Dr. B</h1>
<h2>Welcome to CS651</h2>
<h3>Have fun <strong>teaching!</strong></h3>
</main>
npm install nunjucks
from examples test1.js
nunjucks = require('nunjucks'); // Import Nunjucks
nunjucks.configure({autoescape: true});
// Give it a template in string form, and a JS Object with info
let helloStr = nunjucks.renderString('Hello {{username}}',
{username: 'Dr. B.'});
console.log(helloStr);
From example view/prizes.njk
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Nobel Prizes in {{catDate.title}}</title>
<link rel="stylesheet" href="prizes.css">
</head>
<body>
<main>
<h1>Nobel Prizes in {{catDate.title}}</h1>
<h2>From {{catDate.start}} to {{catDate.end}}</h2>
<nav>
<p> Other categories:
{% for item in menu %}
<a href="{{item.fname}}">{{item.title}}</a>
{% endfor %}
</p>
</nav>
<table>
<thead><tr>
<th>Year</th>
<th>Name</th>
<th>Accomplishment</th>
</tr></thead>
<tbody>
{% for prize in prizes %}
{% for laureate in prize.laureates %}
<tr>
<td>{{prize.year}}</td>
<td>{{laureate.firstname}} {{laureate.surname}}</td><td>{{laureate.motivation}}</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</main>
</body>
</html>
Data from https://www.nobelprize.org/
{
"prizes": [{
"year": "2017",
"category": "physics",
"laureates": [{
"id": "941",
"firstname": "Rainer",
"surname": "Weiss",
"motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"",
"share": "2"
}, {
"id": "942",
"firstname": "Barry C.",
"surname": "Barish",
"motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"",
"share": "4"
}, {
"id": "943",
"firstname": "Kip S.",
"surname": "Thorne",
"motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"",
"share": "4"
}]
}, {
"year": "2017",
"category": "chemistry",
"laureates": [{
"id": "944",
"firstname": "Jacques",
"surname": "Dubochet",
"motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"",
"share": "3"
}, {
"id": "945",
"firstname": "Joachim",
"surname": "Frank",
"motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"",
"share": "3"
}, {
"id": "946",
"firstname": "Richard",
"surname": "Henderson",
"motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"",
"share": "3"
}]
}]
}
Produces a set of Nobel prize pages based on a list of categories and date ranges. See examples NobelPrizes.js
/* A file to rendering Nobel Prize information from JSON into HTML
with *nunjucks*.
*/
const nunjucks = require('nunjucks');
const prizesJSON = require('./prize.json');
const fs = require('fs'); // The file system module
let catDates = [{
topic: "physics",
start: 1926,
end: 1954,
title: "Physics",
fname: "physics.html"
},
{
topic: "chemistry",
start: 1936,
end: 1964,
title: "Chemistry",
fname: "chemistry.html"
},
{
topic: "economics",
start: 1940,
end: 1980,
title: "Economics",
fname: "economics.html"
}];
nunjucks.configure({
autoescape: true
});
nunjucks.configure('views', {
autoescape: true
});
// Process prizes.json to get only information of interest
let prizeArray = prizesJSON.prizes;
for (let catDate of catDates) {
let myPrizes = prizeArray.filter(function (x) {
return (x.category === catDate.topic) && (x.year >= catDate.start) && (x.year <= catDate.end)
});
myPrizes.reverse();
let prizeInfo = {
catDate: catDate,
prizes: myPrizes,
menu: catDates
}
// console.log(JSON.stringify(myPrizes));
let outString = nunjucks.render('prizes.njk', prizeInfo);
fs.writeFileSync('./output/' + catDate.fname, outString);
console.log("Wrote file " + catDate.fname);
}
node NobelPrizes.js
/output
directory in examples to see the generated HTML filesHTML (pages) are created ahead of time and stored on server which waits for a page request. Static Site
HTML is created in Web Browser via the DOM and JavaScript from data from website. Web App
HTML is created on the server when a request comes in based on data stored on the server. Classic Website, Server side rendering, e.g., WordPress, Drupal, etc…