Chuyển đến nội dung chính

Lesson 12: Middleware, Plugins & Modules

Route middleware, server middleware. Nuxt plugins, lifecycle. Nuxt modules ecosystem (@nuxtjs/i18n, @nuxt/image, @nuxt/content). Custom module development.

💻 Programming — Lesson 12 Lesson 12: Middleware, Plugins & Modules

Vue.js & Nuxt: From Basics to Advanced

Part 3: Nuxt 3 Fundamentals

xdev.asia

1. Route Middleware

// middleware/auth.ts — named middleware
export default defineNuxtRouteMiddleware((to, from) => {
  const { loggedIn } = useUserSession()

  if (!loggedIn.value) {
    return navigateTo('/login', { redirectCode: 301 })
  }
})

// middleware/admin.ts
export default defineNuxtRouteMiddleware((to) => {
  const { user } = useUserSession()

  if (user.value?.role !== 'admin') {
    return abortNavigation({
      statusCode: 403,
      message: 'Không có quyền truy cập',
    })
  }
})
<!-- pages/dashboard.vue — apply middleware -->
<script setup lang="ts">
definePageMeta({
  middleware: ['auth'], // Named middleware
})
</script>

<!-- pages/admin.vue — multiple middleware -->
<script setup lang="ts">
definePageMeta({
  middleware: ['auth', 'admin'],
})
</script>
// middleware/01.global.ts — runs on every route
export default defineNuxtRouteMiddleware((to, from) => {
  console.log(`Navigate: ${from.path} → ${to.path}`)
})

2. Nuxt Plugins

// plugins/api.ts
export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig()

  const api = $fetch.create({
    baseURL: config.public.apiBase,
    onRequest({ options }) {
      const token = useCookie('token')
      if (token.value) {
        options.headers.set('Authorization', `Bearer ${token.value}`)
      }
    },
    onResponseError({ response }) {
      if (response.status === 401) {
        navigateTo('/login')
      }
    },
  })

  return {
    provide: {
      api, // Available as useNuxtApp().$api
    },
  }
})
// plugins/dayjs.client.ts — client-only plugin
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import 'dayjs/locale/vi'

export default defineNuxtPlugin(() => {
  dayjs.extend(relativeTime)
  dayjs.locale('vi')

  return {
    provide: {
      dayjs,
    },
  }
})

3. Nuxt Modules Ecosystem

ModuleFunction
@nuxtjs/tailwindcssTailwind CSS integration
@pinia/nuxtPinia state management
@nuxt/imageImage optimization
@nuxt/contentFile-based CMS
@nuxtjs/i18nInternationalization
@sidebase/nuxt-authAuthentication
nuxt-auth-utilsOAuth helpers
@nuxt/fontsFont optimization
@nuxt/scriptsThird-party scripts
// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@nuxtjs/tailwindcss',
    '@pinia/nuxt',
    '@nuxt/image',
    '@nuxtjs/i18n',
  ],

  i18n: {
    locales: [
      { code: 'vi', file: 'vi.json' },
      { code: 'en', file: 'en.json' },
    ],
    defaultLocale: 'vi',
    langDir: 'locales/',
  },

  image: {
    quality: 80,
    format: ['webp', 'avif'],
  },
})

4. Custom Modules

// modules/analytics/index.ts
import { defineNuxtModule, addPlugin, createResolver } from '@nuxt/kit'

export default defineNuxtModule({
  meta: {
    name: 'my-analytics',
    configKey: 'analytics',
  },
  defaults: {
    trackingId: '',
  },
  setup(options, nuxt) {
    const resolver = createResolver(import.meta.url)

    // Add runtime plugin
    addPlugin(resolver.resolve('./runtime/plugin'))

    // Add composable
    nuxt.options.alias['#analytics'] = resolver.resolve('./runtime/composables')
  },
})

Next article: Authentication & Authorization — OAuth, sessions, RBAC.