Preface
Goal: Build static HTML files using partial Nunjucks utilizing Grunt.
Nunjucks is my favorite templating engine. It is powerful. Its syntax is simply a html document, so you can just copy-paste, and change a bit of your code. But I can’t show you the full power here in this article. This article will only provide a simple example for beginner.
Official Documentation
Source Examples
You can obtain source examples here:
1: Nunjucks Case
We use nunjucks
as html preprocessor
to build html
documents.
Consider transform our last HTML Case into Nunjucks Case.
Directory Structure
Consider nunjucks
structure.
└── views
├── css.njk
├── html.njk
├── index.njk
├── javascript.njk
├── partials
│ ├── head.njk
│ ├── layout.njk
│ ├── navbar.njk
│ └── sidebar.njk
└── php.njk
We want the nunjucks
to build html
artefacts as below:
└── build
├── css.html
├── html.html
├── index.html
├── javascript.html
└── php.html
Now we can separate each html parts.
Layout
<!DOCTYPE html>
<html lang="en">
<head>
{% include "partials/head.njk" %}
</head>
<body>
{% include "partials/sidebar.njk" %}
<div id="main">
{% include "partials/navbar.njk" %}
<div class="w3-container">
{% block main %}
<p>Default Page</p>
{% endblock %}
</div>
</div>
</body>
</html>
As shown in order we have three include
artefacts.
include head.njk
,include sidebar.njk
,include navbar.njk
,
And one block named main
.
{% block main %}
<p>Default Page</p>
{% endblock %}
Head
It is almost the same with the original head.
<title>{{ title or "Link Example: Default" }}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<script src="../js/script.js"></script>
<script src="//localhost:35729/livereload.js"></script>
Here we put the default title if we cannot find title
variable.
<title>{{ title or "Link Example: Default" }}</title>
I also add livereload
for use with grunt
later.
Sidebar
It is a simply a verbatim copy-paste from the original html
.
<div class="w3-sidebar w3-bar-block w3-card w3-animate-left"
style="display:none" id="mySidebar">
<button class="w3-bar-item w3-button w3-large"
id="closeNav" >Close ×</button>
<a class="w3-bar-item w3-button"
href="index.html">Home</a>
<a class="w3-bar-item w3-button"
href="html.html">HTML Link</a>
<a class="w3-bar-item w3-button"
href="css.html">CSS Link</a>
<a class="w3-bar-item w3-button"
href="php.html">PHP Link</a>
<a class="w3-bar-item w3-button"
href="javascript.html">Javascript Link</a>
</div>
Navbar
It is also a an exact copy from the original html
.
<div class="w3-teal">
<button class="w3-button w3-teal w3-xlarge"
id="openNav">☰</button>
<div class="w3-container">
<h1>My Page</h1>
</div>
</div>
<div class="w3-bar w3-black">
<a class="w3-bar-item w3-button"
href="index.html">Home</a>
<a class="w3-bar-item w3-button"
href="html.html">HTML</a>
<a class="w3-bar-item w3-button"
href="css.html" >CSS</a>
<a class="w3-bar-item w3-button"
href="php.html" >PHP</a>
<a class="w3-bar-item w3-button"
href="javascript.html">Javascript</a>
</div>
Index
By extending the partials/layout.njk
,
we can alter the content of main
block,
and also setup the title
variable.
{% extends "partials/layout.njk" %}
{% set title = "Link Example: Home" %}
{% block main %}
<p>Home Page</p>
{% endblock %}
2: Nunjucks Content Propagation
How does it works ?
Block and Inheritance
In partials/layout.njk
we have this block.
{% block main %}
<p>Default Page</p>
{% endblock %}
Then we can replace the content,
of the block in child layout index.njk
.
{% block main %}
<p>Home Page</p>
{% endblock %}
Title
Variable Propagation Between Template
In index.njk
we have this variable.
{% set title = "Link Example: Home" %}
This variable will be utilized in partials/head.njk
<title>{{ title or "Link Example: Default" }}</title>
This is almost self explanatory.
Main Files
Instantly, all the main files can be so short as below:
{% extends "partials/layout.njk" %}
{% set title = "Link Example: CSS" %}
{% block main %}
<p>CSS Page</p>
{% endblock %}
{% extends "partials/layout.njk" %}
{% set title = "Link Example: PHP" %}
{% block main %}
<p>PHP Page</p>
{% endblock %}
Result
Conclusively, we can check the result in build/index.html
,
against the original html
.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Link Example: Home</title>
...
</head>
<body>
...
<div id="main">
...
<div class="w3-container">
<p>Home Page</p>
</div>
</div>
</body>
</html>
3: Grunt Configuration
Command Line Interface
I cannot figure out how to use nunjucks-cli
properly.
Luckily, we have this good grunt
, as replacement.
package.json
All you need to know is the devDependencies
.
"devDependencies": {
"grunt": "^1.0.1",
"grunt-contrib-watch": "^1.1.0",
"grunt-nunjucks-2-html": "^2.2.0",
"nunjucks": "^3.2.1"
}
To begin with grunt
, you need to run npm install
first.
Gruntfile.js
You also need to a configuration file named Gruntfile.js
.
module.exports = function(grunt) {
// configure the tasks
let config = {
nunjucks: {
options: {
data: grunt.file.readJSON('data.json'),
paths: 'views'
},
render: {
files: [ {
cwd: "views",
src: "*.njk",
dest: "build",
expand: true,
ext: ".html"
} ]
}
},
watch: {
nunjucks: {
files: ['views/**/*'],
tasks: ['nunjucks'],
options: {
livereload: true,
interrupt: false,
spawn: false
}
}
}
};
grunt.initConfig(config);
// load the tasks
grunt.loadNpmTasks('grunt-nunjucks-2-html');
grunt.loadNpmTasks('grunt-contrib-watch');
// define the tasks
grunt.registerTask('default', [
'nunjucks', 'watch'
] );
};
The configuration is self explanatory.
Just read the official documentation of grunt-nunjucks-2-html
.
Data
We can skip data in grunt
, and your build will be working just fine.
But just in case you need to surpress warning message,
you can put empty data.json
as below:
{
}
Running Grunt
Now you can build your own static html
files using nunjucks
.
What’s Next?
We still have two grunt
example: EJSand
handlebars`.
Consider continue reading [ Template - Grunt - EJS ].