สร้าง Github Pages ด้วย Next.js

Napat Limsirorat
Napat Limsirorat
November 9, 2022

ใครที่เคยใช้ Github คงเคยได้เห็น feature ในการสร้างหน้าเว็บของตัวเองได้อย่างง่ายดาย ด้วย Github Pages

แต่ถ้าหากลองศึกษาวิธีทำ ส่วนใหญ่จะนิยมแนะนำให้เริ่มต้นด้วย Jekyll แต่ด้วยตัวผมเองไม่ค่อยถนัดภาษา Ruby เท่าไหร่ เพราะใช้ Javascript มาตลอดทั้ง frontend และ backend จึงลองหาทางเลือกอื่นและมาเจอเครื่องมือนึงของ Next.js คือความสามารถในการ export เว็บทั้งหมดออกมาเป็น html, js, css เพียวๆ โดยไม่มี backend เลย เลยได้มีโอกาสลองเล่นซึ่งพบว่าไม่ยากอย่างที่คิด เลยจะมาแชร์ขั้นตอนการติดตั้งเผื่อจะเป็นประโยชน์ครับ (ใครขี้เกียจอ่านทีละขั้นข้ามไปดูโค้ดสุดท้ายเลยก็ได้นะครับ -> https://github.com/jewkub/jewkub.github.io )

เริ่มจากสร้าง repository ก่อน ตั้งชื่อเป็น <username>.github.io และตั้ง gitignore เป็น Node เพราะเราจะใช้ Node เป็นตัวรันคำสั่งต่างๆ ทั้งหมดครับ

ตัวอย่างการสร้าง repository (อย่าลืมเปลี่ยนชื่อตาม username ด้วยนะครับ)

จากนั้นก็ clone ลงเครื่อง และเริ่ม project ด้วยคำสั่ง

npx create-next-app

หรือใครชอบ yarn ก็ใช้

yarn create next-app

ใส่ชื่อ project ตามชื่อ repository เสร็จแล้วเข้าไปที่โฟลเดอร์ที่พึ่งสร้าง จะได้ structure ประมาณนี้

ลบโฟลเดอร์ /api ทิ้งได้เลยครับ เพราะเราจะไม่ใช้ API route หลังจากนั้นดูที่ไฟล์ package.json จะเป็นไฟล์หน้าตาประมาณนี้

เพิ่มคำสั่งที่เราจะใช้สั่งเรื่อยๆ ในช่อง "scripts" เป็นแบบนี้ (สามารถใช้ touch แทน type nul > ได้เลย ตัว Windows มันไม่รองรับคำสั่งนี้ 😢)

"scripts": {  
    "dev": "next dev",  
    "build": "next build",  
    "start": "next start",  
    "export": "npm run build && next export && type nul > out/.nojekyll",  
    "serve": "npm run export && serve out",  
    "deploy": "npm run export && node gh-pages.js"  
},

ไฟล์ .nojekyll มีไว้เพื่อระบุว่าเราจะไม่ใช้ jekyll ให้ข้ามขั้นตอนนั้น แล้ว host static file ของเราได้เลย

ที่จริงแล้ว gh-pages สามารถสั่งจาก command line ได้เลย แต่ส่วนตัวรู้สึกว่าพอต้อง config อะไรเพิ่มขึ้นเรื่อยๆ ก็ตั้งเป็นไฟล์ไปเลยดีกว่า สร้างไฟล์ gh-pages.js ที่ root folder

อธิบายโค้ดด้านบนคือ จากที่ github pages จะยอม host file ให้เฉพาะไฟล์ที่อยู่บน master branch เท่านั้น จึงต้องเปลี่ยน branch (ที่เดิม default เป็น gh-pages) เป็น master และเราต้องกำหนดด้วยว่าให้ ship ไฟล์ที่ชื่อขึ้นต้นด้วย . (ในที่นี้คือ .nojekyll) โดยระบุ dotfiles: true และส่วนสุดท้ายคือ commit messages โดยใช้ moment ด้วยเพื่อแปลงวันที่ได้อย่างสะดวก (ที่ใส่วันที่ด้วยเพราะไม่งั้น deploy แต่ละครั้งจะมี commit messages เหมือนกันหมดเลย เดี๋ยวจะดูยาก)

หลังจากนั้นติดตั้ง dependencies ที่เหลือที่ Next ไม่ได้ให้มา

npm install moment gh-pages serve

รัน npm run serve script จะรัน 3 คำสั่งด้วยกัน

  1. build คือการประมวลไฟล์ทั้งหมดให้เป็นรูปแบบ production คือพร้อม deploy ขึ้นใน backend ที่ต่างๆ แต่ในที่นี้เราใช้ Github pages ซึ่งไม่ค่อยรองรับ backend เท่าไหร่นัก จึงต้อง
  2. export หน้าเว็บทั้งหมดให้กลายเป็น static html files และสามารถนำไปฝากไว้ที่ host ที่ไหนก็ได้โดยไม่ต้องตั้ง server เองแต่อย่างใด
  3. serve ก็คือเหมือนทดสอบ host ที่โฟลเดอร์ที่เรากำหนด ในที่นี้กำหนดที่โฟลเดอร์ที่เราพึ่ง export มา คือ /out แล้วลองเข้าตาม url ที่มันเด้งขึ้นมา http://localhost:5000 ก็จะพบกับ

http://localhost:5000

ได้แล้วว คราวนี้ลองเพิ่ม routes ด้วย Link component ที่ Next มีสำเร็จรูปมาให้ใช้ ด้วยการสร้างหน้าว่างๆ ขึ้นมาหน้านึง ที่มี link กลับหน้าแรก

แก้โค้ดใน index.js ให้ใช้ Link component

npm run serve อีกครั้ง จะพบว่าเว็บเราสามารถ navigate ไปมาภายในได้แล้ว 😃

ต่อไปเป็นขั้นตอนการ deploy เริ่มจากตั้งค่า git ในโฟลเดอร์เราก่อน ให้มี remote ชี้ไปที่ url ของ repository เรา

git remote add origin https://github.com/<username>/<username>.github.io.git

จากนั้นตั้ง branch เป็น branch หลักของ source code นี้ ชื่ออะไรก็ได้ที่ไม่ใช่ master

git checkout -b main

เริ่ม deploy เว็บลง master

npm run deploy

ผลออกมาเป็น

ไปที่ environment -> View deployment ก็จะพบกับหน้าเว็บของเราเป็นที่เรียบร้อย 🎉🎉🎉

เพิ่มเติม

สำหรับโค้ดด้านบนทั้งหมดเพียงพอต่อการตั้งเว็บด้วย Github pages แล้ว แต่ก็ยังพอมีอะไรที่ทำเพิ่มให้สวยงามได้อีก

เริ่มจาก commit ผลงานเราขึ้นอีก branch ประดับไว้ด้วย

git add -A && git commit -m "Setup Nextjs for Pages"

และ push

git push --set-upstream origin main

(เฉพาะครั้งแรกที่ต้องสั่ง set-upstream หลังจากนี้สั่งแค่ git push ก็พอ)

ถ้าสังเกตุใน log ตอน export จะมีบอกว่า No “exportPathMap” found in “next.config.js”. Generating map from “./pages” ซึ่งเราสามารถ config ตรงนี้ได้ ในไฟล์ next.config.js

ถ้าหากอยากใส่ไฟล์ readme ใน master branch ด้วยเผื่อใครผ่านเข้ามาใน git จะได้เห็น source code หลังบ้าน ก็ทำได้ง่ายๆ แค่ใส่ไฟล์ไว้ในโฟลเดอร์ /public ตอน build ไฟล์นี้ก็จะ ship ไปด้วยและ deploy ไปด้วยกันเลย

ลองใช้ Typescript กัน

Next.js มี Typescript ให้ใช้ด้วย ลองทำตาม docs เลยละกัน (ใน docs มีบอกให้ใช้ yarn แต่ใครใช้ npm มาแล้วก็ใช้ npm ต่อไปนะ ใช้สลับไปสลับมาอาจทำให้ตอน build มันมองไม่เห็นไฟล์)

หลังจากเปลี่ยนไฟล์เป็น .tsx หมดแล้วก็อยากเปลี่ยน gh-pages.js เป็น .ts ด้วย

และเปลี่ยนคำสั่งใน scripts เป็น ts-node gh-pages.ts ใช้ ts-node เพื่อจะได้รัน typescript ได้โดยไม่ต้อง compile ก่อน ซึ่งพอลองรัน serve ก็ยังปกติดี แต่พอ deploy จะมี error ขึ้นมาว่า

SyntaxError: Cannot use import statement outside a module

ซึ่งเป็นเพราะว่าใน tsconfig.json มีการตั้งค่า “module”: “esnext” ดังนั้นเราจึงต้องตั้ง “type”: “module” ใน package.json ด้วย แต่เมื่อตั้งแล้วก็พบ error อะไรไม่รู้อีกหน้าตาแปลกๆ อ่านไม่รู้เรื่อง หลังจากนั่งซุยๆ อยู่ซักพักนึงก็เข้าใจว่าปัญหาเกิดจากไฟล์ที่เป็นไฟล์ของ Next เอง มีการ load module ด้วยวิธีที่ไม่ใช่คำสั่ง import (เดาว่าน่าจะใช้ require) เพราะเราไปตั้ง type เป็น module ไปซะแล้วเลยต้องใช้ import เท่านั้น จึงไปลองดูใน github issue ก็พบว่ามีคนมีปัญหานี้เหมือนกันเลย #9607 แล้ว ณ ตอนที่เขียนนี้ issue นี้ยัง open อยู่ จึงต้องรอต่อไป ในระหว่างนี้ก็แก้ด้วยการกลับไปใช้ gh-pages.js ไปก่อน

เป็นอันเสร็จสิ้นการติดตั้งเว็บ ลองเอาไปเล่นกันได้ ผลเป็นอย่างไรมาแชร์กันได้ครับ 😊

198698_517793794899786_2013913423_n.webp
By Napat Limsirorat
November 9, 2022

© Jew • 2022

FacebookGithub