Vite+Vue 3+TS 配置记录

01 - 项目初始化

通过如下命令创建项目

npm init vite@latest# oryarn create vite# orpnpm create vite

得到如下的 package.json 和 .eslintrc.cjs 文件

文件:package.json

"scripts": {    "dev": "vite",    "build": "vue-tsc --noEmit && vite build",    "preview": "vite preview --port 5050",    "test:unit": "vitest --environment jsdom",    "test:e2e": "start-server-and-test preview http://127.0.0.1:5050/ 'cypress open'",    "test:e2e:ci": "start-server-and-test preview http://127.0.0.1:5050/ 'cypress run'",    "typecheck": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"  },  "dependencies": {    "pinia": "^2.0.13",    "vue": "^3.2.33",    "vue-router": "^4.0.14"  },  "devDependencies": {    "@rushstack/eslint-patch": "^1.1.0",    "@types/jsdom": "^16.2.14",    "@types/node": "^16.11.27",    "@vitejs/plugin-vue": "^2.3.1",    "@vitejs/plugin-vue-jsx": "^1.3.10",    "@vue/eslint-config-prettier": "^7.0.0",    "@vue/eslint-config-typescript": "^10.0.0",    "@vue/test-utils": "^2.0.0-rc.20",    "@vue/tsconfig": "^0.1.3",    "cypress": "^9.5.4",    "eslint": "^8.5.0",    "eslint-plugin-cypress": "^2.12.1",    "eslint-plugin-vue": "^8.2.0",    "jsdom": "^19.0.0",    "prettier": "^2.5.1",    "start-server-and-test": "^1.14.0",    "typescript": "~4.6.3",    "vite": "^2.9.5",    "vitest": "^0.9.3",    "vue-tsc": "^0.34.7"  }

文件:.eslintrc.cjs

/* eslint-env node */require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = defineConfig({  env: {    browser: true,    'vue/setup-compiler-macros': true  },  extends: [    'plugin:vue/vue3-essential',    'eslint:recommended',    '@vue/eslint-config-typescript/recommended',    '@vue/eslint-config-prettier'  ],  rules: {    'node/no-extraneous-require': 'off',    'node/no-missing-import': 'off'  },  overrides: [    {      files: ['cypress/integration/**.spec.{js,ts,jsx,tsx}'],      extends: ['plugin:cypress/recommended']    }  ]})

按正常来说,此时编写项目代码应该不会有太多问题。

由于我个人倾向于使用 SFC 方式进行编写,那么 Vue 的一些 API 使用就需要自己手动引入了。

// 文件:componentA.vueimport { ref, onMounted, computed, provide, useSlots, ...  } from 'vue'

如果再来有使用到 vue-router、pinia 这些生态包的话那么就有可能需要手动引入更多。

// 文件:componentA.vueimport { ref, onMounted, computed, provide, useSlots, ...  } from 'vue'import { useRouter, useRoute, ... } from 'vue-router'import { storeToRefs, mapActions, mapGetters, mapStores, ...  } from 'pinia'

这样的操作对于少量的组件倒是还行 CV 大法加加减减完事。但如果是要在一个有规划的项目里这样的东西多了,就会显得比较繁琐杂乱。不利于规范的建立。

02 - 自动导入

如何能够解决这样的场景那就成为了一个痛点。

好在 @Anthony Fu 开源了一个支持了 Vite 的插件 unplugin-auto-import ,这个插件能够按需自动导入所需的包。

将 unplugin-auto-import 加入到项目之后,修改 vite.config.ts 文件,新增如下内容。​​​​​​​

import ...+ import AutoImport from 'unplugin-auto-import/vite'...export default defineConfig({  ...,  plugins: [    ...,+   AutoImport({imports: ['vue', 'vue-router', 'pinia']})  ]})

修改完成后,如果不是使用了 TypeScript 的话,那么此时就可以将组件文件里关于 vue、vue-router、pinia 相关的 import 都可以删除了。​​​​​​​

- import { ref, onMounted, computed, provide, useSlots, ...  } from 'vue'- import { useRouter, useRoute, ... } from 'vue-router'- import { storeToRefs, mapActions, mapGetters, mapStores, ...  } from 'pinia'
+

但由于我这里的项目是使用了 TypeScript 所以这时候删除的话,VS Code 还是会提示 eslint的错误:ref is not defined.。

图片

根据 [unplugin-auto-import 文档](https://github.com/antfu/unplugin-auto-import#readme) 说明,插件也是支持了 TypeScript 的 d.ts 类型描述文件的生成,vite.config.ts 里改动如下。​​​​​​​

import ...
import AutoImport from 'unplugin-auto-import/vite'
...
export default defineConfig({  ...,  plugins: [    ...,-   AutoImport({ imports: ['vue', 'vue-router', 'pinia'] }),+   AutoImport({+     imports: ['vue', 'vue-router', 'pinia'],+     dts: 'types/auto-imports.d.ts',+     eslintrc: {+       enabled: false,+       filepath: 'types/.eslintrc-auto-import.json',+       globalsPropValue: true,+     },+   }),  ],})

参数解释看这里:[configuration](https://github.com/antfu/unplugin-auto-import#configuration)

新增的这些参数主要还是用于支持 TypeScript,我这里是习惯于将 *.d.ts 这类文件统一放置在 types 文件夹下。

将文件生成后,那么 types 文件夹下将会出现 auto-imports.d.ts 与 .eslintrc-auto-import.json 两个文件。这两个文件将需要分别配置到 tsconfig.json 与 .eslintrc.cjs 中。

关系如下:

  • tsconfig.json <- auto-imports.d.ts

  • .eslintrc.cjs <- .eslintrc-auto-import.json

修改 tsconfig.json​​​​​​​

{  "include": [    ...,+   "types/auto-imports.d.ts"  ]}

修改 .eslintrc.cjs​​​​​​​

module.exports = defineConfig({  extends: [    ...,+   './types/.eslintrc-auto-import.json'  ]})

修改完成后就能得到正确的类型提示了。

图片

03 - 自定义类型支持

使用 TypeScript 的项目中难免会有一些自定义的类型,虽然 与文件同名.d.ts 能够解决当前文件的类型定义,但总是会有一些公共的类型需要定义,例如请求返回的自定义数据体。

假设自定义一个类型文件:types/request.d.ts​​​​​​​

// 假设返回数据结构如下type ResultData = {  code: number  msg: string  data: unknown}

这时候在非当前文件中使用该类型定义的时候,则会提示:ResultData is not defined.

非 *.ts 文件是由 eslint 提示错误。

图片

*.ts 文件是由 TS 自身提示错误。

图片

如有多个文件中都使用了请求函数,那么就需要编写多次或者引入类型文件使用该类型,这样并不利于管理也过于散乱,也有可能修改一处,其它处都需要修改。

所以我就想着是否可以通过配置的方式实现全局使用该类型呢?

其实是可以的。

解决 *.ts 使用自定义类型报错提示

解决 *.ts 文件的报错就比较简单了。

types/request.d.ts 文件修改如下。​​​​​​​

- type ResultData = {+ declare type ResultData = {  code: number  msg: string  data: unknown}

tsconfig.json 文件修改如下。​​​​​​​

{  "include": [    ...,+   "types/request.d.ts"  ]}

修改完成后即可得到正确的类型提示,也不需要再次定义或者引入额外的类型文件。

图片

解决非 *.ts 使用自定义类型报错提示

*.ts 文件的类型使用报错解决了,但这只是针对于 *.ts 的,而非 *.ts 的文件使用该类型还是会有 eslint 的错误提示。

新增一个 types/.eslintrc-request.json 文件用于 eslint 错误提示的解决。​​​​​​​

{  "globals": {    "ResultData": true  }}

.eslintrc.cjs 文件修改如下。​​​​​​​

module.exports = defineConfig({  extends: [    ...,+   './types/.eslintrc-request.json'  ]})

文件添加完成后也可得到了正确的类型提示了。

文件:componentA.vue

图片

04 - 组件命名

关于给组件命名的问题,Vue 3 所提供的方式有限,且也不够优雅,写起来终是感觉有点奇怪。

对于这个问题,我去看了一些开源库的应用最终目标指向为 unplugin-vue-define-options 由三咲智子开源的插件。

正常来说仅需要在 vite.config.ts 新增如下内容即可实现。​​​​​​​

import ...+ import DefineOptions from 'unplugin-vue-define-options/vite'
...
export default defineConfig({  ...,  plugins: [    ...,+   DefineOptions()  ]})

TypeScript 项目则需要修改 tsconfig.json 文件,新增类型支持。​​​​​​​

{  ...,  "compilerOptions": {+   "types": ["unplugin-vue-define-options/macros-global"]  }}

使用 defineOptions 函数即可定义。

文件:componentA.vue​​​​​​​

defineOptions({  name: 'Dialog'})

pnpm-workspace package 分项目的问题

但由于我这使用了 pnpm-workspace,那么 A项目 的 UI 组件由 B项目 提供。

目录结构如下:​​​​​​​

- packages  - A  - B

其关系是使用 "workspace:*" 方式绑定,而 B项目 除必要包外都由 A项目 引入。

那么这个时候在 B项目 中使用 defineOptions 就是会出现报错的:defineOptions is not defined.。

图片

解决:在 A项目 中 tsconfig.json 配置 B项目 别名路径即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值