Natcha Luang - Aroonchai

Trust me I'm Petdo

Bangkok, Thailand

[Hugo] รู้จักกับ Hugo เครื่องมือสำหรับสร้าง static website

ตอนนี้ผมย้าย website จาก Ghost มา Hugo เป็นที่เรียบร้อยแล้ว เลยถือโอกาสเขียนเล่าถึงการ setup และการ deploy ด้วย automation tool จะเป็นอย่างไร ไปติดตามกันเลยครับ

สารบัญ

อะไรคือเหตุผลที่เปลี่ยนมาใช้ Hugo?

ในยุคสมัยนิยมแห่ง Jekyll ที่ใคร ๆ ก็ใช้งานกัน ผมเองก็เคยใช้งานอยู่ในช่วงนึง เวลาที่เขียนแต่ละบทความผมก็จะสั่ง reload เพื่อดูบทความอยู่ตลอดเวลา ทีนี้เวลาใช้งาน Jekyll เนี่ยก็นิยมใช้พวก Gulp หรือ Grunt สำหรับสั่ง auto compile แต่มันช้ามาก ๆ เลยกลายเป็นความเบื่อหน่ายจนไม่อยากจะใช้งานเลย ทำให้กลับมาใช้งาน WordPress อยู่ช่วงนึงก่อนจะไปใช้ Ghost และก็มาถึง Hugo อย่างตอนนี้

ข้อดีที่สุดของ Hugo คือมันถูกสร้างด้วยภาษา Go ใช่แล้วแค่นี้ผมก็เอียงมาแล้ว เพราะนี้เป็นภาษาที่ผมเห็นแล้วว่าดีที่สุดในตอนนี้ (โอกาสหน้าจะมาเขียนอวยภาษานี้อีกที) มันเร็วมากในระดับ millisecond เลยน่ะและยังมี local server ที่สามารถ detect file change พร้อมกับทำ live reload ได้ทันทีเมื่อเราแก้ไขไฟล์อะไรก็ตามใน project ดูดีมากเลยใช่ไหมล่ะ! ถ้าแค่ใช้งานง่าย ๆ ไม่ต้องมานั่งเขียน compile script เองสักบรรทัด!

และที่สำคัญยังมี theme ฟรีอีกเยอะ (อ่ะแต่ Jekyll ก็มีเยอะเหมือนกันน่ะ) ลองดูตัวอย่าง theme ที่ชอบได้จาก ลิงค์นี้ และถ้าอยากสร้างเองก็ไม่ยากมี document พร้อม

จะรออะไรอยู่ล่ะ

เลือกใช้งาน Github หรือ AppEngine ดี?

ก่อนจะไปเริ่มการใช้งาน Hugo ผมขอคั่นด้วยคำถามนี้คือระหว่างสองบริการนี้ (จริงมีอีกเยอะ) อย่างไหนดีกว่ากัน ต้องบอกก่อนว่าสำหรับ GitHub การที่เราจะ host website ไว้บนนั้น จำเป็นต้องสร้าง repository ก่อน จากนั้นจึงจะสามารถสร้าง GitHub page ได้ ซึ่งถ้าเป็น free plan เราจะไม่สามารถสร้าง private repository ได้ จนกว่าจะเปลี่ยนเป็น plan ที่ต้องเสียเงิน ซึ่งผมเองยังไม่คิดว่าจะต้องเสียเงินในตอนนี้ และอีกข้อคือ website ของผมเองยังมีปริมาณ traffic ที่ค่อนข้างน้อย และประกอบกับ Google AppEngine มีบริการที่เรียก free quota ต่อวัน ซึ่งถ้าเราใช้ resource ไม่เกิน free quota ต่อวันแล้ว เราจะสามารถใช้งานบริการนั้นได้ฟรีเลย

ดังนั้นผมจึงเลือกใช้งาน Google AppEngine ที่คิดค่าใช้งานเป็นปริมาณ resource ที่เรียกว่า instance hours โดยจะมี free quota ต่อวันอยู่ที่ 28 instance hours (เยอะมาก) โดยผมทดลองดูจาก website ตัวเองที่ host อยู่ประมาณ 1 เดือนพบว่า instance hours ที่ใช้ต่อวันมากที่สุดยังไม่เกิน 2~3 instance hours เลยเพราะตัว website เป็น static file ทั้งหมด ทำให้ไม่จำเป็นต้องเสีย resource ในการประมวลผลเลย!

ไม่เชื่อหรอมีหลักฐานให้ดูจริง ๆ น่ะ

Instance hours latest 30 days

ติดตั้ง Hugo

การติดตั้ง Hugo ง่ายมากเพราะโปรแกรมถูกสร้างด้วย Go จึงทำให้สามารถ compile และติดตั้งได้กับทุก OS (Windows, Linux และ OS X) สำหรับ OS อื่นสามารถดูวิธีการติดตั้งได้จาก Quick Start Guide ของ Hugo ส่วนใครที่ใช้งาน Mac ดูวิธีติดตั้งด้วย Homebrew กันได้เลย

เปิด terminal ขึ้นมาจากนั้นใช้คำสั่ง

$ brew install hugo

ทดลองเรียกคำสั่ง hugo --help เพื่อดูว่าการติดตั้งใช้งานได้เรียบร้อย

Hello, world!

เมื่อติดตั้ง Hugo เสร็จเรียบร้อยแล้วเราก็มาลองสร้าง post แรกกันเลยดีกว่า ก่อนอื่นต้องสร้าง project สำหรับ website กันก่อน ผมสร้าง folder ชื่อว่า myweb จากนั้นสั่งให้ Hugo สร้าง project structure ด้วยคำสั่งนี้

$ hugo new site .

เมื่อ run คำสั่ง new site Hugo จะสร้าง folder ใน project ของเราออกมาเป็นแบบนี้

myweb/
├── archetypes
├── config.toml
├── content
├── data
├── layouts
└── static

จากนั้นสั่งให้ Hugo สร้าง post ด้วยคำสั่ง

$ hugo new post/hello-world.md

จะได้ไฟล์ hello-world.md อยู่ที่

content/
└── post
    └── hello-word.md

เมื่อเปิดดูจะเห็นข้างในไฟล์มีหน้าตาประมาณนี้

+++
date = "2015-12-17T10:42:44+07:00"
draft = true
title = "hello word"

+++

ให้เราพิมพ์บทความต่อตากบรรทัดที่เป็น +++ เป็นต้นไป และในการเขียน post จะใช้ syntax ที่เรียกว่า Markdown สามารถดูรายการ syntax ทั้งหมดได้ ที่นี่

ในระหว่างการแก้ไข post ถ้าเราต้องการดูว่า post มีหน้าตาเป็นอย่างไรสามารถใช้คำสั่ง

$ hugo server -w

เพื่อทำ live reload ได้ แต่ในตอนนี้เรายังไม่มี theme ที่จะเอาไว้แสดง post ถ้า run แล้วพบหน้า blank ก็ไม่ต้องตกใจน่ะครับ

ติดตั้ง theme

เราจะติดตั้ง theme จากรายการที่มีในหน้า document ของเว็บ ส่วนใครที่ใช้ theme อื่น ๆ ก็สามารถศึกษาวิธีติดตั้งได้เองจากผู้พัฒนาครับ

โดย theme ที่ผมจะใช้ชื่อว่า Cactus เริ่มจาก clone project ของ theme ที่เราจะใช้ไว้ที่ project folder ให้ชื่อว่า themes

$ mkdir themes
$ cd themes
$ git clone [email protected]:digitalcraftsman/hugo-cactus-theme.git

จากนั้นให้เพิ่ม parameter -t ต่อท้ายคำสั่ง hugo server แบบนี้

$ hugo server -w -t hugo-cactus-theme

หรือจะใช้การแก้ไขที่ config.toml แบบนี้ก็ได้เช่นกัน

theme = "hugo-cactus-theme"

ทีนี้เมื่อ run Hugo server ก็จะได้หน้าตาแบบนี้

Cactus theme

Generate static files

หลังจากติดตั้ง theme และเขียนบทความเรียบร้อยแล้ว ทีนี้ถึงขั้นตอนการสร้าง static file สำหรับอัพโหลด ซึ่งเป็นขั้นตอนการทำงานที่ง่ายมาก ๆ แค่รันคำสั่ง

$ hugo

เท่านั้นก็เสร็จเรียบร้อยแล้ว โดยเมื่อเรา run คำสั่งแล้วจะมีรายการไฟล์ที่ถูกสร้างขึ้นอยู่ที่ public/

public/
├── 404.html
├── index.html
├── index.xml
├── post
│   ├── hello-word
│   │   └── index.html
│   ├── index.html
│   └── index.xml
└── sitemap.xml

และ log ว่าเราสร้างอะไรอย่างไรบ้างแบบนี้

0 draft content
0 future content
1 pages created
0 paginator pages created
0 tags created
0 categories created
in 5 ms

เท่านี้ website เราก็พร้อมสำหรับการใช้งานได้แล้วครับ

อัพโหลด website ขึ้น Google AppEngine

แน่นอนอย่างที่เกริ่นไว้แล้วว่าผมใช้ Google AppEngine เป็น host สำหรับวาง website ตอนนี้ก็มาถึงขั้นตอนการ deploy สำหรับใครที่ไม่มีบัญชี Gmail ก็คงต้องสมัครกันก่อนเพื่อใช้งาน Google services ทั้งหลาย

จากนั้นข้อสำคัญอย่างนึงคือผมจะสร้าง project สำหรับ host static website ก็จริง แต่ AppEngine บังคับว่าเราต้องเลือก runtime ภาษาใดภาษานึงสำหรับ project ดังนั้นผมจะเลือก Go เพราะว่าเป็นภาษาที่ประหยัด resource มากที่สุด ซึ่งเราก็แค่เขียน net/http สำหรับ handle route ง่าย ๆ ทิ้งไว้สักอันก็ได้ เพื่อให้ runtime compile ตอน deploy project

main.go

func init() {
  http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
    http.Redirect(rw, r, "/", http.StatusFound)
    })
}

สร้าง project

เอาล่ะสมมติว่ามีบัญชี Gmail กันแล้วก็ไปที่หน้าเว็บของ AppEngine กัน จากนั้นคลิกที่ Create a project ใส่ Project name และก็กด Create รอจนกว่าจะเสร็จก็ใช้งานได้แล้ว จะลองเข้าเว็บไซต์ของ project ดูก็ได้เช่นกัน โดยใช้ชื่อ project-id เป็น sub domain name ของ appspot.com ตัวอย่าง https://proven-grid-116204.appspot.com

AppEngine new project

Config app.yaml

ขั้นตอนสุดท้ายเราต้อง config app.yml เพื่อให้ AppEngine รู้จัก route ของ website ไม่อย่างนั้นจะมีแต่ 404 แน่ ๆ ครับ

app.yml

application: your-project-id
version: 1
runtime: go
api_version: go1

handlers:
  - url: /
    static_files: public/index.html
    upload: public/index.html

  - url: /robots.txt
    static_files: public/robots.txt
    upload: public/robots.txt

  - url: /css/(.*\.css)
    mime_type: text/css
    static_files: public/css/\1
    upload: public/css/(.*\.css)

  - url: /js/(.*\.js)
    mime_type: text/javascript
    static_files: public/js/\1
    upload: public/js/(.*\.js)

  - url: /font/(.*\.(eot|svg|ttf|woff|woff2))
    static_files: public/font/\1
    upload: public/font/(.*\.(eot|svg|ttf|woff|woff2))

  - url: /(.*\.(bmp|gif|ico|jpeg|jpg|png))
    static_files: public/\1
    upload: public/(.*\.(bmp|gif|ico|jpeg|jpg|png))

  - url: /(.*\.xml)
    static_files: public/\1
    upload: public/(.*\.xml)

  - url: /(categories|page|post|tags|\d{4})/(.*)/
    static_files: public/\1/\2/index.html
    upload: public/(.*\.html)

  - url: /(categories|page|post|tags|\d{4})/(.*)
    static_files: public/\1/\2/index.html
    upload: public/(.*\.html)

  - url: /.*
    static_files: public/404.html
    upload: public/404.html

skip_files: ^(.*/)?((archetypes/.*)|(go_appengine/.*)|(index\.yaml)|(index\.yml)|(config\.yaml)|(#.*#)|(.*~)|(.*\.py[co])|(.*\.po)|(.*\.pot)|(\..*)|(manage\.py)|(README\.md)|(LICENSE)|(content\/.*)|(data\/.*)|(static\/.*)|(layouts\/.*)|(\.git\/.*)|(\.gitignore))$

จากนั้นก็สั่งอัพโหลดไฟล์ทั้งหมดด้วยคำสั่ง

$ appcfg.py update .

เป็นอันเสร็จสิ้นการติดตั้ง Hugo บน Google AppEngine ตอนต่อไปเราจะมา setup domain name พร้อมกับเปิดใช้งาน free SSL จาก CloudFlare กันครับ

[AppEngine] setup SSL และเปิดใช้งาน custom domain name


อ้างอิง

Comments