Devahoy Logo
PublishedAt

Astro

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

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

/content/config.ts
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

astro.config.mjs
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

Expressive Code Theme

Deployment

เราเลือกใช้ Vercel เหมือนเดิม เนื่องจากหลายๆ โปรเจ็คก็อยู่ที่นี่ การตั้งค่าให้ hosting Vercel ก็คือต้องใช้ Adapter นั่นเอง

Terminal window
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
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust

Related Posts