手把手教你搭建vite开发环境 - [vue3ts 代码检查,单元测试, 异步组件,自动生成 .d]
第一期我们搭建了基础结构后,项目依然需一些代码检查类的工作,这里暂时选用的 eslint + prettierrc 的格式化工具,事例如下:
配置 eslint + prettierrc
所需的安装包如下:
$ yarn add eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue vue-eslint-parser @typescript-eslint/eslint-plugin @typescript-eslint/parser -D
首先是 eslint、prettier 模块 和 eslint 插件模块
eslint、prettier 不必多说,现在先聊一下eslint的插件部分
-
eslint-plugin-vue
插件是vue官方给eslint提交的一个插件,其目的是给eslit支持解析.vue后缀的能力,也提供了一些有用的解析器服务来帮助遍历生成的 AST 和访问模板令牌:context.parserServices.defineTemplateBodyVisitor(visitor, scriptVisitor)
context.parserServices.getTemplateBodyTokenStore()
-
vue-eslint-parser
做的工作是让eslit可以正常解析vue文件,和上面的eslint-plugin-vue
的区别是:- eslint-plugin-vue 是一个针对vue内容的检查插件
- vue-eslint-parser 则是对 vue 文件进行编译和和解析的
两个包虽然都会去读
.eslintrc
的配置,但是其工作原理不同,eslint-plugin-vue 插件依赖vue-eslint-parser
解析器,vue-eslint-parser
解析器,只解析 .vue 中html部分的内容,不会检测<script>
中的JS内容,由于Vue中的单个文件组件不是普通的JavaScript,因此无法使用默认解析器,因此引入了新的解析器。vue-eslint-parser
生成带有节点的增强型AST,这些节点代表模板语法的特定部分以及<script>
标记内的内容。 -
eslint-plugin-prettier
插件会调用prettier对你的代码风格进行检查,其原理是先使用prettier对你的代码进行格式化,然后与格式化之前的代码进行对比,如果过出现了不一致,这个地方就会被prettier进行标记 -
eslint-config-prettier
插件是麻省理工提供的eslint和prettier的扩展程序,他并非以插件形式运作,而是去通过污染prettier的配置选项的方式工作的,有兴趣的同学可以访问他们的github -
@typescript-eslint/eslint-plugin
和@typescript-eslint/parser
看完了上面的vue相关的eslint插件的描述,大家对这两个插件的用途应该也理解了吧,当然,ts里还是做了很多关于ts的类型语言的解释的,这是vue-eslint-parser所没有的
配置事例
// .eslintrc.js
// options to see https://eslint.org/docs/user-guide/configuring/
module.exports = {
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: {
tsx: true,
jsx: true,
},
},
settings: {
tsx: {
version: 'detect',
},
},
ignorePatterns: ['node_modules/', 'dist/'],
extends: ['plugin:vue/vue3-recommended', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
rules: {},
}
// .prettierrc.js
// options to see https://prettier.io/docs/en/options.html
module.exports = {
printWidth: 120,
tabWidth: 2, // tab 2 spaces
semi: false, // no semicolons
singleQuote: true, // use single quotes
trailingComma: 'es5', // trailing commas es5
jsxSingleQuote: false,
jsxBracketSameLine: false,
arrowParens: 'always',
vueIndentScriptAndStyle: true,
htmlWhitespaceSensitivity: 'strict',
}
代码风格检查的配置差不多配置完毕了。我们现在配置一下eslint检查的package命令,方便以后进行检查
// package.json
{
"script": {
...
"lint:fix": "eslint src --fix --ext .ts,.tsx"
}
}
如果大家使用的是 vscode
, 下载一下相关插件然后打开auto format on save就可以在保存文件的时候自动格式化了
增加 Jest 单元测试 vitest
关于 Jest 单元测试,看到其他博主都给了很多自己安装的解决方案,实际官方给出了vitest的解决方案,官网在上面,使用方式也很简单
- 在项目内引入
$ yarn add @vue/test-utils jsdom vitest -D
- 在vite.config.ts内写入配置项
下面这是引入 test 的类型声明
/// <reference types="vitest" />
...
export default defineConfig({
...
test: {
globals: true,
environment: 'jsdom',
transformMode: {
web: [/.[tj]sx$/],
},
},
...
})
官方给出了各种框架下的使用案例,有兴趣的同学可以戳这里
写个单测试一下:
// utils.ts
export const getArrayDiff = <T>(array: Array<T>, otherArr: Array<T>): Array<T> => {
return array.filter((item) => !otherArr.includes(item))
}
// utils.spec.ts
import { getArrayDiff } from '../index'
describe('/utils/index.ts', () => {
it('getArrayDiff', () => {
const array = [1, 2, 3, 4, 5]
const otherArr = [1, 2, 3, 4, 5, 6]
expect(JSON.stringify(getArrayDiff(array, otherArr))).toBe(JSON.stringify([]))
})
})
可以看到单测已经可以运行了,
而后我们在命令行加入调试命令,方便之后的git提交前进行脚本执行
{
"scripts": {
...
"test": "vitest",
"coverage": "vitest run --coverage"
},
}
现在为止,单元测试已经可以正常运作了,我们继续进行路由的异步处理
异步化路由和文件
借用vue官方文档的描述
以前,异步组件是通过将组件定义为返回 Promise 的函数来创建的,例如:
const asyncModal = () => import('./Modal.vue')
或者,对于带有选项的更高阶的组件语法:
const asyncModal = {
component: () => import('./Modal.vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
}
现在,在 Vue 3 中,由于函数式组件被定义为纯函数,因此异步组件需要通过将其包裹在新的 defineAsyncComponent
助手方法中来显式地定义:
import { defineAsyncComponent } from 'vue'
import ErrorComponent from './components/ErrorComponent.vue'
import LoadingComponent from './components/LoadingComponent.vue'
// 不带选项的异步组件
const asyncModal = defineAsyncComponent(() => import('./Modal.vue'))
// 带选项的异步组件
const asyncModalWithOptions = defineAsyncComponent({
loader: () => import('./Modal.vue'),
delay: 200,
timeout: 3000,
errorComponent: ErrorComponent,
loadingComponent: LoadingComponent
})
我们全局注入的组件就需要从之前的Vue.component
注入的方式改掉了,从隐式调用,改为显示声明的方式来做。
// vue2.x
Vue.component('async-example', () => import('@/componets/test.vue')
// vue3.x
import { defineAsyncComponent } from 'vue'
app.component('async-example', defineAsyncComponent(() =>
import('@/componets/test.vue')
)
这样全局注册的组件,vue就会知道它需要异步加载的,而非直接注入。异步的方式也比较简单,检测它是否是一个promise,而进行标记性定义
自动生成ts.d类型声明文件
vite社区提供了一个插件 vite-plugin-dts
,这是个国人作者 github请戳vite-plugin-dts
使用也很简单,即装即用, 是一个 基于rollup打包写的插件,也有一些rollup的接口可以去配置你的输出结果,是个不错的工具
$ yarn add vite-plugin-dts -D
export default defineConfig({
...
build: {
...
lib: {
entry: resolve(__dirname, 'src/main.ts'),
name: 'MyLib',
formats: ['es'],
fileName: 'my-lib' // 输出的.d文件名称事例将会生成 my-lib.d.ts
}
},
plugins: [..., dts()]
})
经过上面的配置,我们的 .d 文件就可以直接在我们dist打包目录的根目录下找到了,是不是很方便。
本期就先到这里,下期我们来讲一下 vite 打包优化方面的问题和 vue3+ tsx 下的 ui组件库引入的一些问题和解决方案
转载自:https://juejin.cn/post/7082352016759980039