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

使用 Pug 和 Express 提供動態 HTML

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

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]刪除
最新教學 更多>
  • jQuery.height()為何返回隱藏元素的值?
    jQuery.height()為何返回隱藏元素的值?
    在這種情況下,具有ID“ target”的元素具有通過CSS設置為“無”的元素。但是,當使用$(“#target”)檢查其高度時。 If an element has an offsetWidth of 0 (considered "hidden" by jQuery), th...
    程式設計 發佈於2025-04-12
  • HTML5全屏API使用指南 - SitePoint
    HTML5全屏API使用指南 - SitePoint
    If you don’t like change, perhaps web development isn’t for you. I previously described the Full-Screen API in late 2012 and, while I claimed the im...
    程式設計 發佈於2025-04-12
  • 如何通過單擊鼠標單擊的div中編程選擇所有文本?
    如何通過單擊鼠標單擊的div中編程選擇所有文本?
    在鼠標上選擇div文本單擊帶有文本內容,用戶如何使用單個鼠標單擊單擊div中的整個文本?這允許用戶輕鬆拖放所選的文本或直接複製它。 在單個鼠標上單擊的div元素中選擇文本,您可以使用以下Javascript函數: function selecttext(canduterid){ if(d...
    程式設計 發佈於2025-04-12
  • Java中ArrayList轉String\[\]數組方法
    Java中ArrayList轉String\[\]數組方法
    在java Converting using toArray() MethodThe toArray() method is a convenient way to convert an ArrayList to a String[].它接受數組作為參數,其中的元素被複製到其中。以下代碼片段演示了...
    程式設計 發佈於2025-04-12
  • 如何干淨地刪除匿名JavaScript事件處理程序?
    如何干淨地刪除匿名JavaScript事件處理程序?
    刪除匿名事件偵聽器將匿名事件偵聽器添加到元素中會提供靈活性和簡單性,但是當要刪除它們時,可以構成挑戰,而無需替換元素本身就可以替換一個問題。 element? element.addeventlistener(event,function(){/在這里工作/},false); 要解決此問題,請考...
    程式設計 發佈於2025-04-12
  • 我的Lightspeed服務器是否啟用了mod_rewrite?
    我的Lightspeed服務器是否啟用了mod_rewrite?
    使用.htaccess規則在Lightspeed服務器上不按預期運行的。本文提供了一個解決方案來驗證其在此類服務器上的狀態。 使用phpinfo() For Lightspeed servers, the following command can be used:sudo a2enmod rew...
    程式設計 發佈於2025-04-12
  • 如何使用“ JSON”軟件包解析JSON陣列?
    如何使用“ JSON”軟件包解析JSON陣列?
    parsing JSON與JSON軟件包 QUALDALS:考慮以下go代碼:字符串 } func main(){ datajson:=`[“ 1”,“ 2”,“ 3”]`` arr:= jsontype {} 摘要:= = json.unmarshal([] byte(...
    程式設計 發佈於2025-04-12
  • 哪種在JavaScript中聲明多個變量的方法更可維護?
    哪種在JavaScript中聲明多個變量的方法更可維護?
    在JavaScript中聲明多個變量:探索兩個方法在JavaScript中,開發人員經常遇到需要聲明多個變量的需要。對此的兩種常見方法是:在單獨的行上聲明每個變量: 當涉及性能時,這兩種方法本質上都是等效的。但是,可維護性可能會有所不同。 第一個方法被認為更易於維護。每個聲明都是其自己的語句,使...
    程式設計 發佈於2025-04-12
  • 如何使用Python理解有效地創建字典?
    如何使用Python理解有效地創建字典?
    在python中,詞典綜合提供了一種生成新詞典的簡潔方法。儘管它們與列表綜合相似,但存在一些顯著差異。 與問題所暗示的不同,您無法為鑰匙創建字典理解。您必須明確指定鍵和值。 For example:d = {n: n**2 for n in range(5)}This creates a dict...
    程式設計 發佈於2025-04-12
  • \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    答案: 在大多數現代編譯器中,while(1)和(1)和(;;)之間沒有性能差異。編譯器: perl: 1 輸入 - > 2 2 NextState(Main 2 -E:1)V-> 3 9 Leaveloop VK/2-> A 3 toterloop(next-> 8 last-> 9 ...
    程式設計 發佈於2025-04-12
  • Day - HTML與CSS
    Day - HTML與CSS
    [2 HTML代表超級文本標記語言。 HTML是用於創建網頁的標準語言。 它使用標籤或元素系統定義了網頁的結構。 [2 CSS代表級聯樣式表。 它用於樣式和格式化使用HTML創建的網頁的佈局。 它控制著顏色,字體,間距,定位和響應式設計之類的東西。 CSS允許您將結構(HTML)與設計...
    程式設計 發佈於2025-04-12
  • 如何修復\“常規錯誤:2006 MySQL Server在插入數據時已經消失\”?
    如何修復\“常規錯誤:2006 MySQL Server在插入數據時已經消失\”?
    How to Resolve "General error: 2006 MySQL server has gone away" While Inserting RecordsIntroduction:Inserting data into a MySQL database can...
    程式設計 發佈於2025-04-12
  • 為什麼我在Silverlight Linq查詢中獲得“無法找到查詢模式的實現”錯誤?
    為什麼我在Silverlight Linq查詢中獲得“無法找到查詢模式的實現”錯誤?
    查詢模式實現缺失:解決“無法找到”錯誤在Silverlight應用程序中,嘗試使用LINQ建立LINQ連接以錯誤而實現的數據庫”,無法找到查詢模式的實現。”當省略LINQ名稱空間或查詢類型缺少IEnumerable 實現時,通常會發生此錯誤。 解決問題來驗證該類型的質量是至關重要的。在此特定實例...
    程式設計 發佈於2025-04-12
  • 定制Seaborn圖表尺寸,完美打印輸出
    定制Seaborn圖表尺寸,完美打印輸出
    在海洋繪圖中自定義圖形大小用於打印 1。使用seaborn set_theme方法: RC參數允許您使用字典以英寸為單位指定所需的圖形大小。利用matplotlib rcparams: = 11.7,8.27 此方法允許直接操縱matplotlib的配置來設置圖形大小。 附加說明:探索seab...
    程式設計 發佈於2025-04-12
  • 如何使用PHP將斑點(圖像)正確插入MySQL?
    如何使用PHP將斑點(圖像)正確插入MySQL?
    essue VALUES('$this->image_id','file_get_contents($tmp_image)')";This code builds a string in PHP, but the function call fil...
    程式設計 發佈於2025-04-12

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

Copyright© 2022 湘ICP备2022001581号-3