keyboard_tabSkip to content
arrow_back All Posts

Oct 11, 2023

ทำไมถึงต้องใช้ Nuxt ทั้งๆที่มี Vue อยู่แล้ว ?

มาทำความรู้จัก Nuxt กันว่ามันคืออะไร มีความแตกต่างกับ Vue ยังไงบ้าง และเคสแบบไหนควรใช้ Nuxt บ้าง

สารบัญ

nuxt-vs-vue สามารถดู 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 ยังไงบ้าง ?

Loading diagram…

State ที่ Nuxt เพิ่มเติมมาจาก Vue

  1. Server-side rendering (หรือ SSR) = สามารถทำ SSR ได้และสามารถทำ Hybrid mode ในแต่ละหน้าได้ https://nuxt.com/docs/guide/concepts/rendering

  2. SEO and Meta = ด้วยความสามารถ SSR ทำให้สามารถกำหนด meta tag สำหรับ share social จากการ render server ได้

  3. Auto import = ไม่ต้องคอย import คำสั่งนับล้านเข้า เช่น Vue

html
<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

html
<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>
  1. Data-fetching utilities = มีคำสั่ง useFetch ในการ call API (โดยไม่ต้อง import คำสั่งมาใหม่)

  2. 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 ออกมาเลย

bash
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 แทน

html
<template>
  <div>
    <!-- Markup shared across all pages, ex: NavBar -->
    <NuxtPage />
  </div>
</template>

ตัวอย่าง pages/todos/index.vue

  • เพิ่มสำหรับการ list todo ออกมา
  • ทำการเพิ่ม Router และการ edit ออกมา
html
<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

html
<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 ได้เลย

ตอบคำถามอื่นๆจากทางบ้าน

(เดี๋ยวมีเพิ่มในบทความมา เบื้องต้นทุกคนสามารถฟังผ่านคลิปก่อนได้)

forumComments (0)

lockLog in to join the conversation.

Log In

Loading comments…