Nuxt.js Fundamental ตอนที่ 4 - Nuxt.js Concept

Published on

เขียนวันที่ : Aug 22, 2020

LastModified on

(อัพเดท : Mar 19, 2022)

Discord

สำหรับหัวข้อนี้จะเป็นเรื่องของทฤษฎี อาจจะอ่านแล้วเข้าใจยากซักหน่อย แต่เชื่อเถอะว่าเนื้อหาส่วนนี้ค่อนข้างสำคัญครับ และมีประโยชน์มาก หากเราเข้าใจ Concept เข้าใจการทำงานของมัน เราก็สามารถประยุกต์และใช้งานได้ครับ ในหัวข้อนี้ จะมี

  • View คืออะไร?
  • Modules คืออะไร?
  • Nuxt Context ใช้ยังไง?
  • Nuxt Life Cycle ทำงานยังไงบ้าง

เริ่มกันเลยครับ

Views

ในทีนี้คือหมายถึงตัว View หรือ UI เช่น Layout, Template หรือหน้า Page ซึ่งเราสามารถที่จะ customize เพิ่มเติม หรือกำหนดพวก SEO Meta Tag ได้ด้วย

Nuxt View

Reference: Nuxt.js Views

ถ้าดูจากภาพด้านบน จะเห็นว่ามีส่วน

  • Layout ที่จะหมายถึง Component, Head, Middleware ที่ให้เรากำหนดรูปแบบ layout template ได้ เช่น layout แบบมี sidebar, layout แบบ full-width, layout แบบ admin เป็นต้น
  • ส่วน Page ก็จะมี ส่วนย่อยๆ เต็มเลย เช่น asyncData, fetch, head, middleware, transition, validate เป็นต้น

Layout

เราสามารถกำหนด default layout ได้ เช่นสร้างไฟล์ default.vue ใน folder layouts

<template>
  <Nuxt />
</template>

ซึ่งทุกๆ Page (ไฟล์อยู่ใน folder pages) ก็จะใช้ default layout ถ้าเราไม่ได้กำหนด layout ให้มัน แต่ถ้าเราอยากกำหนด layout นอกเหนือจาก default ละ ทำยังไง?

ก็แค่สร้างไฟล์ มาอีกไฟล์เช่น dashboard.vue ไว้ใน layouts

<template>
  <div>
    <aside class="sidebar">This is sidebar</asid>
    <main>
      <h2>this is dashboard layout</h2>
      <Nuxt />
    </main>
    <Nuxt />
  </div>
</template>

ทีนี้ในหน้า pages ที่เราสร้าง เราก็แค่กำหนด layout แบบนี้ เช่น สร้างไฟล์ pages/dashboard.vue

dashboard.vue
<template>
  <h1>My Dashboard</h1>
</template>
<script>
export default {
  layout: 'dashboard'
};
</script>
  • เราสังเกตว่า เอะเราใช้ layout ใน export default {} ได้ แสดงว่า ตัวอื่นในรูปบน ก็ใช้ได้นี้นา?

ตัวอย่าง เช่น เราใช้ head แบบนี้ครับ เพื่อกำหนด HTML Meta tag

<template>
  <h1>{{ title }}</h1>
</template>

<script>
export default {
  head() {
    return {
      title: 'My title',
      meta: [
        {
          hid: 'description',
          name: 'description',
          content: 'My custom description'
        }
      ]
    };
  }
};
</script>

ตัวอย่าง อื่นๆ เช่น middleware, validate, asyncData ก็ได้ดังนี้ (เดี๋ยวจะพูดถึงรายละเอียดอีกทีครับ อันนี้แค่ overview)

<template>
  <h1>{{ title }}</h1>
</template>

<script>
  export default {
    asyncData(context) {
      return { project: 'nuxt' };
    },
    head() {
      return {
        title: 'title',
        meta: [
          {
            hid: 'description',
            name: 'description',
            content: 'My custom description'
          }
        ]
      };
    },
    middleware: 'myMiddleware',
    validate({ params, query, store }) {
      return true; // if the params are valid
    }
  };
</script>

ตัวอย่าง validate ลองย้อนกลับไปดูเรื่อง Routing ได้ครับ เป็นการเช็คว่าหน้าที่เรา navigate มามันถูกหรือไม่ ส่วนการกำหนด head นอกจากการกำหนด แต่ละ Page แล้ว เราก็สามารถกำหนด แบบ global ที่ไฟล์ nuxt.config.js ได้ด้วย

Context

Context เป็นก้อน Data ใน Nuxt.js ที่เราสามารถเรียกใช้งานผ่าน Nuxt Life Cycle hook ต่างๆ เช่น ใน asyncData ดึงข้อมูล Vuex Store, เข้าถึง req, res, query ต่างๆ เข้าถึง nuxtState เต็มไปหมดเลย

ตัวอย่างด้านล่าง คือ context มีอะไรอยู่ข้างในบ้าง และบางตัวแปร ก็เข้าถึงได้เฉพาะ server หรือ client เป็นต้น

function (context) {
  const {
    app,
    store,
    route,
    params,
    query,
    env,
    isDev,
    isHMR,
    redirect,
    error,
   $config
  } = context

  // Only available on the Server-side
  if (process.server) {
    const { req, res, beforeNuxtRender } = context
  }

  // Only available on the Client-side
  if (process.client) {
    const { from, nuxtState } = context
  }
}

สามารถอ่านรายละเอียด หรือดูรูปภาพจาก Nuxt Context & Helpers เพิ่มเติมครับ เพื่อให้เห็นภาพ

Modules

ใน Nuxt.js ตัว modules เปรียบเสมือน Extensions นั่นเอง ที่ช่วยให้เราสามารถเพิ่ม feature หรือส่วนเสริม และหากมองแล้ว จริงๆ Modules ก็เป็นเพียงแค่ function นั่นเอง ตัวอย่าง modules เช่น

  • @nuxt/content - เป็น Module ที่ทำให้เราสามารถอ่านไฟล์ JSON, CSV, Markdown, YAML จาก folder content ได้
  • @nuxt/axios - เป็น Module ที่ Nuxt เอา axios library ที่ไว้ fetch HTTP ยอดนิยม มาใช้ได้เลย
  • @nuxt/auth - เป็น Module ที่จัดการเรื่อง Authentication กำหนด schema และ strategy ได้เลย

และหากเราต้องการใช้ module ก็แค่ไปเพิ่มในไฟล์ nuxt.config.js คล้ายๆแบบนี้ครับ

export default {
  modules: ['@nuxt/content']
};

นอกจาก Modules ด้านบนที่กล่าวมา เรายังสามารถสร้าง Module ขึ้นมาใช้เองได้ด้วยนะ เช่น สร้างไฟล์ขึ้นมาใหม่ชื่อ simple.js ไว้ใน folder modules

// ไฟล์ modules/simple.js
export default function SimpleModule(moduleOptions) {
  // Write your code here
}

เหมือนกับ Module ของ Nuxt หากเราเขียน Module ขึ้นเอง เราก็ต้องไปกำหนดในไฟล์ nuxt.config.js เหมือนกันครับ แบบนี้

export default {
  modules: [
    // Simple usage
    '~/modules/simple',
    // Passing options directly
    ['~/modules/simple', { token: '123' }]
  ]
};

Nuxt Life Cycle

Nuxt Life Cycle

Life Cycle ของ Nuxt.js จะแบ่งออกเป็น 2 ส่วนคือ Server และ Client และก็แบ่งย่อยตามเหตุการณ์ได้อีก 2 คือ ตอน build time และ ตอนเปลี่ยนหน้าเวลา User click link (ด้วย NuxtLink)

Server

  • แบบ SSR จะใช้คำสั่ง nuxt start จะ execute ทุกๆครั้ง ที่มีการ request ไปที่ Server
  • ถ้าโหมด SSG nuxt generate จะ execute ครั้งเดียว ตอน build แต่ทุกๆเพจที่ถูก generate เช่นเว็บมี 5 หน้า ก็จะรัน 5 ครั้ง ตอน build

Reference : Nuxt Life Cycle

Hints & Questions?

  • เพื่อนๆ ลองเล่นพวก middleware, plugins, validate หรือ asyncData, head ดูนะครับ ว่าทำอะไรเพิ่มได้บ้าง (บางเนื้อหา มีในหัวข้อถัดไป)
  • ลองเรียกใช้งาน context ในแต่ละบริบท เช่นผ่าน asyncData หรือผ่าน middleware หรือผ่าน nuxtState มันทำได้เหมือนกันมั้ย?
  • พยายามทำความเข้าใจ Life Cycle ตัวอย่างรูปภาพ จาก Nuxt Docs นั้น อ่านเข้าใจ และมีประโยชน์มาก (ควรเซฟเก็บไว้ดุเลย) เพราะเวลา development ยังไงก็ต้องดูเป็น reference แน่นอน :)
Buy Me A Coffee
Discord