代码规范

注意

这里不做详细配置说明,你可以查看之前文章前端代码工作流open in new window从 0 到 1 搭建一个企业级前端开发规范open in new window了解。

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",