【Vue.js】Nuxt.js v3

656 阅读7分钟

封面:

image.png

什么是 Nuxt.js ?

Nuxt.js 是一款基于 Vue.js 的服务端渲染(SSR)框架。

Nuxt.js 的优势:

  1. 免费 & 开元
  2. 直观
  3. 易扩展
  4. 高性能
  5. 全栈
  6. 没有供应商锁定,允许应用部署到任何地方,甚至是边缘。

自动化和约定:

  • 基于文件的路由: 根据 pages/目录 的结构定义路由。这样可以更容易地组织应用程序,避免手动配置路由的需要。
  • 代码分割: Nuxt 自动将代码拆分成较小的块,这有助于减少应用程序的初始加载时间。
  • 内置服务器端渲染: Nuxt 具备内置的服务器端渲染能力,因此你不需要自己设置单独的服务器。
  • 自动导入: 在各自的目录中编写 Vue 组件和可组合函数,并在使用时无需手动导入,享受 TreeShaking 和优化 JS Bundle 的好处。
  • 数据获取工具: Nuxt提供了可用于处理与服务器端渲染兼容的数据获取的可组合函数,以及不同的策略。
  • 零配置的 TypeScript 支持: 可以编写类型安全的代码,无需学习 TypeScript,因为我们提供了自动生成的类型和 tsconfig.json 配置文件。
  • 配置好的构建工具: 我们默认使用 Vite 来支持开发中的热模块替换(HMR),以及在生产中将代码打包成符合最佳实践的形式。

安装一个 Nuxt 项目:

前置准备:

注意

  • Nuxt v3 版本需要确保您的 Node 版本 大于等于 v16.10.0
  • Nuxt v3 的 Node 版本最好是偶数 (e.g v16.10v18.1.0v20.1.0)

开发前配置推荐:

  1. 推荐使用 Visual Studio Code
  2. 安装 Volar 扩展
  3. 安装社区开发的 Nuxtr 扩展

安装步骤:

  1. 打开一个终端,使用下面的脚手架命令创建一个 nuxt 项目:
# npx
npx nuxi@latest init <project-name>

# pnpm
pnpm dlx nuxi@latest init <project-name>

# bun
bunx nuxi@latest init <project-name>
  1. 进入到项目 <project-name> 里面:
cd <project-name>
  1. 安装依赖:
# npm
npm install

# yarn
yarn install

# pnpm
pnpm install

# bun
bun install
  1. 启动项目:
# npm
npm run dev

# yarn
yarn dev

# pnpm
pnpm run dev

# bun
bun run dev
  1. 打开这个页面就算是大功告成了:

配置 nuxt 项目

概述:

  • 默认情况下,Nuxt已经配置了大多数使用情况。
  • 如果对于项目还需要一些定制化,请参考下面的内容。

nuxt.config.ts

说明:

nuxt.config.ts 文件位于 Nuxt 项目的根目录配置文件, 配置的方式是使用 defineNuxtConfig 方法默认导出一个对象进行配置:

export default defineNuxtConfig({
  // 我的Nuxt配置
});

建议用法:

  1. 通常在文档中会提到nuxt.config.ts,例如添加自定义脚本、注册模块或更改渲染模式。
  2. 推荐使用 nuxt.config.ts而不是 nuxt.config.js,因为这样会具有更好的语法提示。

runtimeConfig:

环境覆盖:

可以按照如下方式配置 nuxt 在不同环境下面的运行配置,这些特殊的环境配置会将原有的环境配置进行覆盖。

export default defineNuxtConfig({
  // 生产环境需要覆盖的配置:
  $production: {
    routeRules: {
      '/**': { isr: true }
    }
  },
  // 开发环境需要覆盖的配置:
  $development: {
    //
  },

  // 元数据:
  $meta: {}
})

运行时配置:

说明:

runtimeConfig API 将像环境变量这样的值暴露给应用程序的其余部分。

runtimeConfig.public中的配置的键值对变量可以在客户端中使用。

使用步骤:

  1. 根目录下配置nuxt.config.ts文件:
export default defineNuxtConfig({
  runtimeConfig: {
    // 只在服务器端可用的私有键
    apiSecret: '123',
    // public中的键也可以在客户端使用
    public: {
      apiBase: '/api'
    }
  }
});
  1. 根目录下配置 .env文件:
# 这将覆盖apiSecret的值
NUXT_API_SECRET=api_secret_token
  1. 在项目下使用 useRuntimeConfig()这个 hook 来获取环境变量的值
// useRuntimeConfig() 是全局注入的,不需要导入
const runtimeConfig = useRuntimeConfig();

console.log(runtimeConfig.public.apiBase);

app.config.ts

说明:

  • app.config.ts 文件位于源目录中(默认为项目的根目录),用于公开在构建时确定的公共变量。
  • runtimeConfig选项不同,app.config.ts 中的变量不能使用环境变量进行覆盖。
  • 一个最简配置文件导出了defineAppConfig函数,函数中包含了一个配置对象。defineAppConfig助手函数在全局范围内无需导入即可使用。

使用步骤:

  1. 在根目录下面定义 app.config.ts:
export default defineAppConfig({
  title: '张三的 nuxt app',
  theme: {
    dark: true,
    colors: {
      primary: '#ff0000'
    }
  }
});
  1. 在组件中使用 useAppConfig()这个 hook 来获取 appConfig
const appConfig = useAppConfig();

console.log(appConfig.title);
console.log(appConfig.theme);

对比 runtimeConfigappConfig

如上所述,runtimeConfigapp.config 都用于向应用程序的其余部分公开变量。为了确定应该使用其中之一,以下是一些指导原则:

  • runtimeConfig:需要在构建后使用环境变量指定的私有或公共令牌 (敏感项目配置)
  • app.config:在构建时确定的公共令牌,网站配置(如主题变体、标题)以及不敏感的项目配置等。
功能runtimeConfigapp.config
客户端端已注入已打包
环境变量✅ 是❌ 否
响应式✅ 是✅ 是
类型支持✅ 部分✅ 是
每个请求的配置❌ 否✅ 是
热模块替换❌ 否✅ 是
非原始JS类型❌ 否✅ 是

其他的配置文件:

Nuxt使用 nuxt.config.ts 文件作为配置的唯一来源,并跳过读取外部配置文件。在构建项目的过程中,你可能需要配置这些文件。下表列出了常见的配置:

构建配置:

名称配置文件如何配置
Nitronitro.config.tsnuxt.config中使用nitro
PostCSSpostcss.config.jsnuxt.config中使用postcss
Vitevite.config.tsnuxt.config中使用vite
webpackwebpack.config.tsnuxt.config中使用webpack

项目风格配置:

名称配置文件如何配置
TypeScripttsconfig.json更多信息
ESLint.eslintrc.js更多信息
Prettier.prettierrc.json更多信息
Stylelint.stylelintrc.json更多信息
TailwindCSStailwind.config.js更多信息
Vitestvitest.config.ts更多信息

关于 Vue 本身的一些高级配置:

参考:www.nuxt.com.cn/docs/gettin…

Nuxt 的视图渲染

入口 app.vue

  • 默认情况下,Nuxt 将把 app.vue 文件视为入口点,并为应用程序的每个路由渲染其内容。
  • 不需要像 SPA 一样考虑 main.js, 因为 Nuxt在底层已经实现了这个文件的逻辑操作。
<template>
  <div>
   <h1>欢迎来到 Nuxt App</h1>
  </div>
</template>

组件:

大多数组件是可重用的用户界面部件,如按钮和菜单。

Nuxt 中,可以按照需要在 @/components/ 目录中创建组件,这些组件将自动在整个应用程序中注册,无需显式地导入。

<template>
  <div>
    <h1>欢迎来到首页</h1>
    <AppAlert>
      这是一个自动导入的组件。
    </AppAlert>
  </div>
</template>

页面:

页面代表了每个特定路由模式的视图。@/pages 目录中的每个文件都表示一个不同的路由,显示其内容。

要使用页面,创建 pages/index.vue 文件并将 <NuxtPage /> 组件添加到 app.vue(或者删除 app.vue 以使用默认入口)。现在,你可以通过在 pages/ 目录中添加新文件来创建更多页面及其对应的路由。

  • 项目结构
app.vue
|- pages
	|- index.vue
	|- detail
  	|- 1.vue
  	|- 2.vue
  	|- 3.vue
  • app.vue中使用路由进行导入:
<template>
  <router-view />
</template>
  • 访问对应的页面:

    • http://localhost:3000
    • http://localhost:3000/detail/1
    • http://localhost:3000/detail/2
    • http://localhost:3000/detail/3

路由:

描述:

Nuxt 文件系统路由为pages/目录中的每个文件创建一个路由。

Nuxt 的核心功能之一是文件系统路由。

pages/目录中的每个 Vue 文件都会创建一个相应的URL(或路由),用于显示文件的内容。通过为每个页面使用动态导入,Nuxt 利用代码分割来仅加载所需路由的最小量 JavaScript。

目录结构:

  1. 创建如下的目录结构的文件夹和文件:
| pages/
	---| about.vue
	---| index.vue
	---| posts/
		-----| [id].vue
  ---| user-[name]/
    ----| [id].vue
  1. 最终渲染效果:
{
  "routes": [
    {
      "path": "/about",
      "component": "pages/about.vue"
    },
    {
      "path": "/",
      "component": "pages/index.vue"
    },
    {
      "path": "/posts/:id",
      "component": "pages/posts/[id].vue"
    },
    {
      "path": "/user-:name/:id",
      "component": "pages/users-[group]/[id].vue"
    }
  ]
}

提醒

  • 动态 params 路由如果配置了之后没有生效,请重启一下 nuxt 服务器!!!

标签式导航:

<NuxtLink> 组件用于在页面之间创建链接。它会将 <a> 标签渲染为具有 href 属性设置为页面的路由。

一旦应用程序被渲染,页面的切换将在 JavaScript 中进行,通过更新浏览器 URL 来实现。这样可以避免整页刷新,同时允许实现动画过渡效果。

<NuxtLink> 在客户端视口中可见时,Nuxt会自动预取链接页面的组件和负载(生成的页面),从而加快导航速度。

<template>
  <header>
    <nav>
      <ul>
        <li><NuxtLink to="/about">关于</NuxtLink></li>
        <li><NuxtLink to="/posts/1">文章1</NuxtLink></li>
        <li><NuxtLink to="/posts/2">文章2</NuxtLink></li>
      </ul>
    </nav>
  </header>
</template>

路由参数:

使用 useRoute() 这个 hook 可以访问当前路由的详细信息。

// script setup 中使用
const route = useRoute();

// 当访问/posts/1时,route.params.id将为1
console.log(route.params.id);

路由中间件:

描述:

Nuxt 提供了一个可自定义的路由中间件框架,您可以在应用程序中使用,非常适合提取在导航到特定路由之前要运行的代码。

有三种类型的路由中间件:

  1. 匿名(或内联)路由中间件,直接在使用它们的页面中定义。
  2. 命名路由中间件,放置在middleware/目录中,当在页面中使用时,会通过异步导入自动加载。(注意:路由中间件名称会转换为短横线分隔命名,因此someMiddleware会变成some-middleware。)
  3. 全局路由中间件,放置在middleware/目录中(使用.global后缀),将在每次路由更改时自动运行。

步骤:

  1. 定义中间件
export default defineNuxtRouteMiddleware((to, from) => {
  // isAuthenticated()是一个验证用户是否已经认证的示例方法
  if (isAuthenticated() === false) {
    return navigateTo('/login');
  }
});
  1. 在页面组件中使用中间件
<script setup lang="ts">
definePageMeta({
  middleware: 'auth'
});
</script>

<template>
  <h1>欢迎来到您的仪表盘</h1>
</template>

路由验证:

Nuxt通过每个要验证的页面中的 definePageMeta() 的validate属性提供路由验证。

validate 属性接受 route 作为参数。您可以返回一个布尔值来确定是否将此路由视为有效路由以渲染此页面。如果返回false,并且找不到其他匹配项,这将导致404错误。

您还可以直接返回一个带有statusCode/statusMessage的对象以立即响应错误(其他匹配项将不会被检查)。

如果您有更复杂的用例,可以使用匿名路由中间件代替。

definePageMeta({
  // 使用 validate 方法来进行校验路由
  validate: async (route) => {
    // 检查id是否由数字组成
    return /^\d+$/.test(route.params.id)
  }
});

布局:

描述:

布局是页面的包装器,包含了多个页面的共同用户界面,如页眉 header 和页脚 footer

布局是使用 <slot /> 组件来显示页面内容的 Vue 文件。layouts/default.vue 文件将被默认使用。自定义布局可以作为页面元数据的一部分进行设置。

基本使用:

  1. 创建 layouts/default.vue
<template>
  <div>
    <AppHeader />
    <slot></slot>
    <AppFooter />
  </div>
</template>
  1. 修改一下 app.vue
<template>
  <nuxt-layout>
    <div class="container">
      <router-view />
    </div>
  </nuxt-layout>
</template>

<script lang="ts" setup>
</script>

提醒:

  1. 如果你的应用程序只有一个布局,我们建议使用 app.vue
  2. 使用布局时:
    • 在页面中使用 definePageMeta 设置 layout 属性。
    • 设置 <NuxtLayout> 的 name 属性 (默认是 default)。
  3. 布局名称会被规范化为 kebab-case,因此 someLayout 将变为 some-layout
  4. 如果没有指定布局,将使用 layouts/default.vue
  5. 如果应用程序中只有一个布局,建议使用 app.vue
  6. 与其他组件不同,布局必须具有单个根元素,以允许 Nuxt 在布局更改时应用过渡效果 - 而且此根元素不能是 <slot />

更多布局:

参考:www.nuxt.com.cn/docs/guide/…

控制 HTML 模板的渲染:

添加一个 Nitro 插件来完全控制 HTML 模板,该插件注册一个钩子函数。 render:html 钩子函数的回调函数允许你在将 HTML 发送到客户端之前对其进行修改。

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('render:html', (html, { event }) => { 
    // 这将是 HTML 模板的对象表示形式。
    console.log(html);
    html.head.push(`<meta name="description" content="My custom description" />`);
  })
  // 你也可以在这里拦截响应。
  nitroApp.hooks.hook(
    'render:response',
    (response, { event }) => {
      console.log(response);
    }
  );
});

Nuxt 中的资源 & 样式访问

public 公共目录访问:

概述:

public/ 目录用作应用程序的公共服务器,用于存放在应用程序的指定URL下公开访问的静态资源。

你可以通过应用程序的代码或浏览器的根URL / 获取 public/ 目录中的文件。

示例:

例如,在 public/img/ 目录中引用一个图像文件,该文件可通过静态URL /img/nuxt.png 访问:

<template>
  <img src="/img/nuxt.png" alt="Discover Nuxt 3" />
</template>

assets 资源目录访问:

概述:

Nuxt 使用 Vite(默认)或 webpack 来构建和打包你的应用程序。

这些构建工具的主要功能是处理 JavaScript 文件,但它们可以通过 插件(对于Vite)或 加载器(对于webpack)来处理其他类型的资源,如样式表、字体或SVG。此步骤主要是为了提高性能或缓存目的而对原始文件进行转换(例如样式表的缩小或浏览器缓存失效)。

按照约定,Nuxt 使用 @/assets/ 目录来存储这些文件,但该目录没有自动扫描功能,你可以使用任何其他名称。

在应用程序的代码中,你可以通过使用 ~/assets/ 路径来引用位于 @/assets/ 目录中的文件。

示例:

例如,引用一个图像文件,如果构建工具配置为处理该文件扩展名:

<template>
  <img src="~/assets/img/nuxt.png" alt="Discover Nuxt 3" />
</template>

注意:

  • Nuxt 不会将 assets/ 目录中的文件作为静态URL(如 /assets/my-file.png)提供。
  • 如果你需要一个静态URL,请使用 public/ 目录。

全局样式引入:

概述:

要在你的 Nuxt 组件样式中全局插入语句,你可以在 nuxt.config 文件中使用 Vite 选项。

示例:

scss为例:

  1. 全局配置颜色变量 assets/_colors.scss
$primary: #49240F;
$secondary: #E4A79D;
  1. nuxt.config 中配置:
export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "@/assets/_colors.scss" as *;'
        }
      }
    }
  }
})

组件样式引入:

你可以在页面、布局和组件中直接引入样式表。

你可以使用 JavaScript 的 import,或者使用 css 的 @import语句

<script>
// 使用静态导入以实现服务器端兼容性
import '~/assets/css/first.css';

// 注意:动态导入不兼容服务器端
import('~/assets/css/first.css');
</script>

<style>
@import url("~/assets/css/second.css");
</style>

注意:

  • 样式表将被内联到 Nuxt 渲染的 HTML 中。

项目行内 css 整体引入:

你还可以使用 Nuxt 配置中的 css 属性。

将你的样式表放在 assets/目录 是最自然的位置。

然后你可以引用它的路径,Nuxt 将会将它包含在应用程序的所有页面中。

export default defineNuxtConfig({
  css: ['~/assets/css/main.css']
});

使用外部样式表:

你可以通过在 nuxt.config 文件的 head 部分添加一个 link 元素来在应用程序中包含外部样式表。你可以使用不同的方法来实现这个目标。注意,本地样式表也可以以这种方式包含。

你可以通过 Nuxt 配置的 app.head 属性来修改 head:

export default defineNuxtConfig({
  app: {
    head: {
      // 引入 animate.css
      link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
    }
}});

在 Nuxt 中请求数据:

概述:

Nuxt 提供了组合函数来处理应用程序中的数据获取。

Nuxt 提供了两个组合函数和一个内置库,用于在浏览器或服务器环境中执行数据获取:useFetchuseAsyncData$fetch

简而言之:

  • useFetch 是在组件设置函数中处理数据获取的最简单方法。
  • $fetch 可以根据用户交互进行网络请求。
  • useAsyncData 结合 $fetch,提供了更精细的控制。

useFetchuseAsyncData 共享一组常见的选项和模式,在后面的章节中我们将详细介绍。

在此之前,首先要知道为什么需要这些组合函数。

网络请求的方式

useFetchuseAsyncData 组合函数确保一旦在服务器上进行了 API 调用,数据将以有效的方式在 payload 中传递到客户端。

payload 是通过 useNuxtApp().payload 访问的 JavaScript 对象。它在客户端上用于避免在浏览器中执行代码时重新获取相同的数据

基于 <Suspense>

Nuxt 在底层使用 Vue 的 <Suspense> 组件,以防止在视图中的每个异步数据可用之前导航。数据获取组合函数可以帮助您利用此功能,并根据每个调用的需求使用最适合的方法。

$fetch

Nuxt 包括了 ofetch 库,并且作为全局别名 $fetch 自动导入到应用程序中。它是 useFetch 在幕后使用的工具。

const users = await $fetch('/api/users').catch((error) => error.data);

关于 ofetch

ofetch 库是基于 Fetch API 构建的,并为其添加了便利功能:

  • 在浏览器、Node 或 worker 环境中的使用方式相同
  • 自动解析响应
  • 错误处理
  • 自动重试
  • 拦截器

注意

  • 在通常情况下,不要直接使用 $fetch! 因为有可能会导致重复地请求数据
  • 更建议使用 useFetch()useAsyncData()这两个 hook

useFetch

useFetch 组合函数是执行数据获取的最简单的方法。

<script setup lang="ts">
  const { data: count } = await useFetch('/api/count');
</script>

<template>
  页面访问量:{{ count }}
</template>

这个组合函数是 useAsyncData 组合函数和 $fetch 工具的封装。

useAsyncData

概述:

useAsyncData 组合函数负责封装异步逻辑并在解析完成后返回结果。(和 React 的 useRequest类似)

事实上,useFetch(url) 几乎等同于 useAsyncData(url, () => $fetch(url)) - 它是为最常见的用例提供的开发者体验糖。

在某些情况下,使用 useFetch 组合函数是不合适的,例如当 CMS 或第三方提供自己的查询层时。在这种情况下,您可以使用 useAsyncData 来封装您的调用,并仍然保持组合函数提供的好处。

useAsyncData 的第一个参数是用于缓存第二个参数(查询函数)的响应的唯一键。如果直接传递查询函数,则可以忽略该参数。在这种情况下,它将自动生成。

useAsyncData 组合函数是包装和等待多个 useFetch 完成,并获取每个结果的绝佳方式。

基本使用:

const { data, error } = await useAsyncData('users', () => myGetFunction('users'));

多个 fetch 请求:

const { data: discounts, pending } = await useAsyncData('cart-discount', async () => {
  const [coupons, offers] = await Promise.all([$fetch('/cart/coupons'), $fetch('/cart/offers')])

  return {
    coupons,
    offers
  }
});

更多的配置选项:

参考:www.nuxt.com.cn/docs/gettin…

Nuxt 中的状态管理

概述:

Nuxt提供了强大的状态管理库和 useState 组合函数,用于创建响应式且适用于SSR的共享状态。

useState

什么是 useState ?

useState 是一个适用于SSR的 ref 替代品。它的值将在服务器端渲染后保留(在客户端渲染期间进行hydration),并通过唯一的键在所有组件之间共享。

useState 的基本使用:

使用步骤:

  1. app.vue中使用 useState 声明需要共享的状态 state
  2. 在子组件中 inject

代码示例:

  • 父组件:
<script setup lang="ts">
  import { provide } from 'vue';
  const counter = useState('counter', () => Math.round(Math.random() * 1000));

  provide('$$counter$$', counter);
</script>

<template>
  <div>
    计数器:{{ counter }}
    <button @click="counter++">
      +
    </button>
    <button @click="counter--">
      -
    </button>
  </div>
</template>
  • 子组件
<template>
  <div class="inner-page">
    <p>Child</p>
    <p>{{ counter }}</p>
  </div>
</template>

<script setup lang="ts">
  import { inject } from 'vue';
  import { COUNTER_KEY } from '@/configs/keys';

  const counter = inject<number>(COUNTER_KEY);

  onMounted(() => {
    console.log(counter);
  });
</script>

使用 useState 共享状态

通过使用自动导入的组合函数,我们可以定义全局类型安全的状态并在整个应用程序中导入它们:

  1. composition/states.ts中定义:
export const useCounter = () => useState<number>('counter', () => 0);
export const useColor = () => useState<string>('color', () => 'pink');
  1. app.vue 使用这些自定义 hook:
<script setup lang="ts">
  const color = useColor(); // 与useState('color')相同
</script>

<template>
  <p>当前颜色:{{ color }}</p>
</template>

推荐配合使用的状态管理库:

Nuxt 对状态管理不持有特定观点,所以请根据你的需求选择合适的解决方案。

Nuxt 与最流行的状态管理库有多种集成方式,包括:

  • Pinia - 官方推荐的 Vue 状态管理库
  • Harlem - 不可变的全局状态管理库
  • XState - 基于状态机的方法,具有可视化和测试状态逻辑的工具

部署 Nuxt 项目

概述:

学习如何将你的 Nuxt 应用部署到任何托管提供商。

Nuxt 应用可以部署在 Node.js 服务器上,预渲染以进行静态托管,或部署到无服务器或边缘(CDN)环境中。

如果你正在寻找支持 Nuxt 3 的云提供商列表,请查看托管提供商部分。

Node.js 服务器

使用 Nitro 中的 Node.js 服务器预设可以在任何 Node 托管上部署。

  • 默认输出格式,如果没有指定或自动检测
  • 仅加载渲染请求所需的块,以获得最佳的冷启动时间
  • 适用于将 Nuxt 应用部署到任何 Node.js 托管上

入口点

使用 Node 服务器预设运行 nuxt build 后,将得到一个启动准备就绪的 Node 服务器的入口点。 终端将启动你的生产 Nuxt 服务器,默认监听端口为 3000。 它会遵循以下运行时环境变量:

  • NITRO_PORTPORT(默认为 3000)
  • NITRO_HOSTHOST(默认为 '0.0.0.0')
  • NITRO_SSL_CERTNITRO_SSL_KEY - 如果两者都存在,则会以 HTTPS 模式启动服务器。
  • 在绝大多数情况下,除了测试之外,不应该使用 NITRO_SSL_KEY 选项,Nitro 服务器应该在像 nginxCloudflare 这样的反向代理后面运行,由它们终止 SSL。

PM2

要使用 pm2,请使用 ecosystem.config.js 文件:

  1. 编写 ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'NuxtAppName',
      port: '3000',
      exec_mode: 'cluster',
      instances: 'max',
      script: './.output/server/index.mjs'
    }
  ]
};
  1. 使用 npm run build打包项目

  2. 使用 pm2 start ./ecosystem.config.js启动项目

集群模式

你可以使用 NITRO_PRESET=node_cluster 来利用 Node.js 的 cluster 模块来提高多进程性能。

默认情况下,工作负载会使用轮询策略分发给工作进程。

node .output/server/index.mjs
module.exports = {
  apps: [
    {
      name: 'NuxtAppName',
      port: '3000',
      exec_mode: 'cluster',
      instances: 'max',
      script: './.output/server/index.mjs'
    }
  ]
};

静态托管

有两种方式可以将 Nuxt 应用部署到任何静态托管服务上:

  • 使用 ssr: true 进行静态站点生成(SSG),在构建时预渲染应用程序的路由(这是运行 nuxi generate 时的默认行为)。它还会生成 /200.html 和 /404.html 单页面应用回退页面,这些页面可以在客户端上渲染动态路由或 404 错误(尽管您可能需要在静态主机上进行配置)。
  • 或者,你可以使用 ssr: false 进行预渲染(静态单页面应用)。这将产生带有空的 <div id="__nuxt"></div> 的 HTML 页面,通常用于渲染 Vue 应用的位置。你会失去许多预渲染站点的 SEO 优势,因此建议使用 <ClientOnly> 来包装无法在服务器端渲染的站点部分(如果有的话)。

基于爬取的预渲染

使用 nuxi generate命令 使用 Nitro 爬虫构建和预渲染应用程序。这个命令类似于将 nuxt build 运行时的 nitro.static 选项设置为 true,或者运行 nuxt build --prerender。

终端

npx nuxi generate

就是这样!你现在可以将 .output/public 目录部署到任何静态托管服务上,或者使用 npx serve .output/public 在本地预览。

Nitro 爬虫的工作原理:

  1. 加载应用程序的根路由(/)的 HTML、~/pages 目录中的任何非动态页面以及 nitro.prerender.routes 数组中的其他路由。
  2. 将 HTML 和 payload.json 保存到 ~/.output/public/ 目录,以进行静态服务。
  3. 查找 HTML 中的所有锚点标签(<a href="...">)以导航到其他路由。
  4. 对每个找到的锚点标签重复步骤 1-3,直到没有更多的锚点标签可以爬取。

这一点很重要,因为没有链接到可发现页面的页面无法自动预渲染。

了解更多关于 nuxi generate 命令的信息。

选择性预渲染

你可以手动指定 Nitro 将在构建期间获取和预渲染的路由,或者忽略不想预渲染的路由,比如在 nuxt.config 文件中的 /dynamic 路由:

nuxt.config.ts

defineNuxtConfig({
  nitro: {
    prerender: {
      routes: ['/user/1', '/user/2']
      ignore: ['/dynamic']
    }
  }
});

你可以将此与 crawLinks 选项结合使用,以预渲染一组爬虫无法发现的路由,比如你的 /sitemap.xml 或 /robots.txt:

nuxt.config.ts

defineNuxtConfig({
  nitro: {
    prerender: {
      crawlLinks: true,
      routes: ['/sitemap.xml', '/robots.txt']
    }
  }
});

将 nitro.prerender 设置为 true 类似于将 nitro.prerender.crawlLinks 设置为 true。

在 Nitro 文档中了解更多关于预渲染的信息。

仅客户端渲染

如果你不想预渲染你的路由,另一种使用静态托管的方式是在 nuxt.config 文件中将 ssr 属性设置为 false。nuxi generate 命令将输出一个 .output/public/index.html 入口点和类似经典客户端端 Vue.js 应用程序的 JavaScript 捆绑包。

nuxt.config.ts

defineNuxtConfig({
  ssr: false
});