nuxt

200 阅读4分钟

特点

  • 基于文件的路由:根据 pages/ 目录的结构定义路由。
  • 代码分割:Nuxt 会自动将您的代码分割成更小的块,这有助于减少应用程序的初始加载时间。
  • 开箱即用的服务器端渲染:Nuxt 内置 SSR 功能,因此您不必自己设置单独的服务器。
  • 自动导入:在各自的目录中编写 Vue 可组合和组件,并使用它们,而无需导入它们,并具有树抖动和优化的JS 包的好处。
  • 数据获取实用程序:Nuxt 提供了可组合的工具来处理与 SSR 兼容的数据获取以及不同的策略。
  • 零配置TypeScript支持:编写类型安全代码,而无需使用我们自动生成的类型和 tsconfig.json 学习TypeScript
  • 已配置的构建工具:我们默认使用 Vite 来支持开发中的热模块替换(HMR),并将您的代码与最佳实践捆绑在一起用于生产。

在开发过程中,它使用 Rollup 和 Node.js worker 来进行服务器代码和上下文隔离。它还通过阅读 server/api/ 中的文件和 server/middleware/ 中的服务器中间件来生成您的服务器API。

Nuxt 由不同的核心包组成:

安装

Node.js - v18.0.0 或更新版本

official Vue extension

Nuxtr extension

npx nuxi@latest init <project-name>

配置

nuxt.config.ts 文件位于 Nuxt 项目的根目录,可以覆盖或扩展应用程序的行为。

环境变量

runtimeConfig 将环境变量等值暴露给应用程序的其他部分。默认情况下,这些密钥仅在服务器端可用。 runtimeConfig.public 中的键可以用于客户端。

// .env
# This will override the value of apiSecret
NUXT_API_SECRET=api_secret_token
<script setup lang="ts">
const runtimeConfig = useRuntimeConfig()
</script>

位于源目录 app.config.ts 文件用于公开可在构建时确定的公共变量。这些不能使用环境变量覆盖。

export default defineAppConfig({
  title: 'Hello Nuxt',
  theme: {
    dark: true,
    colors: {
      primary: '#ff0000'
    }
  }
})
<script setup lang="ts">
const appConfig = useAppConfig()
</script>
  • runtimeConfig :需要在构建后使用环境变量或者私有或公共 token。
  • app.config: 构建时使用公共 token ,网站配置,如主题变量,标题和任何不敏感的项目配置
特点runtimeConfigapp.config
客户端Hydrated Bundled 
环境变量✅ Yes ❌ No 
Reactive ✅ Yes ✅ Yes 
类型支持✅ Partial ✅ Yes 
按请求配置❌ No ✅ Yes 
热模块替换❌ No ✅ Yes 
非原始 JS 类型❌ No ✅ Yes 

外部工具配置

NameConfig FileHow To Configure
Nitronitro.config.tsUse nitro key in nuxt.config
PostCSSpostcss.config.jsUse postcss key in nuxt.config
Vitevite.config.tsUse vite key in nuxt.config
webpackwebpack.config.tsUse webpack key in nuxt.config
NameConfig FileHow To Configure
TypeScripttsconfig.jsonMore Info
ESLinteslint.config.jsMore Info
Prettier.prettierrc.jsonMore Info
Stylelint.stylelintrc.jsonMore Info
TailwindCSStailwind.config.jsMore Info
Vitestvitest.config.tsMore Info

vite 配置

  • vite.vue 对应 @vitejs/plugin-vue
  • vite.vueJsx 对应 @vitejs/plugin-vue-jsx
// nuxt.config.ts

export default defineNuxtConfig({
  vite: {
    vue: {
      customElement: true,
    },

    vueJsx: {
      mergeProps: true,
    },
  },
});

视图

app.vue

入口文件,main.js nuxt 自动处理

components

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

Pages

创建 pages/index.vue 文件并将 <NuxtPage /> 组件添加到 app.vuepages/ 目录中添加新文件来创建更多页面及其相应的路由。

layouts

默认使用 layouts/default.vue 文件布局

<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>

扩展HTML模板

// server/plugins/extend-html.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('render:html', (html, { event }) => {
    // This will be an object representation of the html template.
    console.log(html)
    html.head.push(`<meta name="description" content="My custom description" />`)
  })
  // You can also intercept the response here.
  nitroApp.hooks.hook('render:response', (response, { event }) => { console.log(response) })
})

静态资源

public 目录用作静态资产的公共服务器,可以 / 获取 public/ 目录中的文件

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

Assets 经过构建,如样式表,字体 或 SVG,使用 ~/assets/ 路径引用位于 assets/ 目录中的文件。

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

全局样式导入

// assets/_colors.scss
$primary: #49240F;
$secondary: #E4A79D;
// nuxt.config
export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "~/assets/_colors.scss" as *;',
        },
      },
    },
  },
});

样式

本地样式表可以放在 assets 目录,全局使用

<script>
// Use a static import for server-side compatibility
import '~/assets/css/first.css'

// Caution: Dynamic imports are not server-side compatible
import('~/assets/css/first.css')
</script>

<style>
@import url("~/assets/css/second.css");
</style>
export default defineNuxtConfig({
  css: ['~/assets/css/main.css']
})

字体

字体文件放到 public 目录, assets 目录 css 文件引用

/* assets/css/main.css */
@font-face {
  font-family: 'FarAwayGalaxy';
  src: url('/fonts/FarAwayGalaxy.woff') format('woff');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}
<style>
h1 {
  font-family: 'FarAwayGalaxy', sans-serif;
}
</style>

npm 样式

// app.vue
<script>
import 'animate.css'
</script>

<style>
@import url("animate.css");
</style>
// nuxt.config.ts
export default defineNuxtConfig({
  css: ['animate.css']
})

CDN

// nuxt.config.ts

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

useHead({
  link: [
    {
      rel: "stylesheet",
      href: "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css",
    },
  ],
});
export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook('render:html', (html) => {
    html.head.push('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">')
  })
})

Vue 单文件 JS 和 css 相互使用

<script setup lang="ts">
const color = ref("red")
</script>

<template>
  <div class="text">hello</div>
</template>

<style>
.text {
  color: v-bind(color);
}
</style>
<template>
  <p :class="$style.red">This should be red</p>
</template>

<style module>
.red {
  color: red;
}
</style>

使用 PostCSS

// nuxt.config.ts
export default defineNuxtConfig({
  postcss: {
    plugins: {
      'postcss-nested': {}
      "postcss-custom-media": {}
    }
  }
})
<style lang="postcss">
  /* Write postcss here */
</style>

默认情况下,Nuxt 附带以下已预配置的插件:

  • postcss-import:改进了 @import 规则
  • postcss-url:转换 url() 语句
  • autoprefixer:自动添加供应商前缀
  • cssnano:压缩和清除

路由

pages 文件对应路由

导航

<template>
  <header>
    <nav>
      <ul>
        <li><NuxtLink to="/about">About</NuxtLink></li>
        <li><NuxtLink to="/posts/1">Post 1</NuxtLink></li>
        <li><NuxtLink to="/posts/2">Post 2</NuxtLink></li>
      </ul>
    </nav>
  </header>
</template>

路由参数

<script setup lang="ts">
const route = useRoute()

// When accessing /posts/1, route.params.id will be 1
console.log(route.params.id)
</script>

路由中间件