ทำไมถึงต้องใช้ Nuxt ทั้งๆที่มี Vue อยู่แล้ว ?
/ 4 min read
สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video
(บทความยังไม่เสร็จดี กำลังอยู่ในระหว่างการเรียบเรียงใหม่ สามารถฟังฉบับเนื้อหาได้ก่อนผ่านคลิปนะครับ 🙏)
Nuxt คืออะไร ?
Web: https://nuxt.com/
Nuxt คือ open source ที่สร้างขึ้นสำหรับ full stack web app โดยเฉพาะ ที่ห่อหุ่มอยู่บน Vue.js อีกที
Nuxt มีไอเดียว่า เราจะทำการเตรียมของที่จำเป็นที่ต้องการในการสร้างเว็บด้วย Vue.js framework เอาไว้ และเพ่ิมความสามารถในการทำ server side render เป็น default เพื่อให้ครอบคลุมทุก use case ของการ production ไว้ด้วย
แตกต่างกับ Vue ยังไงบ้าง ?
State ที่ Nuxt เพิ่มเติมมาจาก Vue
-
Server-side rendering (หรือ SSR) = สามารถทำ SSR ได้และสามารถทำ Hybrid mode ในแต่ละหน้าได้ https://nuxt.com/docs/guide/concepts/rendering
-
SEO and Meta = ด้วยความสามารถ SSR ทำให้สามารถกำหนด meta tag สำหรับ share social จากการ render server ได้
-
Auto import = ไม่ต้องคอย import คำสั่งนับล้านเข้า เช่น Vue
<script setup> import { ref, computed } from "vue"; import { useRoute } from "vue-router";
const route = useRoute(); const firstName = ref(""); const lastName = ref("");
const fullName = computed(() => { return `${firstName.value} ${lastName.value}`; });</script>
<template> Fullname {{ fullName }} <input v-model="firstName" /> <input v-model="lastName" /></template>
เทียบกับ Nuxt
<script setup> const route = useRoute(); const firstName = ref(""); const lastName = ref("");
const fullName = computed(() => { return `${firstName.value} ${lastName.value}`; });</script>
<template> Fullname {{ fullName }} <input v-model="firstName" /> <input v-model="lastName" /></template>
-
Data-fetching utilities = มีคำสั่ง
useFetch
ในการ call API (โดยไม่ต้อง import คำสั่งมาใหม่) -
Code splitting = แยกส่วนทำให้ build file แต่ละ file ขนาดเล็กลง
ในเมื่อ Nuxt ทำเว็บได้เหมือน Vue เลย ใช้ Vue หรือ Nuxt อะไรจะง่ายกว่า ?
- มันมี feature ที่เหมือนกับ vue เลย (เพราะมันห่อหุ้ม Vue เอาไว้)
- ความแข็งแกร่งของ Nuxt = เหมือน vue แต่เตรียม feature ไว้ให้พร้อมแล้ว
- Routing ก็มี
- Fetch ก็มี (แถม async, await ไม่ต้องประกาศ function ก่อนด้วย)
- state management ก็มี (ซึ่งจริงๆจะใช้ Pinia ก็ได้)
มันเหมาะสำหรับใครก็ตามที่
- ขี้เกียจวาง structure เอง (มีคนเตรียม pattern เอาไว้ให้แล้ว)
- ต้องการความสามารถ server side render
= คุณเหมาะกับ Nuxt มากกว่า
แต่ถ้าใครซีเรียสเรื่อง
- การวาง Strucuture เป็นแบบฉบับตัวเอง
- ต้องการเอาเว็บ deploy แค่ฝั่ง Client site (เพื่อให้สามารถขึ้นเว็บง่ายๆ อย่าง github page, firebase hosting)
= คุณเหมาะกับ Vue มากกว่า
มาลองทำ Nuxt กัน
เราจะทำเป็น static site 2 หน้าคือหน้ารวม Todo และหน้าแสดง Todo แบบง่าย ๆ
- ใช้รูปแบบ project เหมือน Vue todo (ที่เคยยิงเข้า Mock API มา)
เราใช้คำสั่ง nuxt ในการ render web ออกมาเลย
npx nuxi@latest init <project name>
หลังจากนั้นสร้าง structure มาประมาณนี้
- เราจะทำการสร้างไฟล์ขึ้นมาที่ folder
todos
├── README.md├── app.vue├── data│ └── blogs.json├── nuxt.config.ts├── package-lock.json├── package.json├── pages│ ├── index.vue│ └── todos --> สร้าง folder นี้แทน│ ├── [id].vue│ └── index.vue├── public│ └── favicon.ico├── server│ └── tsconfig.json└── tsconfig.json
แรกสุดเราจะเปลี่ยน app.vue
เรียก NuxtPage เพื่อใช้ Router ของ Nuxt แทน
<template> <div> <!-- Markup shared across all pages, ex: NavBar --> <NuxtPage /> </div></template>
ตัวอย่าง pages/todos/index.vue
- เพิ่มสำหรับการ list todo ออกมา
- ทำการเพิ่ม Router และการ edit ออกมา
<script setup> const BASE_URL = 'https://<id จากเว็บ mockapi>.mockapi.io'
const statuses = ['Pending', 'Doing', 'Done'] const todoText = ref('') const isLoading = ref(true) const todos = ref([])
const loadTodo = async () => { isLoading.value = true const { data } = useFetch(`${BASE_URL}/todos`, { lazy: true }) console.log(data) todos.value = data.value isLoading.value = false }
const addTodo = async () => { try { isLoading.value = true const todoData = { name: todoText.value, status: 'Pending' } await useFetch(`${BASE_URL}/todos`, { method: 'post', body: todoData }) await loadTodo() } catch (error) { console.log('error', error) } isLoading.value = false }
const deleteTodo = async (id) => { try { isLoading.value = true await useFetch(`${BASE_URL}/todos/${id}`, { method: 'delete' }) await loadTodo() } catch (error) { console.log('error', error) }
isLoading.value = false }
// load in state setup await loadTodo()</script>
<template> <div> <h1>Todo List</h1> <div> <input type="text" v-model="todoText" /> <button @click="addTodo">Add</button> </div> <ul v-if="!isLoading"> <li v-for="todo in todos" :key="todo.id"> {{ todo.name }} status : <select v-model="todo.status"> <option v-for="status in statuses" :key="status" :value="status">{{ status }}</option> </select>
<NuxtLink :to="`/todo/${todo.id}`"> <button>Edit</button> </NuxtLink> <button @click="deleteTodo(todo.id)">DELETE</button> </li> </ul> <div v-else>Loading</div> </div></template>
ตัวอย่าง pages/todos/[id].vue
<script setup> const route = useRoute(); const todoId = route.params.id;
const BASE_URL = "https://<id จากเว็บ mock api>.mockapi.io";
const { pending, data: todo } = useFetch(`${BASE_URL}/todos/${todoId}`, { lazy: true, }); E;</script>
<template> <nuxt-link to="/">Back</nuxt-link> <div v-if="pending">Loading</div> <div v-else> <div>Todo {{ todo.id }}</div> <div>{{ todo.name }}</div> </div></template>
การ deploy Nuxt
ด้วยความที่ Nuxt พื้นฐานเป็น SSR = ต้องการ backend server ในการ render website
- Nuxt run อยู่บน Node.js https://nuxt.com/docs/getting-started/deployment
- เช่น ถ้าจะ deploy Firebase hosting มันจะ require Firebase Cloud function (Node) ด้วยสำหรับการทำ SSR เพิ่มเข้ามา
มองในแง่การ deploy = Nuxt จะเปลือง resource มากกว่า เพราะต้องใช้การ render server ร่วมกันด้วย (ใช้มาก ใช้น้อย ขึ้นอยู่กับวิธี optimize เว็บ)
ตัวอย่าง deploy ลง Vercel
เราจะมาลอง deploy Nuxt ที่เราทำกันลง Vercel เลย https://vercel.com/
- ต้อง push งานขึ้น git เพื่อทำการ deploy
- เสร็จแล้วเลือก menu ผ่าน Vercel = deploy ได้เลย
ตอบคำถามอื่นๆจากทางบ้าน
(เดี๋ยวมีเพิ่มในบทความมา เบื้องต้นทุกคนสามารถฟังผ่านคลิปก่อนได้)
- รู้จักกับ Web Vitals guideline การสร้าง UX ที่ดีออกมากันมี Video
รู้จักกับคำศัพท์พื้นฐานของ Web Vitals และ use case ต่างๆของ Web Vitals กัน
- มาแก้ปัญหา Firestore กับปัญหาราคา Read pricing สุดจี๊ดมี Video มี Github
ในฐานะที่เป็นผู้ใช้ Firebase เหมือนกัน เรามาลองชวนคุยกันดีกว่า ว่าเราจะสามารถหาวิธีลด Pricing หรือจำนวนการ read ของ Firestore ได้ยังไงกันบ้าง
- มารู้จักการเขียน code แบบ clean code กัน (ฉบับ Javascript)มี Video
มาแชร์เทคนิคการเขียน code แบบ clean ฉบับ Javascriptกัน ว่ามีกี่วิธีที่สามารถทำให้ code สะอาดขึ้นได้บ้าง
- รู้จักกับ Auth0มี Video
มารู้จักกับ Auth0 Authentication platform ที่ช่วยทำให้พัฒนา application พร้อมระบบยืนยันตัวตนได้ง่ายขึ้น