Devahoy + Astro กับการเปลี่ยนเว็บใหม่อีกครั้ง

สวัสดีครับ วันนี้ผมมาเขียนบล็อกแชร์ประสบการณ์การเปลี่ยนเว็บจาก Next.js มาเป็น Astro ว่าทำไมถึงเลือกเปลี่ยน โดยเป้าหมายหลักๆ คือ
ทำไมผมถึงเลือกใช้ Astro?
- อย่างแรกคือ อยากลองอะไรใหม่ๆ และ Astro ก็เป็นหนึ่งในตัวเลือกที่อยู่ใน list มานานแล้ว
- สะดวกในการจัดการ Content โดยใช้ Markdown และ MDX (ซึ่งจริงๆ ก็เหมือนกับปัจจุบัน ที่ใช้ Next.js + MDX)
- รองรับ View Transitions API
- ใช้ UI framework ตัวไหนก็ได้ ไม่จำกัด เช่น React, Vue, Svelte
- มีแผนในการทำ ระบบ Auth และก็ server-side ทำให้เลือกใช้ Astro ที่ไม่เลือกใช้ Next.js ก็เพราะ งานหลักก็เจอ Next.js ทำให้งาน hobby เราก็อยากเลือก tool อื่นๆ เพื่อความหลากหลายบ้าง
Migration
เนื่องจากผมมีช่วงที่ย้ายไป Ghost อยู่พักนึง และก็อีกส่วนที่ใช้ Next.js ขั้นตอนการย้าย สำหรับ Next.js นั้นไม่ยาก ส่วนหน้าเว็บ พยายามให้เหมือนเดิม มีการปรับ re-design บ้างเล็กน้อย
- ในส่วนของ content ผมเป็น Markdown + MDX อยู่แล้ว สามารถที่จะย้ายได้เลย
- ในส่วนของ content ที่เขียนไว้ที่ Ghost ผมใช้วิธี นั่ง rewrite ใหม่ และเลือกบาง content มาเท่านั้น
จากนั้น ก็กำหนด Content Collection ให้ตรงกับ frontmatter
import { defineCollection, reference, z } from 'astro:content'
const blog = defineCollection({ type: 'content', schema: () => z.object({ title: z.string(), category: z.string(), tags: z.array(z.string()), authors: z.array(reference('author')).default(['default']), // Transform string to Date object date: z.coerce.date(), cover: z.string().optional(), draft: z.boolean().optional(), postLayout: z .enum(['simple', 'column']) .default(POST_METADATA.defaultLayout as 'simple' | 'column') })})
export const collections = { blog }
ผมเริ่มโดยการ fork project tailwind-astro-starting-blog และนำมา customize ต่อ ส่วนโปรเจ็คอื่นๆ ก็มีดูเป็นไอเดีย นำมาใช้บ้าง เช่น
Motion
ใช้ตัว motion.dev แบบ JavaScript เนื่องจากตัว component ผม .astro
ก็ใส่ code ใน tag <script>
<script>import { animate, inView, stagger } from 'motion'
animate('<selector>', { opacity: 0.25, y: 10 })</script>
Expressive Code
เป็นเหมือน Plugin มาช่วยจัดการเรื่องของ Syntax Highlighting
- แสดง Line Numbers หรือ hightlight แต่ละบรรทัดได้
- มี Terminal Frames แล้วก็ code block title
ตัวอย่าง config สำหรับโชว์ line number และ ปรับแต่ง themes
import { defineConfig } from 'astro/config'import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'
export default defineConfig({ integrations: [ expressiveCode({ plugins: [pluginLineNumbers()], themes: ['tokyo-night', 'slack-ochin', 'catppuccin-mocha'], defaultProps: { wrap: true, showLineNumbers: true } }) ]})
ในเมื่อในเว็บมีปุ่ม toggle theme ก็ต้องปรับ theme ให้ตรงเวลากดด้วย
if (newTheme === 'light') { document.documentElement.setAttribute('data-theme', 'slack-ochin')} else { document.documentElement.setAttribute('data-theme', 'catppuccin-mocha')}
Theme ที่รองรับของ Expressive Code
Deployment
เราเลือกใช้ Vercel เหมือนเดิม เนื่องจากหลายๆ โปรเจ็คก็อยู่ที่นี่ การตั้งค่าให้ hosting Vercel ก็คือต้องใช้ Adapter นั่นเอง
npm install @astrojs/vercel
ตั้งค่า config
import { defineConfig } from 'astro/config'import vercel from '@astrojs/vercel/serverless'
export default defineConfig({ output: 'hybrid', adapter: vercel()})
เนื่องจากผมมีแผน ให้มีทั้ง Servier Side และส่วนที่เป็นบล็อกจะเป็น static ทำให้ตั้ง output เป็น hybrid
คือให้มัน build static แต่ถ้าเราจะให้เป็น server side ก็ต้องไปกำหนด prerender
ให้ไม่ตรง pre-render static page
export const prerender = false
สุดท้าย ฝากติดตามบล็อกใหม่ด้วยนะครับ ขอบคุณครับ
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust