”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 Pug 和 Express 提供动态 HTML

使用 Pug 和 Express 提供动态 HTML

发布于2024-08-19
浏览:798

Serving Dynamic HTML With Pug And Express

Before Single Page Applications became a thing, templating languages like Pug were super popular because they allowed developers to render a page on the server side before sending it over to the client. Express is the most popular backend application framework for Node.js. It prides itself on being lightweight, unopinionated, and minimal to use. In this guide, you will learn how to serve dynamic HTML with Pug from an Express.js server application.

How does Pug work?

HTML can be cumbersome to write sometimes. The language has no support for features like "components", which can lead to code duplication unless you rely on external tools like JavaScript.

Pug is a templating engine that makes it easier to write HTML. With Pug, you can split your code and reuse "components" in as many places as you'd like. Regarding syntax, Pug differs from traditional HTML as it uses indentation instead of closing tags. In HTML, you define an element like this:

This is something worth noting

In Pug, however, you define an element like this:

div(class='hello') This is something worth noting

The tag name is defined on the left, with its attributes in brackets. The tag is separated from its contents by the space next to it. The Pug transpiler will transpile your code back to the proper HTML code recognized by the browser. Child elements are defined by indentation. This means if you wanted to have a div inside a main tag, you'd do something like this:

main
div Hello from the children of planet Earth!

Integrating Pug with Express

To add Pug to your Express.js project, simply install Pug with any package manager of your choice. For this example, I'm working with NPM:

npm i pug

This will add Pug to your list of dependencies in your package.json file. Now, you'll need to set your view engine to pug, so in your project's entry file (usually main.js, app.js, or index.js ), import express properly and configure the application settings with the set method.

import express from 'express';
const app = express();

app.set('view engine', 'pug');

By setting view engine to 'pug', you're telling Express to use Pug as its templating engine. So, when you call the render method on the response object, you must pass a valid 'view' for Express to render. Views in Express must be placed in a special views directory, in the project's root directory. If you haven't created a views directory, you can do so with the following:

mkdir views
# Make sure you are in your project root 

Now, that you've got things set up, let's proceed to writing our first view in Pug.

Basic Pug Usage in an Express Project

Create a views/index.pug file, and add the following to it:

html
  head
    title Welcome to my website
  body
    div Hello World

Now that your index.pug file is ready, you'll need to serve it to the client on a route. Go to your project's entry file and define a get request handler that will render and return the views/index.pug file to the client.

app.get("/", (req, res) => {
  res.render("index.pug");
});

When you open localhost:, you should see the "Hello World" message printed on the screen. In the callback function of the get method, you'll see the usage of res.render in its simplest form. The syntax for the render method is shown below:

res.render(view [, locals] [, callback]);

First, we have view, which is simply the path of the .pug file you want to render. Remember that Express locates the .pug files relative to the views directory. So, if you have a Pug file located at views/layouts/main.pug, you should refer to it as layouts/main when setting the view in your route.

app.get("/", (req, res) => {
  res.render("layouts/main");
});

Next, the locals is an object with properties that define local variables that should be passed into the specified view for interpolation. When callback is provided, the resulting HTML from the render operation is not sent to the client. Instead, you can access it via a parameter in the callback function, like this:

app.get("/", (req, res) => {
  res.render("index.pug", {}, (err, html) => {
    console.log(html);
  });
});

When the client makes a get request to '/', a response is not sent. Instead, html is logged to the server console. You can manually send the HTML to the client with the send method:

res.send(html)

Building Dynamic HTML Pages

Now it's time to take things to the next level. You'll learn how to interpolate data with Pug to create dynamic content on the fly. In Pug, string interpolation is done with the syntax #{}. At compilation time, #{} is resolved to its actual value. Here's an example.

// greet.pug
html
  head
    title Welcome to my website
  body
    div Hello #{name}

In the code block above, name will be replaced the actual value from the locals object passed into the render method. If name is undefined, no error is thrown. Here it is in action.

app.get('/greet', (req, res) => {
    const {name} = req.query;
    res.render('greet.pug', {name})
})

When the client hits /greet?name=David, the following HTML will be returned

  
    Welcome to my website
  
  
    
Hello David

The string interpolation syntax (#{}), is escaped by Pug. This is useful in situations where the content comes from users. If you want Pug is render the string as is without escaping, you'll need to use the !{} syntax.

- var example = very risky
div !{example}

Tags and Tag Intepolation in Pug

Pug provides a handy syntax for tag interpolation #[], which you can use like this:

  1. Basic Tag Interpolation: You can interpolate a tag directly within text.
p This is a #[strong very important] message.

This will render as:

This is a very important message.

  1. Interpolating with Variables: You can also interpolate tags with variables.
- var username = 'John' 
p Hello, #[strong #{username}]!

You don't have to worry about self-closing tags, because Pug knows what tags are self closing. But if you really need to self-close a tag, you can append the / character to the end of the tag like this:

div/

To save space, You can use the : shorthand instead of indentation to specify nested tags.

label: input(type='text' name='username')

The code block above is just as valid as:

label
    input(type='text' name='username')

Using JavaScript in Pug

In the last code block, notice the use of the var keyword from JavaScript to create a variable. Pug allows you to insert valid JavaScript code on any line that starts with an -. For example, you can create an array and iterate over it to render a list of items. Pug has its native syntax for this, but in this example, you can use JavaScript.

html
  head
    title Welcome to my website
  body
    div List of items 
    - var items = ['milk', 'peas', 'bread']
    - items.forEach((item)=>{
      li #{item}
    - })

Study the previous example. Notice how Pug and JavaScript are combined. The forEach method is not part of the Pug API, it belongs to JavaScript. Likewise, the string interpolation symbol is not part of the #{} JavaScript API. The lines with valid JavaScript code are marked with the - symbol. On the second to last line, there is no - symbol, because that is Pug code.

Iteration and conditionals with Pug

For common things like conditionals and iteration, Pug provides its syntax that you can use instead of JavaScript. The most popular keyword for iteration in Pug is each. each must come in the form each VARIABLE_NAME of JS_EXPRESSION. Here's how you can use it:

each item in ['milk', 'peas', 'bread']
   li #{item}

When dealing with objects, the expected format for each is each VALUE, KEY OF JS_EXPRESSION. For example:

each val, key in {1:'milk', 2:'peas', 3:'bread'}
  #{key} : #{val}

You can use the if syntax to handle conditionals. Here's an example:

╴ var loggedIn = false

if !loggedIn
    p Sorry you cannot access this item because you're not logged in

Conversely, Pug has an unless keyword that you can use like this:

unless loggedIn
    p Sorry you cannot access this item because you're not logged in

Advanced Techniques with Pug

Pug offers many features beyond just string interpolation and conditionals. If you are working on a large website, you might need to use advanced features that Pug provides, such as layouts and partials.

Using Layout files for consistent page structure

Layout files allow you to define a common structure for your pages and extend it in other templates, ensuring consistency across your website. Here's an example of how you can use layout files.

//- views/layout.pug
html
  head
    title My Website Title
  body
    header
      h1 My Website
    block content
    footer
      p Footer content

Notice the block keyword in the code block above. A block in a layout file acts as a placeholder. Each block must have a name. In this example, block is defined as content. Whenever you want to use your layout file, you use the extends syntax to tell Pug that a template should include a layout.

//- views/index.pug
extends layout

block content
  p Welcome to the homepage!

In this example, index.pug extends the layout.pug template, which provides the page's base structure, including the header and footer. The block content line defines a block named content where the indented paragraph "Welcome to the homepage!" is inserted. When index.pug is rendered, the final HTML will look this this:

  
    My Website Title
  
  
    

My Website

Welcome to the homepage!

Footer content

Using Partials for Reusable Components

Partials are reusable pieces of templates that can be included in other templates, which helps to keep your code DRY (Don't Repeat Yourself). You can create partials in Pug with the include syntax.

//- views/partials/sidebar.pug
aside
  p This is the sidebar content.

In sidebar.pug defines a partial template for a sidebar with an aside element containing a paragraph of text.

//- views/layout.pug
html
  head
    title My Website Title
  body
    include partials/sidebar
    block content
    footer
      p Footer content

In layout.pug, a layout template is created with a basic HTML structure. It includes the header and sidebar partials using the include keyword, places a block content placeholder for dynamic content, and adds a footer with a paragraph of text. The final render should look something like this:

  
    My Website Title
  
  
    

Welcome to the homepage!

Footer content

Tips for optimizing Pug templates

1. Use partials and layouts wherever you can: Using partials, layouts, and helpers in Pug enhances template organization and efficiency. Partials are reusable snippets that prevent code repetition, while layouts provide a consistent structure for pages by defining common elements and extending them in individual templates.

2. Minimize the use of inline JavaScript: When writing your templates, try to use inline JavaScript sparingly. Adding huge blocks of JavaScript to your code can create issues with debugging and maintainability.

One way to reduce inline JavaScript is through the use of helpers. Helpers, defined in the server-side code, allow dynamic content within templates. You can pass a helper function to a template using the locals method on the express app.

const express = require('express');
const app = express();

app.set('view engine', 'pug');

app.locals.formatDate = function(date) {
  return new Date(date).toLocaleDateString();
};

app.get('/', (req, res) => {
  res.render('index', { title: 'Home', currentDate: new Date() });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

With the formatDate helper function set, you can use it in your Pug template like this:

p Welcome to the homepage!
p Today's date is #{formatDate(currentDate)}

Conclusion

In this guide, you learned how to serve dynamic HTML with Pug and Express. We covered basic Pug syntax, integrating Pug with Express, building dynamic pages, and advanced techniques like using layout files and partials.

Templating engines are very powerful especially when building a server-side web application. They are great for Search Engine optimization too because unlike single-page applications, the content is rendered on the server on each request.

版本声明 本文转载于:https://dev.to/daviduzondu/serving-dynamic-html-with-pug-and-express-17h5?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 左连接为何在右表WHERE子句过滤时像内连接?
    左连接为何在右表WHERE子句过滤时像内连接?
    左JOIN CONUNDRUM:WITCHING小时在数据库Wizard的领域中变成内在的加入很有趣,当将c.foobar条件放置在上面的Where子句中时,据说左联接似乎会转换为内部连接。仅当满足A.Foo和C.Foobar标准时,才会返回结果。为什么要变形?关键在于其中的子句。当左联接的右侧值...
    编程 发布于2025-06-11
  • 如何在Java中正确显示“ DD/MM/YYYY HH:MM:SS.SS”格式的当前日期和时间?
    如何在Java中正确显示“ DD/MM/YYYY HH:MM:SS.SS”格式的当前日期和时间?
    如何在“ dd/mm/yyyy hh:mm:mm:ss.ss”格式“ gormat 解决方案:的,请访问量很大,并应为procectiquiestate的,并在整个代码上正确格式不多: java.text.simpledateformat; 导入java.util.calendar; 导入java...
    编程 发布于2025-06-11
  • 您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    在javascript console 中显示颜色是可以使用chrome的控制台显示彩色文本,例如红色的redors,for for for for错误消息?回答是的,可以使用CSS将颜色添加到Chrome和Firefox中的控制台显示的消息(版本31或更高版本)中。要实现这一目标,请使用以下模...
    编程 发布于2025-06-11
  • 如何简化PHP中的JSON解析以获取多维阵列?
    如何简化PHP中的JSON解析以获取多维阵列?
    php 试图在PHP中解析JSON数据的JSON可能具有挑战性,尤其是在处理多维数组时。要简化过程,建议将JSON作为数组而不是对象解析。执行此操作,将JSON_DECODE函数与第二个参数设置为true:[&&&&& && &&&&& json = JSON = JSON_DECODE($ j...
    编程 发布于2025-06-11
  • Android如何向PHP服务器发送POST数据?
    Android如何向PHP服务器发送POST数据?
    在android apache httpclient(已弃用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    编程 发布于2025-06-11
  • 如何将MySQL数据库添加到Visual Studio 2012中的数据源对话框中?
    如何将MySQL数据库添加到Visual Studio 2012中的数据源对话框中?
    在Visual Studio 2012 尽管已安装了MySQL Connector v.6.5.4,但无法将MySQL数据库添加到实体框架的“ DataSource对话框”中。为了解决这一问题,至关重要的是要了解MySQL连接器v.6.5.5及以后的6.6.x版本将提供MySQL的官方Visual...
    编程 发布于2025-06-11
  • Python中嵌套函数与闭包的区别是什么
    Python中嵌套函数与闭包的区别是什么
    嵌套函数与python 在python中的嵌套函数不被考虑闭合,因为它们不符合以下要求:不访问局部范围scliables to incling scliables在封装范围外执行范围的局部范围。 make_printer(msg): DEF打印机(): 打印(味精) ...
    编程 发布于2025-06-11
  • 如何从PHP中的数组中提取随机元素?
    如何从PHP中的数组中提取随机元素?
    从阵列中的随机选择,可以轻松从数组中获取随机项目。考虑以下数组:; 从此数组中检索一个随机项目,利用array_rand( array_rand()函数从数组返回一个随机键。通过将$项目数组索引使用此键,我们可以从数组中访问一个随机元素。这种方法为选择随机项目提供了一种直接且可靠的方法。
    编程 发布于2025-06-11
  • Python高效去除文本中HTML标签方法
    Python高效去除文本中HTML标签方法
    在Python中剥离HTML标签,以获取原始的文本表示 仅通过Python的MlStripper 来简化剥离过程,Python Standard库提供了一个专门的功能,MLSTREPERE,MLSTREPERIPLE,MLSTREPERE,MLSTREPERIPE,MLSTREPERCE,MLST...
    编程 发布于2025-06-11
  • 如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    Red: How to Redirect Multiple User Types to Respective ActivitiesUnderstanding the ProblemIn a Firebase-based voting app with three distinct user type...
    编程 发布于2025-06-11
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-06-11
  • 在PHP中如何高效检测空数组?
    在PHP中如何高效检测空数组?
    在PHP 中检查一个空数组可以通过各种方法在PHP中确定一个空数组。如果需要验证任何数组元素的存在,则PHP的松散键入允许对数组本身进行直接评估:一种更严格的方法涉及使用count()函数: if(count(count($ playerList)=== 0){ //列表为空。 } 对...
    编程 发布于2025-06-11
  • eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    称量()和ast.literal_eval()中的Python Security 在使用用户输入时,必须优先确保安全性。强大的Python功能Eval()通常是作为潜在解决方案而出现的,但担心其潜在风险。本文深入研究了eval()和ast.literal_eval()之间的差异,突出显示其安全性含义...
    编程 发布于2025-06-11
  • 如何将来自三个MySQL表的数据组合到新表中?
    如何将来自三个MySQL表的数据组合到新表中?
    mysql:从三个表和列的新表创建新表 答案:为了实现这一目标,您可以利用一个3-way Join。 选择p。*,d.content作为年龄 来自人为p的人 加入d.person_id = p.id上的d的详细信息 加入T.Id = d.detail_id的分类法 其中t.taxonomy =...
    编程 发布于2025-06-11
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,以便更快地搜索这些前缀。理解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-06-11

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3