Building Blazing-fast static site with Gatsby

สวัสดีย์ ~ วันนี้เราจะมาเปิดซีรีส์ Tutorial ใหม่กัน หลังจากที่ไม่ได้เขียน Tutorial ที่เป็นซีรีส์มานานหลายปีแล้ว ในรอบนี้เรามาด้วย Tutorial ของ Gatsby ที่ไม่ใช่ The Great Gatsby โดยใน Tutorial ชุดนี้จะใช้ Gatsby V2 Beta โดย Feature ที่จะทำก็คือเหมือนกับเว็บนี้เลย

Gatsby คืออะไร ?

Gatsby เป็น Static Site Generator เหมือนกับ Middleman หรือ Jekyll ที่บางคนอาจจรู้จักกันมาบ้าง ถ้าใครสังเกตเว็บใหม่ผมที่ทุกคนกำลังอ่านอยู่ตอนนี้เบื้องหลังของมันก็คือ Gatsby นี่แหละ

ทำให้แน่นอนว่า Gatsby ทำงานโดยใช้ JAM Stack ที่ประกอบด้วย

  • J avascript ที่จะทำงานอยู่บน Client โดยอาจจะใช้ Frontend Library หรือ Framework อื่นนอกจาก React เช่น Vue.js ก็ได้เหมือนกัน
  • A PI ที่เป็นเหมือนคลังคำสั่งของเราที่เราสามารถเอามา Reuse และเรียกผ่าน HTTP Request บน Javascript ซึ่งเราก็เขียนภาษาอะไรก็ได้ ขอแค่ I/O ผ่าน HTTP เท่านั้น
  • M arkup เป็นเหมือน Template ที่มันจะสร้างตอนที่เรา Generate Site ออกมา ถ้าเป็นเว็บนี้ก็คือบทความก็จะเป็นส่วนของ Markup นั่นเอง

จากทั้ง 3 ข้อทำให้เว็บที่ใช้ JAM Stack มี Performance ที่สูงปรี๊ดเพราะ Web Server แค่ Serve File เท่านั้นไม่ต้องคิดอะไรเลย เพราะ Client จะเป็นคนทำทั้งหมดแทน นอกจากนั้นยังทำให้เราสามารถ Scale ได้ง่ายขึ้น เพราะตัว Web ที่ Generate ออกมาเป็นเป็นแค่ Static File ที่เราสามารถเอาไปแปะไว้ที่ไหนก็ได้ จะทำ Caching ก็ง่ายหยิบขึ้น CDN ก็ชิวแล้ว

ข้อถัดมาคือ มีความปลอดภัยมากขึ้น จากเมื่อก่อนที่เราจะฝัง Operation ต่าง ๆ ลงในหน้าเว็บโดยตรงเลย ทำให้เป็นช่องโหว่ให้คนที่ไม่ดี เข้ามาโจมตีหรือทำไม่ดีไม่ร้ายกับข้อมูลของเราได้ แต่มาตอนนี้เราแค่ Serve File เท่านั้นก็ทำให้เราสามารถตั้งค่าเรื่องของความปลอดภัยอะไรได้มากขึ้น เพราะ Web Server มันไม่ต้องทำอะไรเลยนอกจาก Serve File

และสุดท้ายคือ ทำให้การพัฒนามันสะดวกมากขึ้น จากเมื่อก่อนที่ Frontend และ Backend Developer ต้องเขียน Code ลงไปเผลอ ๆ ไฟล์เดียวกันก็ทำให้การทำงานมันยากขึ้น แต่พอมาใน JAM Stack ฝั่ง Backend ก็แค่เขียน API ขึ้นมาให้ฝั่ง Frontend เรียกแค่บอกว่าต้องใช้อะไรบ้าง ไปที่ไหนแค่นั้นเอง ก็ทำให้ง่ายขึ้นเยอะมาก

กลับมาที่ Gatsby กันต่อ ตัว Gatsby อย่างที่ได้กล่าวไปคือใช้ React นอกจากนั้นยังใช้ GraphQL และ Webpack ที่จะช่วยให้การทำงานของเราง่ายขึ้นมา ถึงแม้ว่าเราจะมาจาก LAMP Stack ก็ตามเถอะ

สิ่งที่ผมชอบของ Gatsby คือการจัดการข้อมูลตั้งแต่ Input เลย เพราะเราสามารถเอาไฟล์ข้อมูลของเราเข้ามาได้จากหลายรูปแบบมาก เริ่มจาก Markdown, JSON หรือแม้กระทั่ง Wordpress ที่มันมี Plugin ให้เราโหลดลงมาใช้ได้เลย

เริ่มติดตั้ง Gatsby กันเถอะ

ก่อนที่เราจะใช้งาน Gatsby ได้เราก็ต้องมาติดตั้งกันก่อน โดยเราจะต้องมี Node.js อยู่ในเครื่องด้วยนะ

ถัดไปเราก็ต้องมาติดตั้งตัว gatsby-cli กันใครใคร่ใช้ Yarn ก็ใช้ ใครใคร่ใช้ NPM ก็ใช้

Yarn
yarn global install gatsby-cli

NPM
npm install —global gatsby-cli

ใน Tutorial นี้เราจะมาสร้าง Blog กัน เริ่มจากการสร้าง Project กันเลยโดยการพิมพ์

gatsby new wonderful-blog

จากนั้นมันก็จะไปทำการโหลด Dependencies และ Boilerplate มาให้เรา ด้านบนจะเป็นการใช้ Gatsby Version 1 ถ้าอยากได้ Version 2 ที่เป็น Beta ให้พิมพ์ตามด้านล่างนี้แทน

gatsby new wonderful-blog https://github.com/gatsbyjs/gatsby-starter-default#v2

หลังจากเสร็จเราก็ cd เข้าไปใน wonderful-blog ที่เราพึ่งสร้างได้เลย โดยการพิมพ์

cd wonderful-blog

จากนั้นเราลองมารันเว็บที่เราพึ่งสร้างได้โดยการพิมพ์

gatsby develop

รอสักแปบให้มันได้ Build พร้อมกับเปิด environment สำหรับการพัฒนาที่เป็น hot-reloading (นั่นคือเราสามารถแก้ Code แล้วเซฟ หน้าเว็บก็จะอัพเดททันทีโดยที่เราไม่ต้องสั่ง Build ใหม่) ซึ่งเราสามารถเปิดได้ผ่าน http://localhost:8000

เราก็จะได้หน้าแบบด้านบนมา โดยเราจะเห็นว่าในหน้าเราจะมี Topbar พร้อมกับ Content นิดหน่อยแปะมาให้เราแล้ว

File Structure

เอาไฟล์สำคัญ ๆ ในตอนแรกกันก่อน ส่วนที่เหลือผมจะค่อย ๆ แนมมาเรื่อย ๆ เดี๋ยวจะงงกัน ส่วนสำคัญที่เราจะดู จะอยู่ใน Folder ที่ชื่อว่า src ถ้าใครเขียนโปรแกรมมาก่อน ก็น่าจะเดาได้ว่า มันเป็นที่ที่เราจะใช้เก็บ Source Code ของเรานั่นเอง ถ้าเราเข้าไป เราจะพบกับ Folder 2 อันคือ

  • components คือ Folder ที่เราใช้เก็บ React Component ถ้าใครคุ้นเคยกับการเขียน React อยู่แล้วก็น่าจะเข้าใจดี
  • pages คือ Folder ที่ใช้เก็บหน้าของเรานั่นเอง

ทีนี้ถ้าเราเข้าไปใน Folder pages แล้ว เราจะเห็นหน้าที่เขาสร้างมาให้แล้วนั่นคือ index.js, page-2.js และ 404.js ทีนี้ถ้าเราลองย้อนกลับไปที่ Web Browser ที่รัน Development Server อยู่แล้วเราลองใส่ /page-2 เราจะเห็นว่าหน้ามันจะวิ่งไปที่ไฟล์ page-2.js แต่ถ้าเราลองไปที่หน้าอื่นที่ไม่มีใน Folder pages ดูเราจะเห็นว่ามันจะเด้งไปที่หน้า 404 หรือก็คือ 404.js นั่นเอง

Create your First Page

เมื่อครู่ เราได้ทดลองแคะและแก้ไปนิดหน่อยแล้ว ถึงเวลาแล้วที่เราจะได้มาลองสร้างหน้าสักหน้าขึ้นมากัน หน้าที่เราจะลองสร้างกันคือหน้า Counter ง่าย ๆ ละกัน (เป็น Tutorial แรกที่ผมใช้เรียน React)

โดย Requirement ของหน้านี้คือ เราต้องมี Label สำหรับแสดงผลตัวเลขปัจจุบัน พร้อมกับปุ่มที่ใช้ในการเพิ่มลดอย่างละปุ่ม เมื่อเรากดปุ่มเพิ่มตัวเลขใน Label ก็ควรจะเพิ่มขึ้น 1 กลับกันถ้าเรากดลบตัวเลขใน Label ก็ควรจะลดลงเช่นกัน แต่ถ้ามันเป็น 0 อยู่แล้ว เราจะไม่ให้มันลดแล้ว เพราะเราไม่ต้องการให้มันแสดงผลเป็นเลขติดลบ

เริ่มจากให้เราสร้างไฟล์ใน Folder pages ชื่อ counter.js แล้วพิมพ์ Boilerplate ตามนี้

import React from ‘react’

import Layout from '../components/layout'

export default class Counter extends React.Component {
	render() {
		return (
			<Layout>
			</Layout>
		)
	}
}

จาก Code ด้านบน ถ้าใครที่เคยเขียน React ก็จะรู้ว่ามันก็คือการสร้าง Component นั่นเอง เริ่มจากการ Import React เข้ามาจากนั้นก็ประกาศ Class ให้ Extend มาจาก React Component สิ่งที่อยากให้สังเกต จะอยู่ใน render() ที่เราสั่งมัน Render Layout ออกมาก่อน อันนี้คือสิ่งที่ต่างจาก Version 1 ที่เราต้องมา Import แล้วแปะ Layout เองแล้ว จากก่อนหน้านี้ Gatsby จะทำให้เราเอง ทีนี้เราจะมาเพิ่ม State ให้มันกัน โดยเราจะเพิ่ม Function ที่ชื่อว่า constructor ลงไป

constructor (props) {
	super(props)
	this.state = {
		currentNumber: 0
	}
}

ตอนนี้เราก็ได้ constructor สำหรับการ Initial ตัว State แล้ว ถัดไปเราก็จะมาสร้าง Function สำหรับการเพิ่มและลดตัวเลขกัน

	addNumber () {
		this.setState({currentNumber: this.state.currentNumber + 1})
	}

	decreaseNumber () {
		this.setState({currentNumber: this.state.currentNumber > 0 ? this.state.currentNumber-1 : this.state.currentNumber})
	}

ผมก็ได้สร้างมา 2 Function สำหรับการเพิ่มและลดตัวเลขแล้ว อันที่น่าจะอ่านแล้วอาจจะงงสำหรับคนที่พึ่งเริ่มคือตรง decreaseNumber() ที่ผมลดรูปในการเขียน IF นิดหน่อย โดยถ้า currentNumber มันมากกว่า 0 เราก็จะให้มันลบออก 1 ได้ แต่ถ้าไม่ก็ปล่อยไว้เหมือนเดิม

ถัดไปเราก็เพิ่ม Element ลงไปในหน้ากัน โดยการเพิ่มปุ่ม 2 ปุ่ม และ 1 Label ในหน้ากัน ให้เราไปดูใน render() แล้ว Return ตามนี้

return (
	<div>
		<p>{this.state.currentNumber}</p>
		<button onClick={this.addNumber}>+</button>
		<button onClick={this.decreaseNumber}>-</button>
	</div>
)

ตอนนี้ให้เราเติม /counter ต่อจาก localhost ไป เราก็จะเห็นว่าหน้าของเรามีปุ่ม 2 ปุ่มเป็นบวกและลบ และตัวเลขวางอยู่ ถ้าเรากด + หรือ - สักปุ่ม มันก็จะ Error ออกมา เพราะเรายังไม่ได้ bind function เลยให้เราเพิ่ม 2 บรรทัดนี้ใน constructor

this.addNumber = this.addNumber.bind(this)
this.decreaseNumber = this.decreaseNumber.bind(this)

ถ้าเรากดบวกหรือลบ มันก็ไม่ระเบิด Error ออกมาแล้ว ตัวเลขก็บวกลบได้อย่างถูกต้อง อีกนิดนึงผมอยากให้เพิ่ม Link กลับไปหน้าแรกดู แว่บแรกเดาเลยว่าทุกคนจะนึกถึง a Tag แน่นอน แต่ Gatsby ได้เตรียม Component สำเร็จรูปสำหรับการทำ Link

วิธีการใช้เริ่มจาก Import มันเข้ามาใน counter.js ของเรา

import {Link} from ‘gatsby’

(Code ด้านบนถ้าเราเอาไปใช้ใน Version 1 จะต้องเปลี่ยนจาก "gatsby" เป็น "gatsby-link") จากนั้นใน render() ให้เราเติมบรรทัดนี้ต่อท้ายใน Return เลย

return (
		<div>
			<p>{this.state.currentNumber}</p>
			<button onClick={this.addNumber}>+</button>
			<button onClick={this.decreaseNumber}>-</button>
			<Link to={“/“}>To Homepage</Link>
		</div>
)

กลับไปที่หน้า Web Browser เราก็จะเห็น Link อันนึงเขียนว่า To Homepage เหมือนที่เราสร้างไว้เมื่อครู่ แล้วถ้าเรากดมันก็จะกลับไปที่หน้าแรก

สรุป

ในตอนนี้ก็เหมือนจุดเริ่มต้นที่พาทุกคนไปรู้จัก Gatsby.js ที่ทำให้การสร้าง Static Site ด้วย React ทำได้อย่างง่ายดายมากขึ้น โดยใช้ Tool ที่เราคุ้นเคยอย่าง React และ GraphQL ในการจัดการข้อมูล พร้อมทั้งด้วย Plugin ที่มีมากมาย ทำให้เราสามารถสร้างเว็บได้อย่างรวดเร็ว พร้อมทั้งพาไปดูวิธีการเตรียม Project, File Structure และการสร้างหน้าใหม่ของเราเอง ในตอนหน้าจะพาเข้าไปดูวิธีการ Styled-Component ต่าง ๆ กัน ติดตามอ่านได้เลยฮ่ะ ~

ปล. บางคนที่เคยใช้อาจจะบอกว่า ถ้าจะทำ Blog ทำไมไม่ใช้ Boilerplate ที่เป็น Blog เลย มันก็มีนะ คำตอบคือ Tutorial นี้เป้าหมายผมอยากให้เราทำได้ทุกอย่าง ไม่ใช่แค่ Blog เดี๋ยวไปตอนหลัง ๆ ผมจะลงลึกพวก Config ต่าง ๆ ที่ถ้าไม่ใช้ Starter เราจะไม่ได้ทำ