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
1
import { defineCollection, reference, z } from 'astro:content'
2
3
const blog = defineCollection({
4
type: 'content',
5
schema: () =>
6
z.object({
7
title: z.string(),
8
category: z.string(),
9
tags: z.array(z.string()),
10
authors: z.array(reference('author')).default(['default']),
11
// Transform string to Date object
12
date: z.coerce.date(),
13
cover: z.string().optional(),
14
draft: z.boolean().optional(),
15
postLayout: z
16
.enum(['simple', 'column'])
17
.default(POST_METADATA.defaultLayout as 'simple' | 'column')
18
})
19
})
20
21
export const collections = { blog }

ผมเริ่มโดยการ fork project tailwind-astro-starting-blog และนำมา customize ต่อ ส่วนโปรเจ็คอื่นๆ ก็มีดูเป็นไอเดีย นำมาใช้บ้าง เช่น

Motion

ใช้ตัว motion.dev แบบ JavaScript เนื่องจากตัว component ผม .astro ก็ใส่ code ใน tag <script>

1
<script>
2
import { animate, inView, stagger } from 'motion'
3
4
animate('<selector>', { opacity: 0.25, y: 10 })
5
</script>

Expressive Code

เป็นเหมือน Plugin มาช่วยจัดการเรื่องของ Syntax Highlighting

  • แสดง Line Numbers หรือ hightlight แต่ละบรรทัดได้
  • มี Terminal Frames แล้วก็ code block title

ตัวอย่าง config สำหรับโชว์ line number และ ปรับแต่ง themes

astro.config.mjs
1
import { defineConfig } from 'astro/config'
2
import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'
3
4
export default defineConfig({
5
integrations: [
6
expressiveCode({
7
plugins: [pluginLineNumbers()],
8
themes: ['tokyo-night', 'slack-ochin', 'catppuccin-mocha'],
9
defaultProps: {
10
wrap: true,
11
showLineNumbers: true
12
}
13
})
14
]
15
})

ในเมื่อในเว็บมีปุ่ม toggle theme ก็ต้องปรับ theme ให้ตรงเวลากดด้วย

1
if (newTheme === 'light') {
2
document.documentElement.setAttribute('data-theme', 'slack-ochin')
3
} else {
4
document.documentElement.setAttribute('data-theme', 'catppuccin-mocha')
5
}

Theme ที่รองรับของ Expressive Code

Expressive Code Theme

Deployment

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

Terminal window
npm install @astrojs/vercel

ตั้งค่า config

1
import { defineConfig } from 'astro/config'
2
import vercel from '@astrojs/vercel/serverless'
3
4
export default defineConfig({
5
output: 'hybrid',
6
adapter: vercel()
7
})

เนื่องจากผมมีแผน ให้มีทั้ง Servier Side และส่วนที่เป็นบล็อกจะเป็น static ทำให้ตั้ง output เป็น hybrid คือให้มัน build static แต่ถ้าเราจะให้เป็น server side ก็ต้องไปกำหนด prerender ให้ไม่ตรง pre-render static page

1
export const prerender = false

สุดท้าย ฝากติดตามบล็อกใหม่ด้วยนะครับ ขอบคุณครับ

Authors
avatar

Chai Phonbopit

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

Related Posts