Pug 初步使用及问题

Pug 是一个健壮的、优雅的、功能丰富的node.js模板引擎。
Pug 原名不叫 Pug,而是大名鼎鼎的 jade,因为商标的原因改名 Pug,但是语法仍然没变。

(一)为什么要用 Pug

在开发官网的项目中,由于需求简单,且有大量可复用代码存在,让人不由自主地想对其进行组件化。然而由于 React 的 SEO 问题,只能选用其他的技术栈,Pug 就成了首选。

Pug 的优点很多,在官网项目里最实用的就是模板继承 Inheritance包含 Include,这两个特性其实已经实现了我们想要的组件化的功能。

(二)Webpack 配置

  1. 由于需要输出HTML,所以需要安装html-webpack-plugin

    1
    $ npm i -D html-webpack-plugin
  2. 然后我们需要安装一下pugpug-html-loader

    1
    $ npm i -D pug html-loader pug-html-loader
  3. 接下来就可以进入webpack.config.js配置处理.pug文件的 loader 啦

    1
    2
    3
    4
    5
    6
    7
    8
    ...
    module: {
    rules: [{
    test: /\.pug$/,
    use: ['html-loader','pug-html-loader']
    }]
    },
    ...

(三)基础语法知识

Pug 的语法很简单,有HTMLJSx基础的话读官方文档半天就能上手,需要注意的是 Pug 用缩进来代表层级关系,这样的好处就是避免嵌套过多时由于闭合问题报错,所以最好把编辑器 Tab 调成 2。

类名和ID名
1
2
a.button
a(class="button")

编译后:

1
2
<a class="button"></a>
<a class="button"></a>

属性

属性可以用()包裹起来,属性之间用逗号隔开

1
a(href="google.com",title="google")

编译后

1
<a href="google.com" title="google"></a>

文本内容

单行文本

1
a(href="google.com",title="google") Hello World

多行文本

1
2
3
4
5
p.
asdfasdfa
asdfasd
adsfasd
asdfasdfa

JavaScript

在 Pug 中写JS代码需要在行首加一个-,但是在条件判断时由于括号是可选的,所以可以省略行首的-,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- var user = { description: 'foo bar baz' }
- var authorised = false
#user
if user.description
h2.green 描述
p.description= user.description
else if authorised
h2.blue 描述
p.description.
用户没有添加描述。
不写点什么吗……
else
h2.red 描述
p.description 用户没有描述

Mixin

Mixin,顾名思义,就是重复代码块,使用也很简单:

1
2
3
4
5
6
//- 定义
mixin pet(name)
li.pet = name
//- 使用
+pet('cat')
+pet('dog')

(五)Include 和 Inheritance

Include

包含(include)功能允许我们把另外的文件内容插入进来

比如我们现在有一个.pug文件

1
2
3
4
//- includes/head.pug
head
title 我的网站
script(src='/javascripts/app.js')

那么我们就可以在另一个文件里引用它,是不是基本实现了我们组件化的需求呢

1
2
3
4
5
6
//- index.pug
doctype html
html
include includes/head.pug
body
h1 欢迎我的网站

Inheritance

Pug 支持使用 block 和 extends 关键字进行模板的继承。一个称之为“块”(block)的代码块,可以被子模板覆盖、替换

比如我们创建了一个默认布局

1
2
3
4
5
6
7
8
9
10
11
//- layout.pug
html
head
title 我的站点 - #{title}
block scripts
script(src='/jquery.js')
body
block content
block foot
#footer
p 一些页脚的内容

现在我们可以引用这个布局

1
2
3
4
5
6
7
8
9
10
11
extends layout.pug

block scripts
script(src='/jquery.js')
script(src='/pets.js')

block content
h1= title
- var pets = ['cat', 'dog']
each petName in pets
include pet.pug

(四)引入json文件遇到的问题

Pug 的 include机制是:包含(include)功能允许您把另外的文件内容插入进来,但是被包含的如果不是 Pug 文件,那么就只会当作文本内容来引入。

这样的话我们引入json文件就很困难,最后的解决办法是建立一个与需要引入json文件的pug文件同名的js文件,

1
2
3
exports.array = [{
......
}]

然后在webpack.config.js中寻找和.pug文件同名的.js文件

1
2
3
4
//const pages = glob.sync('./your/pages/path/*.pug');
pages.map((page)=>{
let dataFilePath = page.replace(/\.pug$/, '.js');
}

我们还需要配置一下相应的loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module: {
rules: [{
test: /\.(pug|html)/,
use: [{
loader: "pug-html-loader",
options: {
data: {
js(){
if(!require('fs').existsSync(dataFilePath)) return {};
delete require.cache[require.resolve(dataFilePath)];
return require(dataFilePath);
}
}
},
}]
}]
}

最后在模板文件的head里加上就大功告成啦~

1
- data = js()