Skip to content

大家好,我是村长!

上一节我们学习了 Nuxt3 处理异常的各种方法,本讲我们将结合项目开发实践给大家介绍一些比较常用的配置项,为以后的项目开发做准备,本节涉及内容如下:

  • 几种配置方式对比;

  • 开发常用配置;

  • 配置 Meta 信息。

几种配置方式对比

Nuxt 应用中有三种常见的配置方式:

  • nuxt.config.ts:覆盖或扩展默认 Nuxt 配置;

  • app.config.ts:配置公共变量;

  • 外部配置文件:配置项目中其他方面。

nuxt.config.ts

Nuxt 其实有一套默认配置,能够应付大部分需要。但是当我们需要覆盖或扩展默认 Nuxt 配置时,我们就可以在项目根目录下创建一个 nuxt.config.ts,它默认导出 defineNuxtConfig() 的执行结果,再和默认 nuxt 配置合并并最终生效,例如我们前面增加的模块配置:

typescript
    export default defineNuxtConfig({
      modules: [
        "@nuxtjs/tailwindcss",
        "@pinia/nuxt",
        "@huntersofbook/naive-ui-nuxt",
      ],
    });

我们会在后面演示一些开发中比较常见的配置方法。

app.config.ts

如果需要配置一些项目需要的公共变量,可以在项目根目录创建 app.config.ts,这些变量是响应式的,不仅在运行时可以访问,还可以改变。例如下面的配置范例:

typescript
    export default defineAppConfig({
      title: 'Hello Nuxt',
      theme: {
        dark: true,
        colors: {
          primary: '#ff0000'
        }
      }
    })

实际上,nuxt.config.ts 中有个 appConfig 选项可以起到相同的作用。

访问 app.config.ts 中的变量:

typescript
     const appConfig = useAppConfig()

范例:根据配置项设置黑暗模式

创建 ~/pages/config.vue,根据 app.config.ts 中的配置控制黑暗模式和标题。

vue
    <template>
      <div :class="{ dark: appConfig.theme.dark }">
        <p
          class="bg-blue-300 dark:bg-slate-600 dark:text-slate-200"
          @click="appConfig.title = 'hello'"
        >
          appConfig: {{ appConfig.title }}
        </p>
    
        <label>
          dark mode:
          <NSwitch id="toggle" v-model:value="appConfig.theme.dark" />
        </label>
      </div>
    </template>
    
    <script setup lang="ts">
    const appConfig = useAppConfig();
    </script>

需要额外开启 tailwind 黑暗模式,tailwind.config.js:

javascript
     module.exports = {
       darkMode: 'class',
     }

效果如下:

外部配置文件

Nuxt 只认 nuxt.config.ts,因此一些大家熟悉的独立配置文件会被忽略,作为替代,nuxt.config.ts 中会有对应的配置项,我们来看一下都有哪些:

  • nitro.config.ts :不能使用,使用 nitro 选项配置;
  • postcss.config.js :不能使用,使用 postcss 选项配置;
  • vite.config.ts :不能使用,使用 vite 选项配置;
  • webpack.config.ts :不能使用,使用 webpack 选项配置。

当然,还有一些配置文件依然可以使用:

  • tsconfig.json;
  • .eslintrc.js;
  • .prettieerrc.json;
  • .stylelintrc.json;
  • tailwind.config.js;
  • vitest.config.js。

开发常用配置

下面我们演示一些开发中非常常用的配置项,掌握它们对我们开发很有帮助。

配置打包工具

Nuxt 支持 Vite、Webpack 两种打包工具,默认使用 Vite。我们可以根据项目需要选择,设置 builder 即可。

下面配置设置打包工具为 Webpack:

typescript
    export default defineNuxtConfig({
      builder: "webpack"
    });

注意:需要安装 @nuxt/webpack-builder。

相应的,如果要修改对应打包工具配置,可以使用 Vite 或 Webpack 选项:

typescript
    export default defineNuxtConfig({
      vite: {},
      webpack: {}
    });

配置渲染模式

Nuxt 默认渲染模式是 SSR 模式。

可以通过设置 ssr: false 修改渲染模式为 SPA,nuxt.config.ts:

typescript
    export default defineNuxtConfig({
      ssr: false,
    })

可以通过设置 nitro.presets 选项修改渲染模式为非 node 模式,nuxt.config.ts:

typescript
    export default defineNuxtConfig({
      nitro: {
        preset: 'vercel'
      },
    })

端口号

配置了端口号为 8080,避免和其他本地服务端口冲突,package.json:

typescript
    {
      "scripts": {
        "dev": "nuxt dev --port=8080"
      }
    }

环境变量

Nuxt 配置中有一个运行时配置 runtimeConfig 可用于对外暴露值,就像环境变量、秘钥等。默认情况下这些 key 只能用于服务端,除非把 key 存储在 runtimeConfig.public 字段中。跟 appConfig 比起来,它们只能在 nuxt.config 中定义,值可以被环境变量覆盖,且不能在运行时修改。

添加 runtimeConfig,nuxt.config.ts:

typescript
    export default defineNuxtConfig({
      runtimeConfig: {
        // 只能用于服务端的 keys
        apiSecret: '123',
        // 可用于客户端的 keys
        public: {
          apiBase: '/api'
        }
      }
    })

访问runtimeConfig,修改 config.vue:

vue
    <template>
      <div :class="{ dark: appConfig.theme.dark }">
        <!-- ... -->
        <!-- 客户端只能访问public里面的key -->
        <p
          class="bg-blue-300 dark:bg-slate-600 dark:text-slate-200"
          @click="appConfig.title = 'hello'"
        >
          runtimeConfig.public.apiBase: {{ runtimeConfig.public.apiBase }}
        </p>
        <!-- ... -->
      </div>
    </template>
    
    <script setup lang="ts">
    const runtimeConfig = useRuntimeConfig()
    console.log('Runtime config:', runtimeConfig)
    // 只在服务端才能输出
    if (process.server) {
      console.log('API secret:', runtimeConfig.apiSecret)
    }
    </script>

服务端效果如下:apiBase 和 apiSecret 都可以访问:

客户端效果如下:只有 apiBase:

范例:环境变量配置

结合 dotenv 可以配置环境变量并覆盖 runtimeConfig 中的对应项,创建 .env 文件:

yml
    NUXT_API_SECRET=api_secret_token
    NUXT_PUBLIC_API_BASE=https://nuxt3.cn

注意 NUXTNUXT_PUBLIC 前缀,以及驼峰转换对应关系。

现在再看效果:

自动导入

该选项主要设置自动导入,例如前面的 store 目录就可以通过配置该选项,避免用户每次使用时手动导入。nuxt.config.ts:

typescript
    export default defineNuxtConfig({
      imports: {
        dirs: ['store']
      },
    }

现在 [id].vue 和 login.vue 中都不需要手动导入 useUser 了!

配置 Meta 信息

我们常常因为 SEO 等需求需要修改页头等 Meta 信息,Nuxt 提供三种修改 Meta 信息的方法:

  • 全局配置页头信息;
  • composables 方法;
  • 内置组件修改。

全局配置页头信息

通过 app.head 可以全局配置网站页头信息:

typescript
    export default defineNuxtConfig({
      app: {
        head: {
          charset: 'utf-8', // 快捷方式
          viewport: 'width=device-width, initial-scale=1', // 快捷方式
          title: 'My App',
          meta: [
            { name: 'description', content: 'My amazing site.' },
            { name: 'charset', content: 'utf-8' },
          ],
          "link": [],
          "style": [],
          "script": []
        }
      }
    })

范例:设置博客范例页头信息

我们在 nuxt.config.ts 中配置整站的描述和关键字:

typescript
    export default defineNuxtConfig({
      app: {
        head: {
          title: "村长的技术空间",
          meta: [
            { name: "description", content: "专注于前端技术分享" },
            { name: "keywords", content: "nuxt,vue,ts,frontend" },
          ]
        },
      }
    })

效果如下:

composables 方法

Nuxt 提供了一个 useHead() 可以在组件内修改 meta 信息:

vue
    <script setup lang="ts">
    useHead({
      title: 'My App',
      meta: [
        { name: 'description', content: 'My amazing site.' }
      ],
      bodyAttrs: {
        class: 'test'
      },
      script: [ { children: 'console.log('Hello world')' } ]
    })
    </script>

范例:设置各子页面标题

设置首页标题,index.vue

typescript
    useHead({
      title: '文章列表'
    })

这样虽然生效,但之前设置的网站名称被覆盖了:

可以设置标题模板解决此问题,app.vue:

vue
    <script setup lang="ts">
    useHead({
      titleTemplate: (s) => {
        return s ? `${s} - 村长的技术空间` : "村长的技术空间";
      },
    });
    </script>

问题解决了:

再去详情页设置页面标题,[id].vue:

typescript
    const route = useRoute();
    // 设置为当前文章id
    useHead({
      title: route.params.id as string
    });

效果如下:

当然也可以设置为文章标题:

typescript
    const { data, pending, error } = await useAsyncData("post", fetchPost);
    // 设置为文章结果
    useHead({
      title: data.value?.title
    });

效果如下:

内置组件修改

Nuxt 还提供了多种组件可以在模板中设置具体页面页头信息:<Title>, <Base>, <NoScript>, <Style>, <Meta>, <Link>, <Body>, <Html> , <Head>,像下面这样使用:

vue
    <script setup>
    const title = ref('Hello World')
    </script>
    
    <template>
      <div>
        <Head>
          <Title>{{ title }}</Title>
          <Meta name="description" :content="title" />
        </Head>
      </div>
    </template>

这更符合大家直觉了!在 [id].vue 中试一下:效果如初~

vue
    <template>
      <div class="p-5">
        <Head>
          <Title>{{ data?.title }}</Title>
        </Head>
        <!-- ... -->
      </div>
    </template>

总结

到这里,开发中常见选项设置就跟大家讨论完毕了。我们不太可能在一节中覆盖全部内容,但是我们演示这些都是最常见的配置需求,可以解决大家大部分问题。更多细节还需要大家多多阅读文档

下次预告

由于服务端渲染不再像 SPA 一样是一堆静态文件,因此在部署上会复杂一些。下一步我们将探讨 Nuxt 项目的打包部署相关知识。

Released under the MIT License.