vue3 + vite + typescript + eslint + jest 我的项目配置实际

1. 我的项目初化

# 全局装置vite-appnpm i -g vite-app# 创立我的项目yarn create vite-app <project-name># 或者npm init vite-app <project-name># 进入我的项目,装置依赖cd <project-name>yarn # 或 npm i# 运行我的项目yarn dev # 关上浏览器 http://localhost:3000 查看

2. 引入TypeScript

# 退出ts依赖yarn add --dev typescript

在 我的项目根目录下创立typescript的配置文件 tsconfig.json

{  "compilerOptions": {    // 容许从没有设置默认导出的模块中默认导入。这并不影响代码的输入,仅为了类型查看。    "allowSyntheticDefaultImports": true,        // 解析非绝对模块名的基准目录    "baseUrl": ".",    "esModuleInterop": true,    // 从 tslib 导入辅助工具函数(比方 __extends, __rest等)    "importHelpers": true,    // 指定生成哪个模块零碎代码    "module": "esnext",    // 决定如何解决模块。    "moduleResolution": "node",    // 启用所有严格类型查看选项。    // 启用 --strict相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict,     // --strictNullChecks和 --strictFunctionTypes和--strictPropertyInitialization。    "strict": true,    // 生成相应的 .map文件。    "sourceMap": true,    // 疏忽所有的申明文件( *.d.ts)的类型查看。    "skipLibCheck": true,    // 指定ECMAScript指标版本     "target": "esnext",        // 要蕴含的类型申明文件名列表    "types": [    ],    "isolatedModules": true,    // 模块名到基于 baseUrl的门路映射的列表。    "paths": {      "@/*": [        "src/*"      ]    },    // 编译过程中须要引入的库文件的列表。    "lib": [      "ESNext",      "DOM",      "DOM.Iterable",      "ScriptHost"    ]  },  "include": [    "src/**/*.ts",    "src/**/*.tsx",    "src/**/*.vue",    "tests/**/*.ts",    "tests/**/*.tsx"  ],  "exclude": [    "node_modules"  ]}

src 目录下新加 shim.d.ts 文件

/* eslint-disable */import type { DefineComponent } from 'vue'declare module '*.vue' {  const component: DefineComponent<{}, {}, any>  export default component}

main.js 批改成 main.ts

在根目录,关上Index.html

<script type="module" src="/src/main.js"></script>批改为:<script type="module" src="/src/main.ts"></script>

3. 引入eslint

# 装置eslint prettier 依赖# @typescript-eslint/parser @typescr ipt-eslint/eslint-plugin 为eslint对typescript反对yarn add --dev eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue @typescript-eslint/parser @typescr ipt-eslint/eslint-plugin

在根目录下建设eslint配置文件: .eslintrc.js

module.exports = {  parser: 'vue-eslint-parser',  parserOptions: {    parser: '@typescript-eslint/parser',    ecmaVersion: 2020,    sourceType: 'module',    ecmaFeatures: {      jsx: true    }  },  extends: [    'plugin:vue/vue3-recommended',    'plugin:@typescript-eslint/recommended',    'prettier/@typescript-eslint',    'plugin:prettier/recommended'  ],  rules: {    '@typescript-eslint/ban-ts-ignore': 'off',    '@typescript-eslint/explicit-function-return-type': 'off',    '@typescript-eslint/no-explicit-any': 'off',    '@typescript-eslint/no-var-requires': 'off',    '@typescript-eslint/no-empty-function': 'off',    'vue/custom-event-name-casing': 'off',    'no-use-before-define': 'off',    // 'no-use-before-define': [    //   'error',    //   {    //     functions: false,    //     classes: true,    //   },    // ],    '@typescript-eslint/no-use-before-define': 'off',    // '@typescript-eslint/no-use-before-define': [    //   'error',    //   {    //     functions: false,    //     classes: true,    //   },    // ],    '@typescript-eslint/ban-ts-comment': 'off',    '@typescript-eslint/ban-types': 'off',    '@typescript-eslint/no-non-null-assertion': 'off',    '@typescript-eslint/explicit-module-boundary-types': 'off',    '@typescript-eslint/no-unused-vars': [      'error',      {        argsIgnorePattern: '^h$',        varsIgnorePattern: '^h$'      }    ],    'no-unused-vars': [      'error',      {        argsIgnorePattern: '^h$',        varsIgnorePattern: '^h$'      }    ],    'space-before-function-paren': 'off',    quotes: ['error', 'single'],    'comma-dangle': ['error', 'never']  }};

建设prettier.config.js

module.exports = {  printWidth: 100,  tabWidth: 2,  useTabs: false,  semi: false, // 未尾逗号  vueIndentScriptAndStyle: true,  singleQuote: true, // 单引号  quoteProps: 'as-needed',  bracketSpacing: true,  trailingComma: 'none', // 未尾分号  jsxBracketSameLine: false,  jsxSingleQuote: false,  arrowParens: 'always',  insertPragma: false,  requirePragma: false,  proseWrap: 'never',  htmlWhitespaceSensitivity: 'strict',  endOfLine: 'lf'}

4. 引入jest 测试

yarn add --dev @babel/core @babel/preset-env @testing-library/jest-dom @types/jest @vue/test-utils@next babel-jest jest ts-jst vue-jest@next

创立jest.config.js

const path = require('path')module.exports = {  rootDir: path.resolve(__dirname),  clearMocks: true,  coverageDirectory: 'coverage',  coverageProvider: 'v8',  moduleFileExtensions: ['vue', 'js', 'json', 'jsx', 'ts', 'tsx', 'node'],  // 别名设置  moduleNameMapper: {    '@/(.*)$': '<rootDir>/src/components/$1'  },  preset: 'ts-jest',  testEnvironment: 'jsdom',  // 测试文件  testMatch: ['<rootDir>/tests/unit/*.spec.ts?(x)'],    transform: {    '^.+\\.vue$': 'vue-jest',    '^.+\\js$': 'babel-jest',    '^.+\\.(t|j)sx?$': 'ts-jest'  }}

新建测试用例文件 test/unit/HelloWorld.spec.ts

import { mount } from '@vue/test-utils'import HelloWorld from '@/HelloWorld.vue'test('displays message', async () => {  const wrapper = await mount(HelloWorld)  // Assert the rendered text of the component  expect(wrapper.find('p').text()).toBe('0')  await wrapper.find('button').trigger('click')  expect(wrapper.find('p').text()).toBe('1')})

package.json 命令(scripts)中退出 "test": "jest" 。 如下:

"scripts": {    "dev": "vite",    "build": "vite build",    "test": "jest" },

运行 yarn test 查看测试后果

5. 退出vue-router、vuex

 yarn add vue-router@next vuex@next

在根目录下创立 store/index.ts

import { InjectionKey } from 'vue'import { createStore, Store } from 'vuex'export interface State {  count: number}export const key: InjectionKey<Store<State>> = Symbol()export const store = createStore<State>({  state() {    return {      count: 0    }  },  mutations: {    increment(state) {      state.count++    }  }})

main.ts 批改

import { createApp } from 'vue'import { store, key } from './store'import App from './App'import './index.css'const app = createApp(App)app.use(store, key)app.mount('#app')

components/HelloWord.vue 批改

<template>  <h1>{{ msg }}</h1>  <button @click="inCrement"> count is: </button>  <p>{{ count }}</p></template><script>  import { defineComponent, computed } from 'vue'  import { useStore } from 'vuex'  import { key } from '../store'  export default defineComponent({    name: 'HelloWorld',    props: {      msg: {        type: String,        default: ''      }    },    setup() {      const store = useStore(key)      const count = computed(() => store.state.count)      return {        count,        inCrement: () => store.commit('increment')      }    }  })</script>