Quick Start

Nuxt - Introduction

基于 Vue 的 SSR (Server Side Rendering) 框架

Init:

npx nuxi@latest init <project-name>

# or using vite
npm create vite@latest

Run:

# npm
npm run dev -- -o

# nuxi
npx nuxi dev

Commands

Nuxt - nuxi

# get nuxt info
npx nuxi info

# init project
npx nuxi init <project_name>

# add modules
npx nuxi module add <NAME>

# creates a .nuxt directory and generates types.
npx nuxi prepare

# run dev
npx nuxi dev --dotenv .env.dev --host 127.0.0.1 --port 3000

# build
npx nuxi build --dotenv .env.prod

# preview after build
npx nuxi preview

# run type check
npx nuxi typecheck

Config

Nuxt Configuration

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: ["nuxt-mongoose", "@nuxt/ui", "@nuxt/image"],
})

设置 baseUrl

{
  app: {
    baseURL: "/prefix/"
  }
}

配置 Nginx 代理配置

http {
    server {
        location /prefix/ {
            proxy_pass http://127.0.0.1:3001/prefix/;
            proxy_set_header Host $http_host;
        }
    }
}

运行时配置

Runtime Config

export default defineNuxtConfig({
  runtimeConfig: {
    // The private keys which are only available within server-side
    apiSecret: '123',
    // Keys within public, will be also exposed to the client-side
    public: {
      apiBase: '/api'
    }
  }
})

其中,在 public 中定义的配置在服务端与客户端都能读取到

const runtimeConfig = useRuntimeConfig()

console.log(runtimeConfig.apiSecret)
console.log(runtimeConfig.public.apiBase)

可以用 .env 覆盖默认定义的配置

NUXT_API_SECRET=api_secret_token
NUXT_PUBLIC_API_BASE=https://nuxtjs.org

在 vue 中使用配置

<script setup lang="ts">
const config = useRuntimeConfig()

console.log('Runtime config:', config)
if (import.meta.server) {
  console.log('API secret:', config.apiSecret)
}
</script>

<template>
  <div>
    <div>Check developer console!</div>
  </div>
</template>

在 api 中使用配置

export default defineEventHandler(async (event) => {
  const { apiSecret } = useRuntimeConfig(event)
  const result = await $fetch('https://my.api.com/test', {
    headers: {
      Authorization: `Bearer ${apiSecret}`
    }
  })
  return result
})

环境变量

.env 文件在 dev/build/generate 阶段会自动加载,可以指定使用哪个 .env 文件

npx nuxi dev --dotenv .env.local

在 .env 文件中定义变量

FOO=bar

使用环境变量

console.log('FOO: ', process.env.FOO)

Server - API

Nuxt - server

目录结构

| server/
--| api/
----| hello.ts      # /api/hello
----| test.get.ts   # GET /api/test
----| test.post.ts  # POST /api/test

通过实现 defineEventHandler 函数

// 同步函数
export default defineEventHandler((event) => {
  return {
    hello: 'world'
  }
})

// 异步函数
export default defineEventHandler(async (event) => {
  return {
    hello: 'world'
  }
})

使用 useFetch调用 api

<script setup lang="ts">
async function submit() {
  const { body } = await useFetch('/api/submit', {
    method: 'post',
    body: { test: 123 }
  })
}
</script>

Route Parameters(路径参数)

  • server/api/hello/[name].ts
export default defineEventHandler((event) => {
  const name = getRouterParam(event, 'name')
  return `Hello, ${name}!`
})
  • server/api/foo/[...].ts:处理所有 /foo 子路径
export default defineEventHandler((event) => {
  // event.context.path to get the route path: '/api/foo/bar/baz'
  // event.context.params._ to get the route segment: 'bar/baz'
  return `Default foo handler`
})

Body Handling

export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  return { body }
})

Query Parameters

Sample query /api/query?foo=bar&baz=qux

export default defineEventHandler((event) => {
  const query = getQuery(event)

  return { a: query.foo, b: query.baz }
})

Type

StackOverflow - How to add typing to getQuery(event) in Nuxt 3

export default defineEventHandler<{ body: { name: string }; query: { id: string } }>((event) => {
  const query = getQuery(event) // Query is typed as { id: string }
  const body = await readBody(event) // Body is typed as { name: string }
})

错误处理

没有错误会返回 200,否则会返回 500 Internal Server Error

server/api/validation/[id].ts

export default defineEventHandler((event) => {
  const id = parseInt(event.context.params.id) as number

  if (!Number.isInteger(id)) {
    throw createError({
      statusCode: 400,
      statusMessage: 'ID should be an integer',
    })
  }
  return 'All good'
})

自定义返回码

export default defineEventHandler((event) => {
  setResponseStatus(event, 202)
})

Server - Plugins

| server/
--| plugins/
----| myPlugin.ts

Example:

export default defineMyPlugin((nitroApp) => {
  console.log('Nitro plugin', nitroApp)
})

NuxtUI

NuxtUI - Introduction

Built with Tailwind CSS and Headless UI

Theming

NuxtUI - Theming

修改 app.config.ts

export default defineAppConfig({
  ui: {
    container: {
      constrained: 'max-w-4xl' // 最大屏幕宽度
    },
    primary: 'blue', // 主题色
  }
})