vite vue3 TypeScript 项目工程化配置

1.ESLint

安装 ESLint

ESLint 文档

1
yarn add  eslint -D

初始化 ESLint

1
npx eslint --init

以下选择仅供参考

1
√ How would you like to use ESLint? · style
2
√ What type of modules does your project use? · none
3
√ Which framework does your project use? · vue
4
√ Does your project use TypeScript? · No / Yes
5
√ Where does your code run? · browser, node
6
√ How would you like to define a style for your project? · guide
7
√ Which style guide do you want to follow? · standard
8
√ What format do you want your config file to be in? · JavaScript
9
Checking peerDependencies of eslint-config-standard@latest
10
The config that you've selected requires the following dependencies:
11
12
eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest eslint-config-standard@latest eslint@^7.12.1 eslint-plugin-import@^2.22.1 eslint-plugin-node@^11.1.0 eslint-plugin-promise@^4.2.1 || ^5.0.0 @typescript-eslint/parser@latest
13
√ Would you like to install them now with npm? · No / Yes

配置 .eslintrc.js

eslint-plugin-vue 配置文档

实战项目配置

需安装

1
yarn add  eslint-define-config vue-eslint-parser -D

eslint-define-config 用来提供配置提示

.eslintrc.js

1
/* eslint-disable @typescript-eslint/no-var-requires */
2
// @ts-check
3
const { defineConfig } = require('eslint-define-config')
4
module.exports = defineConfig({
5
  parser: 'vue-eslint-parser',
6
  env: {
7
    browser: true,
8
    es2021: true,
9
    node: true
10
  },
11
  extends: [
12
    'eslint:recommended',
13
    'plugin:vue/vue3-recommended',
14
    'plugin:@typescript-eslint/recommended'
15
  ],
16
  parserOptions: {
17
    ecmaVersion: 12,
18
    parser: '@typescript-eslint/parser'
19
  },
20
  plugins: ['vue', '@typescript-eslint', 'import'],
21
  rules: {
22
    // vue base
23
    'vue/no-unused-vars': [
24
      'error',
25
      {
26
        ignorePattern: '^_'
27
      }
28
    ],
29
    'vue/singleline-html-element-content-newline': 'off',
30
    'vue/multiline-html-element-content-newline': 'off',
31
    'vue/name-property-casing': ['error', 'PascalCase'],
32
    'vue/no-v-html': 'off',
33
    'vue/html-closing-bracket-newline': 'off',
34
    'vue/html-indent': 0,
35
    'vue/html-self-closing': 'off',
36
    'vue/max-attributes-per-line': 0,
37
    'vue/custom-event-name-casing': 0,
38
    'vue/eqeqeq': [2, 'always', { null: 'ignore' }],
39
    // common
40
    'no-unused-vars': ['error', { args: 'none' }],
41
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
42
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
43
    semi: [2, 'never'],
44
    'semi-spacing': [
45
      2,
46
      {
47
        before: false,
48
        after: true
49
      }
50
    ],
51
    quotes: [
52
      2,
53
      'single',
54
      {
55
        avoidEscape: true,
56
        allowTemplateLiterals: true
57
      }
58
    ],
59
    'comma-dangle': [2, 'never'],
60
    'comma-spacing': [
61
      2,
62
      {
63
        before: false,
64
        after: true
65
      }
66
    ],
67
    'comma-style': [2, 'last'],
68
    'arrow-parens': [2, 'as-needed'],
69
    'arrow-spacing': [
70
      2,
71
      {
72
        before: true,
73
        after: true
74
      }
75
    ],
76
    'jsx-quotes': 2,
77
    'no-async-promise-executor': 0,
78
    'space-before-function-paren': 0,
79
    'no-empty': 0,
80
    'spaced-comment': ['error', 'always'],
81
    'no-undef': 0,
82
    // import
83
    'import/order': 2,
84
    'import/first': 2,
85
    // typescript
86
    '@typescript-eslint/no-explicit-any': 0
87
  }
88
})

package.json scripts 中添加

1
{
2
  "scripts": {
3
    "lint": "eslint ./src --ext .js,.jsx,.ts,.tsx --fix"
4
  }
5
}

添加.eslintignore 文件

1
build
2
src/assets
3
public
4
dist
5
tests/
6
types

2.prettier

prettier 文档

1
yarn add prettier -D

添加.prettierrc.js

1
module.exports = {
2
  trailingComma: 'none',
3
  tabWidth: 2,
4
  semi: false,
5
  printWidth: 100,
6
  singleQuote: true,
7
  jsxSingleQuote: true,
8
  bracketSpacing: true,
9
  arrowParens: 'avoid'
10
}

添加.prettierignore

1
node_modules
2
dist
3
build
4
static
5
public

package.json scripts 中添加

1
{
2
  "scripts": {
3
    "prettier": "prettier . --write"
4
  }
5
}

3.stylelint

stylelint 文档

1
yarn add stylelint stylelint-config-standard stylelint-order
2
stylelint-scss -D

添加.stylelintrc.js

1
module.exports = {
2
  defaultSeverity: 'error',
3
  ignoreFiles: [
4
    'node_modules/**',
5
    'dist/**',
6
    '*.min.css',
7
    'tests/**',
8
    'coverage/**'
9
  ],
10
  extends: ['stylelint-config-standard'],
11
  plugins: ['stylelint-scss', 'stylelint-order'],
12
  rules: {
13
    'order/order': [
14
      'declarations',
15
      'custom-properties',
16
      'dollar-variables',
17
      'rules',
18
      'at-rules'
19
    ],
20
    'order/properties-order': [
21
      'position',
22
      'top',
23
      'right',
24
      'bottom',
25
      'left',
26
      'float'
27
    ],
28
    'media-feature-name-no-vendor-prefix': true,
29
    'selector-no-vendor-prefix': null,
30
    'property-no-vendor-prefix': null,
31
    'rule-empty-line-before': null,
32
    'no-missing-end-of-source-newline': null,
33
    'selector-pseudo-class-no-unknown': null,
34
    'font-family-no-missing-generic-family-keyword': null,
35
    'no-descending-specificity': null,
36
    'declaration-empty-line-before': null,
37
    'declaration-block-trailing-semicolon': null,
38
    'selector-combinator-space-before': null,
39
    'selector-combinator-space-after': null,
40
    'block-closing-brace-newline-before': null,
41
    'at-rule-no-unknown': null,
42
    'property-case': null,
43
    'property-no-unknown': null,
44
    'declaration-block-single-line-max-declarations': null,
45
    'value-no-vendor-prefix': null,
46
    'no-empty-source': null,
47
    'at-rule-no-vendor-prefix': null,
48
    'selector-pseudo-element-no-unknown': [
49
      true,
50
      {
51
        ignorePseudoElements: ['v-deep']
52
      }
53
    ],
54
    'function-calc-no-unspaced-operator': null
55
  }
56
}

package.json scripts 中添加

1
{
2
  "scripts": {
3
    "stylelint": "stylelint  ./src/**/*.{scss,css,less,vue} --fix"
4
  }
5
}

4.git hooks 的添加

husky 文档

commitlint 文档

commitizen/cz-cli 文档

cz-customizable 文档

cz-conventional-changelog 文档

lint-staged 文档

安装依赖

1
yarn add husky @commitlint/cli @commitlint/config-conventional commitizen cz-conventional-changelog cz-customizable  lint-staged  -D

执行

1
npx  husky install

添加提交信息校验 git hooks

1
npx husky add .husky/commit-msg  'npx  commitlint  --edit $1'

添加提交前校验 git hooks

1
npx husky add .husky/pre-commit  'npx  lint-staged'

添加文件 commitlint.config.js

1
module.exports = {
2
  extends: ['@commitlint/config-conventional'],
3
  rules: {
4
    // 提交主题类型
5
    'type-enum': [
6
      2,
7
      'always',
8
      [
9
        'feat',
10
        'fix',
11
        'delete',
12
        'docs',
13
        'test',
14
        'style',
15
        'ci',
16
        'refactor',
17
        'perf',
18
        'chore',
19
        'revert'
20
      ]
21
    ],
22
    'subject-full-stop': [0, 'never'], // 主题句号
23
    'subject-case': [0, 'never'] // 主题案例
24
  }
25
}

添加文件 .cz-config.js 按项目配置

1
module.exports = {
2
  // 修改主题选择
3
  types: [
4
    { value: 'feat', name: 'feat:添加新功能' },
5
    { value: 'fix', name: 'fix:Bug修复' },
6
    { value: 'delete', name: 'delete:删除代码,接口' },
7
    {
8
      value: 'docs',
9
      name: 'docs:  变更的只有文档,比如README.md等'
10
    },
11
    { value: 'test', name: 'test:添加一个测试,包括单元测试、集成测试等' },
12
    {
13
      value: 'style',
14
      name: 'style:  空格, 分号等格式修复(注意不是 css 修改)'
15
    },
16
    { value: 'ci', name: 'ci:ci配置,脚本文件等更新' },
17
    {
18
      value: 'refactor',
19
      name: 'refactor:代码重构(即不是新增功能,也不是修改bug的代码变动)'
20
    },
21
    { value: 'perf', name: 'perf:优化相关,比如提升性能、体验' },
22
    { value: 'chore', name: 'chore:改变构建流程、或者增加依赖库、工具等' },
23
    { value: 'revert', name: 'revert:代码回退' }
24
  ],
25
  // 构建对话
26
  messages: {
27
    type: '选择一种你的提交类型(必选):',
28
    scope: '选择一个更改范围(可选):',
29
    // used if allowCustomScopes is true
30
    customScope: '自定义更改范围(可选):',
31
    subject: '提交说明(必填):\n',
32
    body: '长说明,使用"|"换行(可选):\n',
33
    breaking: '非兼容性说明 (可选):\n',
34
    footer: '关联关闭的issue,例如:#31, #34(可选):\n',
35
    confirmCommit: '确定提交说明?'
36
  },
37
  // 是否允许自定义更改范围
38
  allowCustomScopes: true,
39
  // 允许中断的改变
40
  allowBreakingChanges: ['feat', 'fix'],
41
  // 修改主题描述字数限制
42
  subjectLimit: 100,
43
  // 选择跳过的步骤
44
  skipQuestions: ['scope', 'customScope', 'body', 'breaking', 'footer']
45
}

package.json scripts 中添加

1
{
2
  "scripts": {
3
    "prepare": "husky install",
4
    "commit": "git-cz"
5
  }
6
}

package.json 中添加

1
{
2
  "config": {
3
    "commitizen": {
4
      "path": "node_modules/cz-customizable"
5
    }
6
  },
7
  "husky": {
8
    "hooks": {
9
      "pre-commit": "lint-staged",
10
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
11
    }
12
  },
13
  "lint-staged": {
14
    "src/**/*.{js,jsx,ts,tsx,vue}": ["npm run lint"],
15
    "src/**/*.{html,vue,css,sass,scss}": ["npm run stylelint"]
16
  }
17
}

添加文件 update.sh

1
#!/usr/bin/env bash
2
success="更新成功"
3
set -e
4
git add .
5
npm  run commit
6
git  pull
7
git  push
8
echo  -e "\n\033[32m$success\033[0m"

项目代码提交 使用

1
./update.sh

package.json 完整配置

1
{
2
  "name": "vite-vue3-element-plus-admin",
3
  "version": "1.0.0",
4
  "license": "ISC",
5
  "author": "xiaofei",
6
  "main": "src/main.ts",
7
  "scripts": {
8
    "dev": "vite --host",
9
    "tsc": "vue-tsc --noEmit",
10
    "build:prod": "vite build  --mode production",
11
    "report": "cross-env REPORT=true yarn build:prod",
12
    "dev:staging": "vite --host  --mode staging",
13
    "build:staging": "vite build  --mode staging",
14
    "serve": "vite preview",
15
    "prepare": "husky install",
16
    "commit": "git-cz",
17
    "lint": "eslint ./src --ext .js,.jsx,.ts,.tsx,.vue --fix",
18
    "stylelint": "stylelint  ./src/**/*.{scss,css,less,vue} --fix",
19
    "prettier": "prettier . --write",
20
    "test:unit": "jest  --coverage"
21
  },
22
  "dependencies": {
23
    "accounting": "^0.4.1",
24
    "auto-drawing": "^0.0.31",
25
    "axios": "^0.21.1",
26
    "crypto-js": "^4.1.1",
27
    "dayjs": "^1.10.4",
28
    "echarts": "^5.1.1",
29
    "element-plus": "^1.1.0-beta.7",
30
    "file-saver": "^2.0.5",
31
    "good-storage": "^1.1.1",
32
    "js-cookie": "^2.2.1",
33
    "js-md5": "^0.7.3",
34
    "jsencrypt": "^3.2.0",
35
    "lodash-es": "^4.17.21",
36
    "normalize.css": "^8.0.1",
37
    "nprogress": "^0.2.0",
38
    "numeral": "^2.0.6",
39
    "qs": "^6.10.1",
40
    "uuid": "^8.3.2",
41
    "vue": "^3.2.2",
42
    "vue-cropperjs": "^5.0.0",
43
    "vue-i18n": "^9.1.2",
44
    "vue-router": "^4.0.11",
45
    "vuex": "^4.0.2"
46
  },
47
  "devDependencies": {
48
    "@babel/plugin-syntax-jsx": "^7.14.5",
49
    "@babel/preset-env": "^7.14.1",
50
    "@babel/preset-react": "^7.14.5",
51
    "@commitlint/cli": "^13.1.0",
52
    "@commitlint/config-conventional": "^13.1.0",
53
    "@rollup/plugin-eslint": "^8.0.1",
54
    "@testing-library/jest-dom": "^5.12.0",
55
    "@types/accounting": "^0.4.1",
56
    "@types/crypto-js": "^4.0.2",
57
    "@types/file-saver": "^2.0.1",
58
    "@types/good-storage": "^1.1.0",
59
    "@types/jest": "^26.0.23",
60
    "@types/js-cookie": "^2.2.6",
61
    "@types/js-md5": "^0.4.2",
62
    "@types/lodash-es": "^4.17.4",
63
    "@types/node": "^14.14.37",
64
    "@types/nprogress": "^0.2.0",
65
    "@types/numeral": "^2.0.1",
66
    "@types/qs": "^6.9.6",
67
    "@types/uuid": "^8.3.1",
68
    "@types/vue-cropperjs": "^4.1.1",
69
    "@typescript-eslint/eslint-plugin": "^4.21.0",
70
    "@typescript-eslint/parser": "^4.21.0",
71
    "@vitejs/plugin-legacy": "^1.3.2",
72
    "@vitejs/plugin-vue": "^1.2.1",
73
    "@vitejs/plugin-vue-jsx": "^1.1.4",
74
    "@vue/compiler-sfc": "3.0.11",
75
    "@vue/eslint-config-typescript": "7.0.0",
76
    "@vue/test-utils": "^2.0.0-rc.6",
77
    "autoprefixer": "^8.6.5",
78
    "babel-plugin-transform-import-meta": "^2.0.0",
79
    "babel-preset-vite": "^1.0.4",
80
    "chalk": "^4.1.0",
81
    "commitizen": "^4.2.4",
82
    "cross-env": "^7.0.3",
83
    "cz-conventional-changelog": "^3.3.0",
84
    "cz-customizable": "^6.3.0",
85
    "eslint": "^7.0.0",
86
    "eslint-config-standard": "^16.0.2",
87
    "eslint-define-config": "^1.0.9",
88
    "eslint-plugin-import": "^2.22.1",
89
    "eslint-plugin-jest": "^24.3.6",
90
    "eslint-plugin-node": "^11.1.0",
91
    "eslint-plugin-promise": "^4.3.1",
92
    "eslint-plugin-vue": "^7.8.0",
93
    "husky": "^7.0.2",
94
    "jest": "^26.6.3",
95
    "jest-transform-stub": "^2.0.0",
96
    "lint-staged": "^11.1.2",
97
    "mockjs": "^1.1.0",
98
    "postcss": "^7.0.35",
99
    "postcss-import": "^14.0.1",
100
    "postcss-px-to-viewport": "^1.1.1",
101
    "prettier": "^2.3.0",
102
    "rollup-plugin-visualizer": "^5.5.2",
103
    "sass": "^1.37.5",
104
    "stylelint": "^13.12.0",
105
    "stylelint-config-standard": "^21.0.0",
106
    "stylelint-order": "^4.1.0",
107
    "stylelint-scss": "^3.19.0",
108
    "ts-jest": "^26.5.6",
109
    "typescript": "^4.3.5",
110
    "vite": "^2.5.0",
111
    "vite-plugin-compression": "^0.2.4",
112
    "vite-plugin-element-plus": "^0.0.12",
113
    "vite-plugin-html": "^2.0.6",
114
    "vite-plugin-imagemin": "^0.4.3",
115
    "vite-plugin-mock": "^2.5.0",
116
    "vite-plugin-svg-icons": "^0.4.1",
117
    "vue-eslint-parser": "^7.6.0",
118
    "vue-jest": "^5.0.0-alpha.7",
119
    "vue-tsc": "^0.0.15",
120
    "xml2js": "^0.4.23"
121
  },
122
  "config": {
123
    "commitizen": {
124
      "path": "node_modules/cz-customizable"
125
    }
126
  },
127
  "husky": {
128
    "hooks": {
129
      "pre-commit": "lint-staged",
130
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
131
    }
132
  },
133
  "lint-staged": {
134
    "src/**/*.{js,jsx,ts,tsx,vue}": ["npm run lint"],
135
    "src/**/*.{html,vue,css,sass,scss}": ["npm run stylelint"]
136
  },
137
  "resolutions": {
138
    "bin-wrapper": "npm:bin-wrapper-china"
139
  }
140
}