使用 pug 跟 stylus 把一個網頁寫得更簡潔

linnil1
7 min readOct 1, 2021

--

https://nyadoi.linnil1.me

介紹

大家都知道網頁是瀏覽器依據 html + css + javascript 產生出來的,但是 html 的標記語法很煩人,一堆 </> 而且還要 closing tag,css 的語法則是沒有變數跟 hierarchy 的設計,這對維護跟開發都不友善

所以前端社群就開發了新的好用的工具,比如說 pug 是簡化 html 的工具,stylus, sass 是把 css 做得更有架構, vue 則是把 html, DOM tree 很好的跟 javascript 結合

以下我會用封面圖的這個簡單網頁,簡單的示範使用了 pug stylus 會有什麼樣的差別(這個網頁沒有動態的成分,也就是這次我不會介紹到 vue 跟 javascript)

純 HTML

故事是這樣的,受到九壹的圖的啟發 (原梗來自 iphone 13 就. 很. Pro),按照他的那張圖做了一個網頁

九壹繪製原圖

當然這沒什麼,只要你熟 flex,你就能排出你想要的板

左: css (部分) 右: html

接著就是把這個 html 改寫 (其實是因為想試試看其他工具)

webpack — 在使用 pug stylus 前

這裡要先提一下開發工具 webpack,是個打包工具,能把專案裡面的所有 html, css, javascript, assets(圖片等) 打包成幾個中型檔案。在這個網站中,他扮演著把瀏覽器不認識的 pug 跟 stylus 檔案 precompile 成 html, css 。

如下面的 webpack.config.js 設定

  • 預設 index.pug 會變成主要的 index.html
  • *.pug 會被 pug-loader compile 成 html
  • *.styl 會被 stylus-loader compile 成 css,緊接著用 css-loader 包好
  • *.png *.jpg 視為檔案
pug stylus 的 precompile 設定

打包後的資料夾會像下面這樣, webpack 會幫你重新命名 (如果有 js 會變成 index.xxxxxx.js),原因是如果沒有重新命名,瀏覽器可能會因為看到同樣的檔案名稱,就只接使用快取而不會載入新的檔案(可以省流量,速度也會比較快)。

$ ls dist/ 
062a2857e1f5104bf296aac5e6352c4b.png c5f954d9a802b839fa468343876bb4e8.png
index.html
4c6a1c74b774b26d98cc5ef37cac4bd8.webp f963dcac51d5020e10f30ef102b9141d.png

webpack 還有功能是 webpack-dev-server ,能開啟一個暫時的 host 並有 hot-reload 的功能,會偵測到檔案有被更動,會重新 compile,出新的檔案,然後幫你重整,簡單來說就是可以不用手動按 F5

pug

這是一個 template engine, pug 語法寫成的 template 可以 render 變成 html。最大的特色是用 indent 代表是在哪一層,其實很合理,因為平常寫 html 也會有這個習慣

而 pug 提供很多可以省略的部分 比如說 <div class=’.nyadoi’>…</div>可以直接寫成 .nyadoi … ,所以相較於上面,這種寫法清楚很多

可見範圍的 pug

注意一下圖片用 require 去讀,讓 webpack 知道這張圖片最後會被打包,當 webpack 幫圖片改名時,這裡也會處理好,我們不用擔心

stylus

我希望可以全部 js, css 寫在同一個 html 跟剛剛的純 HTML 一樣 (如果是大專案的話這是奇怪的要求),所以用 pug 的 Include plain text 跟 Interpolation 。使用 Interpolation 是因為我需要用 require觸發把 stylus 檔轉成 css 的機制

Pug 處理css js 的部分

stylus 則像語言,用這個語言產生 css,雖然在這個示範中用的很少很厲害的功能。

這類的 css preprocessor 通常都會支援變數跟 nested 的結構,stylus 還可以不用 大括號、分號、冒號。相較於原本很零散的 css ,我下面的 code (擷取部分自 index.styl),試著把類似功能的 css 寫在一起

  1. 我在前面有定義變數 small-win-size = 576px 所以要調整 responsive 的時候 (media 部分),就不用兩邊一起改
  2. 左上跟右上是 responsive 的部分,當使用小螢幕(手機)看網頁的時候的 font-size, margin-top 跟 flex 方向的設定,寫在一起的確看起來比較輕鬆
  3. 左下是我每行文字的 margin 全部寫在同一塊,就不會忘記哪裡有設定,不用來回檢查 (這個一般 css 也能做到就是ㄌ)
  4. 右下是我把 css 排成原本 html 的架構,讀起來好像也可以?
部分 stylus code

其他部分

其他部分應該自己看就好ㄌ(這個專案很小ㄉ OK ㄉ),Github 連結就放這裡

https://github.com/linnil1/nyadoi_oh_so_cute

注一、 我是習慣用 cloudflare 來放網站 (我之前寫的 CDN 的說明),當然用 GitHub Page 也不是不行,看人的習慣。

注二、工具的安裝一律用 yarn

yarn install
yarn add -D webpack ...
yarn start
yarn build

後記

我不是前端工程師,如果有寫網頁的 project 我會用 Vue,Vue-cli 其實都幫你包好設定好 webpack, webpack config, dev-server, pug, stylus 了,所以通常我都不知道我在幹嘛(反正前端人口多,stackoverflow 通常都有解答)。所以這次我想自己兜,說不定可以更了解那些設定,然後順便賺一篇非本業的文章 XD。第二個原因是這個網站只是一頁而已,不需要用 Vue 來殺雞。第三是推廣喵朵伊,是一個很活潑,很可愛的 vtuber

覺得有幫助的話,記得按 clap 支持我

--

--

linnil1

目前做生物資訊與演算法,過去做過 Machine Vision(Deep learning),維護伺服器(k8s, docker),部分IOT(rpi, arduino)