」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 使用 Pug 和 Express 提供動態 HTML

使用 Pug 和 Express 提供動態 HTML

發佈於2024-08-19
瀏覽:230

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]刪除
最新教學 更多>
  • 如何擴展 JavaScript 中的內建錯誤物件?
    如何擴展 JavaScript 中的內建錯誤物件?
    擴充 JavaScript 中的 Error要擴充 JavaScript 中的內建 Error 對象,您可以使用 extends 關鍵字定義 Error 的子類別。這允許您使用附加屬性或方法建立自訂錯誤。 在 ES6 中,您可以定義自訂錯誤類,如下所示:class MyError extends E...
    程式設計 發佈於2024-11-03
  • 將測試集中在網域上。 PHPUnit 範例
    將測試集中在網域上。 PHPUnit 範例
    介紹 很多時候,開發人員嘗試測試 100%(或幾乎 100%)的程式碼。顯然,這是每個團隊應該為他們的專案達到的目標,但從我的角度來看,只應該完全測試整個程式碼的一部分:您的網域。 域基本上是程式碼中定義項目實際功能的部分。例如,當您將實體持久保存到資料庫時,您的網域不負責將其持...
    程式設計 發佈於2024-11-03
  • 如何使用 SQL 搜尋列中的多個值?
    如何使用 SQL 搜尋列中的多個值?
    使用 SQL 在列中搜尋多個值建立搜尋機制時,通常需要在同一列中搜尋多個值場地。例如,假設您有一個搜尋字串,例如“Sony TV with FullHD support”,並且想要使用該字串查詢資料庫,將其分解為單字。 透過利用 IN 或 LIKE 運算符,您可以實現此功能。 使用 IN 運算子IN...
    程式設計 發佈於2024-11-03
  • 如何安全地從 Windows 登錄讀取值:逐步指南
    如何安全地從 Windows 登錄讀取值:逐步指南
    如何安全地從Windows 註冊表讀取值檢測登錄項目是否存在確定登錄項目是否存在: LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Perl", 0, KEY_READ, &hKey); if (lRes...
    程式設計 發佈於2024-11-03
  • Staat原始碼中的useBoundStoreWithEqualityFn有解釋。
    Staat原始碼中的useBoundStoreWithEqualityFn有解釋。
    在這篇文章中,我們將了解Zustand原始碼中useBoundStoreWithEqualityFn函數是如何使用的。 上述程式碼摘自https://github.com/pmndrs/zustand/blob/main/src/traditional.ts#L80 useBoundStoreWi...
    程式設計 發佈於2024-11-03
  • 如何使用 Go 安全地連接 SQL 查詢中的字串?
    如何使用 Go 安全地連接 SQL 查詢中的字串?
    在Go 中的SQL 查詢中連接字串雖然文字SQL 查詢提供了一種簡單的資料庫查詢方法,但了解將字串文字與值連接的正確方法至關重要以避免語法錯誤和類型不匹配。 提供的查詢語法:query := `SELECT column_name FROM table_name WHERE colu...
    程式設計 發佈於2024-11-03
  • 如何在 Python 中以程式設計方式從 Windows 剪貼簿檢索文字?
    如何在 Python 中以程式設計方式從 Windows 剪貼簿檢索文字?
    以程式設計方式存取Windows 剪貼簿以在Python 中進行文字擷取Windows 剪貼簿充當資料的臨時存儲,從而實現跨應用程式的無縫數據共享。本文探討如何使用 Python 從 Windows 剪貼簿檢索文字資料。 使用 win32clipboard 模組要從 Python 存取剪貼簿,我們可...
    程式設計 發佈於2024-11-03
  • 使用 MySQL 預存程序時如何存取 PHP 中的 OUT 參數?
    使用 MySQL 預存程序時如何存取 PHP 中的 OUT 參數?
    使用MySQL 預存程序存取PHP 中的OUT 參數使用MySQL 儲存程序存取PHP 中的OUT 參數使用PHP 在MySQL 中處理預存程序時,取得由於文件有限,「 OUT”參數可能是一個挑戰。然而,這個過程可以透過利用 mysqli PHP API 來實現。 使用mysqli$mysqli =...
    程式設計 發佈於2024-11-03
  • 在 Kotlin 中處理 null + null:會發生什麼事?
    在 Kotlin 中處理 null + null:會發生什麼事?
    在 Kotlin 中處理 null null:會發生什麼事? 在 Kotlin 中進行開發時,您一定會遇到涉及 null 值的場景。 Kotlin 的 null 安全方法眾所周知,但是當您嘗試新增 null null 時會發生什麼?讓我們來探討一下這個看似簡單卻發人深省的情況吧! ...
    程式設計 發佈於2024-11-03
  • Python 字串文字中「r」前綴的意思是什麼?
    Python 字串文字中「r」前綴的意思是什麼?
    揭示「r」前綴在字串文字中的作用在Python中創建字串文字時,你可能遇到過神秘的“r” ” 前綴。此前綴具有特定的含義,可能會影響字串的解釋,尤其是在處理正則表達式時。“r”前綴表示該字串應被視為「原始」字串。 &&&]在常規字串中,轉義序列如\ n 和\t 被解釋為表示特殊字符,例如換行符和製表...
    程式設計 發佈於2024-11-03
  • 如何解決舊版 Google Chrome 的 Selenium Python 中的「無法找到 Chrome 二進位」錯誤?
    如何解決舊版 Google Chrome 的 Selenium Python 中的「無法找到 Chrome 二進位」錯誤?
    在舊版Google Chrome 中無法使用Selenium Python 查找Chrome 二進位錯誤在舊版Google Chrome 中使用Python 中的Selenium 時,您可能會遇到以下錯誤:WebDriverException: unknown error: cannot find ...
    程式設計 發佈於2024-11-03
  • `.git-blame-ignore-revs` 忽略批量格式變更。
    `.git-blame-ignore-revs` 忽略批量格式變更。
    .git-blame-ignore-revs 是 2.23 版本中引入的一项 Git 功能,允许您忽略 git Blame 结果中的特定提交。这对于在不改变代码实际功能的情况下更改大量行的批量提交特别有用,例如格式更改、重命名或在代码库中应用编码标准。通过忽略这些非功能性更改,gitblame 可以...
    程式設計 發佈於2024-11-03
  • 掌握函數參數:JavaScript 中的少即是多
    掌握函數參數:JavaScript 中的少即是多
    嘿,開發者們! ?今天,讓我們深入探討編寫乾淨、可維護的 JavaScript 的關鍵方面:管理函數參數 太多參數的問題 你有遇過這樣的函數嗎? function createMenu(title, body, buttonText, cancellable, theme, fon...
    程式設計 發佈於2024-11-03
  • 如何使用 FastAPI WebSockets 維護 Jinja2 範本中的即時評論清單?
    如何使用 FastAPI WebSockets 維護 Jinja2 範本中的即時評論清單?
    使用FastAPI WebSockets 更新Jinja2 範本中的項目清單在評論系統中,維護最新的評論清單至關重要提供無縫維護的使用者體驗。當新增評論時,它應該反映在模板中,而不需要手動重新加載。 在Jinja2中,更新評論清單通常是透過API呼叫來實現的。然而,這種方法可能會引入延遲並損害使用者...
    程式設計 發佈於2024-11-03
  • 掌握 SQL 查詢:&#教師薪資格查詢&# 項目
    掌握 SQL 查詢:&#教師薪資格查詢&# 項目
    您是否希望提升 SQL 技能並學習如何有效管理 MySQL 資料庫? LabEx 提供的教師薪資格式查詢專案就是您的最佳選擇。這個綜合計畫將引導您完成在大學資料庫中查詢和格式化教職員工薪資的過程,為您提供必要的知識和技能,以在資料管理工作中脫穎而出。 介紹 在這個引人入勝的專案中,...
    程式設計 發佈於2024-11-03

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3