代码规范
注意
这里不做详细配置说明,你可以查看之前文章前端代码工作流、从 0 到 1 搭建一个企业级前端开发规范了解。
EditorConfig
.editorconfig
点击查看详情
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
.vscode/settings.json
{
"editor.tabSize": 4,
"cSpell.words": [
"Mankeung",
"pinia"
]
}
eslint
安装
pnpm add eslint eslint-config-standard eslint-plugin-vue -D
.eslintrc.js
点击查看详情
module.exports = {
root: true,
env: {
browser: true,
node: true,
es6: true,
commonjs: true,
amd: true
},
settings: {
'import/resolver': {
alias: {
map: [
['@', './src']
],
extensions: ['.ts', '.js', '.jsx', '.json', '.vue']
}
}
},
globals: {
// 你的全局变量(设置为 false 表示它不允许被重新赋值)
//
// myGlobal: false
},
parser: 'vue-eslint-parser',
// ts eslint 配置
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
ecmaFeatures: {
jsx: true,
}
},
plugins: ['@typescript-eslint'],
extends: ['plugin:vue/vue3-recommended', 'plugin:@typescript-eslint/recommended'],
rules: {
// ! 解决eslint报使用v-html警告
'vue/no-v-html': 'off',
'vue/html-self-closing': 'off',
'vue/html-indent': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/max-attributes-per-line': 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 禁用 debugger
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 禁用 console
'@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',
'vue/multi-word-component-names': 'off',
'no-use-before-define': 'off',
'prefer-rest-params': 'off',
'@typescript-eslint/no-this-alias': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@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'],
'vue/component-tags-order': [
'error',
{
order: ['style', ['template', 'script']]
},
],
'max-len': 'off',
// 统一豁免规则,原因:直接修改可能对现有功能产生影响
'eqeqeq': 1,
// 'vue/no-v-html': 1,
// 其中代码本身有问题的规则错误有
'no-undef': 0,
'import/no-duplicates': 0,
// 可能引起格式化问题但建议手动修改代码的有
'no-plusplus': 0,
'no-eval': 0,
'no-prototype-builtins': 0,
'no-multi-assign': 0,
'no-unused-vars': 0,
'no-useless-escape': 0,
'camelcase': 0,
'vue/no-unused-components': 0,
'vue/return-in-computed-property': 0,
'no-param-reassign': 0,
'prefer-const': 0,
'prefer-destructuring': 0,
'no-underscore-dangle': 0,
'no-restricted-syntax': 0,
'no-nested-ternary': 0,
'radix': 0,
'vue/no-side-effects-in-computed-properties': 0,
'vue/order-in-components': 0,
'function-paren-newline': 0,
},
};
.eslintignore
点击查看详情
# 根据自己的实际需求进行添加
# npm
node_modules
# folder
dist
public
templates
docs
www
scripts
# file
postcss.config.js
babel.config.js
.eslintrc.js
plopfile.js
.stylelintrc.js
.prettierrc.js
*.json
*.html
*.d.ts
# vscode
.vscode
npm命令配置
"lint:eslint": "eslint --fix \"src/**/*.{vue,ts,js}\"",
stylelint
安装
pnpm add stylelint stylelint-config-html stylelint-config-prettier stylelint-config-standard stylelint-order stylelint-scss postcss-html postcss-scss -D
.stylelintrc.js
点击查看详情
module.exports = {
root: true,
plugins: ['stylelint-order', 'stylelint-scss'],
customSyntax: 'postcss-html',
extends: ['stylelint-config-standard', 'stylelint-config-prettier', 'stylelint-config-html'],
rules: {
indentation: 4,
'media-feature-name-no-unknown': null,
'selector-class-pattern': null,
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['deep', 'global'],
},
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'],
},
],
'at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'tailwind',
'apply',
'variants',
'responsive',
'screen',
'function',
'if',
'each',
'include',
'mixin',
'at-root'
],
},
],
'no-empty-source': null,
'named-grid-areas-no-invalid': null,
'unicode-bom': 'never',
'no-descending-specificity': null,
'font-family-no-missing-generic-family-keyword': null,
'declaration-colon-space-after': 'always-single-line',
'declaration-colon-space-before': 'never',
// 'declaration-block-trailing-semicolon': 'always',
'rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'first-nested'],
},
],
'unit-no-unknown': [true, {
ignoreUnits: ['rpx']
}],
'keyframes-name-pattern': null,
'order/order': [
[
'dollar-variables',
'custom-properties',
'at-rules',
'declarations',
{
type: 'at-rule',
name: 'supports',
},
{
type: 'at-rule',
name: 'media',
},
'rules',
],
{
severity: 'warning'
},
],
'order/properties-order': [
'position',
'top',
'right',
'bottom',
'left',
'z-index',
'display',
'float',
'width',
'height',
'max-width',
'max-height',
'min-width',
'min-height',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'margin-collapse',
'margin-top-collapse',
'margin-right-collapse',
'margin-bottom-collapse',
'margin-left-collapse',
'overflow',
'overflow-x',
'overflow-y',
'clip',
'clear',
'font',
'font-family',
'font-size',
'font-smoothing',
'osx-font-smoothing',
'font-style',
'font-weight',
'hyphens',
'src',
'line-height',
'letter-spacing',
'word-spacing',
'color',
'text-align',
'text-decoration',
'text-indent',
'text-overflow',
'text-rendering',
'text-size-adjust',
'text-shadow',
'text-transform',
'word-break',
'word-wrap',
'white-space',
'vertical-align',
'list-style',
'list-style-type',
'list-style-position',
'list-style-image',
'pointer-events',
'cursor',
'background',
'background-attachment',
'background-color',
'background-image',
'background-position',
'background-repeat',
'background-size',
'border',
'border-collapse',
'border-top',
'border-right',
'border-bottom',
'border-left',
'border-color',
'border-image',
'border-top-color',
'border-right-color',
'border-bottom-color',
'border-left-color',
'border-spacing',
'border-style',
'border-top-style',
'border-right-style',
'border-bottom-style',
'border-left-style',
'border-width',
'border-top-width',
'border-right-width',
'border-bottom-width',
'border-left-width',
'border-radius',
'border-top-right-radius',
'border-bottom-right-radius',
'border-bottom-left-radius',
'border-top-left-radius',
'border-radius-topright',
'border-radius-bottomright',
'border-radius-bottomleft',
'border-radius-topleft',
'content',
'quotes',
'outline',
'outline-offset',
'opacity',
'filter',
'visibility',
'size',
'zoom',
'transform',
'box-align',
'box-flex',
'box-orient',
'box-pack',
'box-shadow',
'box-sizing',
'table-layout',
'animation',
'animation-delay',
'animation-duration',
'animation-iteration-count',
'animation-name',
'animation-play-state',
'animation-timing-function',
'animation-fill-mode',
'transition',
'transition-delay',
'transition-duration',
'transition-property',
'transition-timing-function',
'background-clip',
'backface-visibility',
'resize',
'appearance',
'user-select',
'interpolation-mode',
'direction',
'marks',
'page',
'set-link-source',
'unicode-bidi',
'speak',
],
},
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
}
.stylelintignore
点击查看详情
# npm
node_modules
# folder
dist
public
templates
# file
postcss.config.js
babel.config.js
.eslintrc.js
.prettierrc.js
plopfile.js
.stylelintrc.js
*.json
*.html
normalize.scss
*.d.ts
# vscode
.vscode
npm命令配置
"lint:prettier": "prettier --write \"src/**/*.{js,ts,json,tsx,css,less,scss,vue,html,md}\"",
"lint:style": "stylelint --fix \"src/**/*.{scss,less,vue,css}\" --cache --cache-location node_modules/.cache/stylelint/",
prettier
安装
pnpm add prettier --dev
.prettierrc.js
点击查看详情
module.exports = {
printWidth: 180, //一行的字符数,如果超过会进行换行,默认为80
tabWidth: 4, //一个tab代表几个空格数,默认为80
useTabs: true, //是否使用tab进行缩进,默认为false,表示用空格进行缩减
singleQuote: true, //字符串是否使用单引号,默认为false,使用双引号
semi: false, //行位是否使用分号,默认为true
vueIndentScriptAndStyle: true,
trailingComma: 'none', //是否使用尾逗号,有三个可选值"<none|es5|all>"
bracketSpacing: true, //对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
jsxSingleQuote: true, // jsx语法中使用单引号
htmlWhitespaceSensitivity: 'strict',
endOfLine: 'auto'
}
npm命令配置
"lint:style": "stylelint --fix \"src/**/*.{scss,less,vue,css}\" --cache --cache-location node_modules/.cache/stylelint/",
husky
安装
pnpm add husky @commitlint/cli @commitlint/config-conventional
commitlint.config.js
点击查看详情
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat', // 新特性
'improvement', // 加强现有特性
'fix', // 修补bug
'refactor', // 重构
'docs', // 文档
'test', // 单元测试
'config', // 配置文件
'style', // 格式需改
'perf', // 性能提升
'ci', // ci 主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
'revert', // 版本回退
'chore', // 其他修改
'scope' // commit 影响的范围(选填), 比如: route, component, utils, build
]
],
'type-empty': [2, 'never'], // type不能为空
'type-case': [0, 'always', 'lower-case'], // type不限制大小写
'subject-empty': [2, 'never'], // subject(简短得描述)不能为空
'subject-max-length': [1, 'always', 50], // subject最大长度,超出只会警告,不阻止提交
'body-leading-blank': [1, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 72]
}
}
scripts/prepare.js
点击查看详情
/*
* @Description: 项目初始化
* @Author: Mankeung
* @Date: 2022-09-25 13:48:49
* @LastEditors: Mankeung
* @LastEditTime: 2022-10-02 21:45:17
*/
const { prompt } = require('enquirer')
const chalk = require('chalk')
const { funExec } = require('./utils')
async function init() {
const arr = ['pnpm', 'yarn', 'npm']
let name = null
for (let i = 0; i < arr.length; i++) {
name = await funExec(`${arr[i]} --version`)
if (name) {
name = arr[i]
break
}
}
// 没有包管理工具
if (!name) throw new Error('请安装包管理工具')
const git = await funExec('git init')
// 没有git
if (!git) throw new Error('请你使用git办理管理工具')
// 处理husky
const husky = await funExec('npx husky install')
// 命令失败
if (!husky) throw new Error('npx husky install error')
console.clear()
console.log(chalk.cyan('项目初始化 ...'))
const answer = await prompt([
{
type: 'confirm',
name: 'q1',
message: '是否需要lint',
initial: true
},
{
type: 'confirm',
name: 'q2',
message: '手否需要commitlint',
initial: true
}
]).catch(() => {
throw new Error('出错了')
})
if (!answer) {
throw new Error('出错了')
}
let npm = `${name} run precommit`
if (answer.q1) npm += `&& ${name} run lint`
if (npm) {
const d = await funExec(`npx husky add .husky/pre-commit "${npm}"`)
if (d) console.log(chalk.cyan(d))
}
if (answer.q2) {
const d = await funExec('npx husky add .husky/commit-msg "npx --no-install commitlint --edit "$1""')
if (d) console.log(chalk.cyan(d))
}
console.log(chalk.cyan('项目初始化完成'))
}
init()
npm命令配置
"precommit": "node ./scripts/precommit.js",