×
By the end of this chapter, you should be able to:
pug
pug
to create dynamic templatesSo far we have only seen how to respond by sending text, but when building server-side applications, we usually want to send back HTML or JSON / XML (if we're building an RESTful API).
If we want to simply send HTML back we can use response.sendFile
, but since we are using server-side templates, we will be using a method called render
.
In order to do that, we need to make use of a templating engine (a tool for dynamically rendering HTML using server data). There are quite a few we can use with Node.js including ejs
, but we will be using one called pug
(formerly known as jade
).
Before we introduce the pug syntax, let's first start a new project and see what we need to include. By default, express expects a folder containing templates to be called views
. Instead of overriding that default, we will also create a folder called views
.
mkdir learn_pug && cd learn_pug touch app.js npm init -y npm install express pug # notice we are installing pug as well! mkdir views touch views/index.pug
Let's now get started in our app.js
:
const express = require("express"); const app = express(); app.set("view engine", "pug"); // notice here we are telling express to render views using the pug templating engine. app.get("/", (request, response) => { return response.render("index"); // here we are rendering a template called index.pug inside of the views folder }); app.listen(3000, () => { console.log( "The server has started on port 3000. Head to localhost:3000 in the browser and see what's there!" ); });
The most important thing to understand about pug
is that it is an indentation-based syntax. To nest elements inside of each other we simply indent the inner elements.
const express = require("express"); const app = express(); const colors = ["red", "green", "blue"]; app.set("view engine", "pug"); // notice here we are telling express to render views using the pug templating engine. app.get("/", (request, response) => { const firstName = "Elie"; return response.render("index", { name: firstName }); // here we are rendering a template called index.pug inside of the views folder. We are also passing a value to the template called "name". Inside of the template, the value of that variable will be the value of the firstName variable, which is "Elie" }); app.get("/colors", (request, response) => { // {colors} is ES2015 object shorthand notation for {colors: colors} return response.render("data", { colors }); // here we are rendering a template called data.pug inside of the views folder. We are also passing a value to the template called "colors". Inside of the template, the value of that variable will be the value of the colors variables, which is an array. }); app.listen(3000, () => { console.log( "The server has started on port 3000. Head to localhost:3000 in the browser and see what's there!" ); });
To evaluate variables inside of our templates, we will use the Jade #{variable}
syntax. When you do string concatenation with Jade - use the ES2015 string templates with the ${javascript to interpolate}
syntax. Here is what our index.pug
file might look like:
h1 Hello #{name}
And our data.pug
- notice we are using the Jade syntax #{}
for variables and ES2015 ${}
for string concatentation/interpolation.
h1 Here are the colors! each color in colors p #{color} a(href=`/colors/${color}`) Learn more about this color
Now in our views/index.pug
file let's place the following:
<!DOCTYPE html> html(lang="en") head meta(charset="UTF-8") title Document body h1 "Hello World!" p Outer Paragraph .foo A div with a class of foo h2 Let's do some math! #{5+5}
One very useful feature that pug gives us is called template inheritance. What this means is that we can use the same template in all of our files and only have to define it once! We can include templates using the extends
keyword. We also need to tell our template where to inject HTML from other files; we do this with the block
keyword.
Let's look at an example. In our views folder, let's create a file called base.pug
.
<!DOCTYPE html> html(lang="en") head meta(charset="UTF-8") title Document body block content
Next, let's create a hello.pug
, extend our base.pug
file, and include our own content! We just have to make sure that the content specific to hello.pug
is indented inside of block content
:
extends base.pug block content h1 Hello World!
For more examples of the features available to you in pug, take a look at the documentation.
express.static
Before we continue with routing, let's examine how to tell our server how to serve static assets (css/javascript/images). To do this we create a folder called public
in the root directory. We can then add the following in our app.js
:
const express = require("express"); const app = express(); app.set("view engine", "pug"); app.use(express.static(__dirname + "/public")); // we are using the express.static middleware and specifying a path for static files to be found (__dirname is a variable that we can use to refer to the directory name of the current module) // even though we were previously using request and response as names of parameters, you will very commonly see these as req and res. app.get("/", (req, res, next) => { return res.render("index"); }); app.listen(3000, () => { console.log("Server is listening on port 3000"); });
You can see an example of this
here.
When you're ready, move on to Lightweight Storage with Redis