2023-07-07 Nuxt3 项目构建记录

1,360 阅读5分钟

Reference

构建依赖及模板

Awesome nuxt 一些包收集

Nuxt modules 官网一些包(与上面或许有重叠)

nuxt3-awesome-starter 一个模板项目,可参考其使用的配置、包、插件

常用储备点

.npmrc config

tsx写法

Userful Moudles Collect (To be adopt)

  1. PWA - Supercharge Nuxt with a heavily tested, updated and stable PWA solution.
  2. Auth - Authentication module for Nuxt.js.
  3. Dotenv - Loads your .env file into your application context.(只支持Nuxt2)
  4. Unocss - like tailwind css
  5. TailwindCSS - TailwindCSS module for Nuxt.js with PurgeCSS.
  6. Color Mode - Dark and Light mode with auto detection made easy with NuxtJS
  7. @nuxt/content 直接页面的方式展示markdonw文件,个人认为可以作为一些静态的规则、协议页面。Nuxt Content reads the content/ directory in your project, parses .md.yml.csv or .json files and creates a powerful data layer for your application. Bonus, use Vue components in Markdown with the MDC syntax.
  8. nuxt/devtools 217670797-12c33a03-ca4f-490d-a18a-ab9008b89c15.png
  9. pinia-plugin-persistedstate 持久化
  10. Nuxt/image 图片预加载、优化等
  11. nuxt/device 设备类型hook

Useful Package Collection

  1. qs 具有一定安全性的查询字符串解析和字符串化库。
  2. postcss-px-to-viewport-8-plugin 此为nuxt3版本,nuxt2版本:postcss-px-to-viewport

Dev Tips

  1. Volar TakeOverMode 在这个模式下,Volar 能够使用一个 TS 语言服务实例同时为 Vue 和 TS 文件提供支持。Nuxt 文档中prerequisites章节中提到的
  2. nuxt.config.ts 支持的配置项 ts 定义在 interface ConfigSchema
  3. composables 目录下的文件会自动 imports,前提是项目运行前要执行过以下提到的命令:Be aware that you have to run nuxi preparenuxi dev or nuxi build in order to let Nuxt generate the types. If you create a composable without having the dev server running, TypeScript will throw an error, such as Cannot find name 'useBar'.
  4. useFetch useAsyncDatawatch 配置项含义。
    默认会自动 watch 请求 url 及 fetch options,当两者发生变化会自动发起请求。同时 watch 项可提供一个响应式数据源,当此数据变化也同时自动发起请求。 如watch置为 false,则请求 url、fetch options 发生变化也不会自动发起请求。
    在手动调用的场景中(即 watchimmediate 选项设为 false),和传入响应性参数,再手动 excute 不矛盾:
const iName = ref('shuazi')
const { data, excute } = useFetch('http://xxx/foo/bar', {
    method: "post",
    body: computed(() => ({
        name: iName,
        job: 'fe'
    })),
    watch: false,
    imediate: false,
})

onMounted(() => {
    setTimeout(() => {
        // !请求参数发生变化,不会自动请求,需手动执行 excute,请求参数为变化后的参数
        iName.value = '刷子'
        excute()
    }, 3000)
})
  1. Nuxt 会根据 pages 下的接口生成路由,同时也可以自定义配置路由,配置方法:自定义路由配置
  2. body 配置 class: nuxtConfig 以及 useHead 中 bodyAttrs 配置
  3. 路由卫士,使用全局中间件
  4. 针对不同页面使用不同渲染模式

踩坑记录

  • pnpm 初始化项目时控制台报错:Conflicting Peer Dependency: vite

解决方案:How To Fix the npm “Conflicting Peer Dependency” Error 手动安装了所需版本,在devDependencies中

  • eslint + prettier 搭配配置。

可以参考此文章配置,再额外安装包 vue-eslint-parser @typescript-eslint/parser,最终配置如下:

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
  },
  parser: "vue-eslint-parser",
  parserOptions: {
    parser: "@typescript-eslint/parser",
  },
  extends: [
    "@nuxtjs/eslint-config-typescript",
    "plugin:vue/vue3-recommended",
    "plugin:prettier/recommended",
  ],
  plugins: [],
  rules: {
    "vue/multi-word-component-names": "off",
  },
};

过程中遇到报错 prettier.resolveConfig.sync is not a function原因为 prettier 3 和 eslint-plugin-prettier 4 不兼容

  • @nuxtjs/tailwindcss 模块安装后使用 jit 如 w-[100px] 编译后未转义为 vw,为了使用 jit 则不引入此模块,转而使用独立配置(配置参考 tailwind 官网指导配置):

defineNuxtConfig({
  // ...
  // tailwind 相关
  css: ['~/assets/css/tailwind.css'],
  postcss: {
    plugins: {
      // tailwind 相关
      tailwindcss: {},
      autoprefixer: {},
      
      // 以下为转 vw 配置
      // https://github.com/lkxian888/postcss-px-to-viewport-8-plugin#readme
      'postcss-px-to-viewport-8-plugin': {
        unitToConvert: 'px', // 需要转换的单位,默认为"px"
        viewportWidth: 750, // 设计稿的视口宽度
        unitPrecision: 5, // 单位转换后保留的精度
        propList: ['*'], // 能转化为vw的属性列表,!font-size表示font-size后面的单位不会被转换
        viewportUnit: 'vw', // 希望使用的视口单位
        fontViewportUnit: 'vw', // 字体使用的视口单位
        // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
        // 下面配置表示类名中含有'keep-px'都不会被转换
        selectorBlackList: ['keep-px'],
        minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
        mediaQuery: false, // 媒体查询里的单位是否需要转换单位
        replace: true, //  是否直接更换属性值,而不添加备用属性
        exclude: [/node_modules/], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
        include: [/src/, /node_modules/], // 如果设置了include,那将只有匹配到的文件才会被转换
        landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
        landscapeUnit: 'vw', // 横屏时使用的单位
        landscapeWidth: 1338 // 横屏时使用的视口宽度
      }
    }
  },
  // ...
 }
  • 配置二级目录

app.baseURL 配置二级目录;
副作用:这个配置项会改变请求地址,因此可以在 useFetch 的配置项 baseURL 加以覆盖

  • 开发环境中的接口代理

在开发环境中请求各个环境的接口,需要node层做代理避免本地请求跨域

  1. 不是 vite.server.proxy 配置,此配置只在 client 端奏效
  2. 不是 nitro.devProxy 配置,此配置两端完全无效

解决方案: 通过 routeRules 配置,需要区分环境,旨在开发环境中做代理,代码如下:

routeRules: {
    // 无需区分环境的配置
    "/": { redirect: "/home" },
    
    // 需要区分环境
    ...(() => {
      const rrules: Record<string, any> = {};

      if (process.env.NODE_ENV === "development") {
        rrules["/motorapi/**"] = {
          proxy: { to: "https://xxxxx/motorapi/**" },
        };
      }
      return rrules;
    })(),
  }
  • useFetch 相关请求配置 server: falseimmediate: false 或导致返回值 pending 始终为true 且无响应性,相关 issue

作者的意思 pending 并非我们开发理解的当前接口请求正处于请求挂起的状态,因此用此字段判断接口是否在请求不恰当。

~/plugins/ 创建插件执行时一直报错 defineNitroPlugin is not defined 。使用场景为:根据不同的ua环境,加载不同的脚本,比如微信渠道加载微信 jssdk。

defineNitroPlugin 一共有3个钩子render:response render:html render:island