前端代码风格自动化

 一、改造背景

代码风格和性格一样,每个程序员都有自己的特点 ,但对于大家协同开发的项目,还是需要力求代码风格的一致性,以减少Bug,但是目前现有项目在代码提交之前,没有进行代码规则检查能够确保进入git库的代码都是符合代码规则的。

该形式的开发模式存在以下几个缺点:

1、javascript相关文件规范依赖插件保提示或者格式,不能在提交前自动校验格式

2、styl样式文件缺少编码风格规则约束,社区相关插件比较少

3、在代码提交之前,对暂存区的文件的脚本和样式文件缺少校验与格式操作且对相关提交信息缺少约束,不利于后期排查问题

综上,当前开发对脚本、样式、提交信息的风格缺少自动化校验流程,代码风格不统一,对后期的维护迭代不利

二、改进点

针对以上问题,在项目里引入Husky、Commitlint、Lint-staged及stylelint工程化工具进行代码风格约束,以减少bug,确定提交到仓库的代码符合约定的语法规范并且对不符合规范的代码进行自动fix操作。

该方案具有以下优点:

1、代码提交钩子Husky,在代码被提交到Git仓库之前,我们可以在这里做一些预检查或者格式化,简单说就是使用Git命令会触发的函数。

2、在有了Husky赋能之后,我们有能力在Git的钩子里做一些事情,首先不得不提的是代码的提交规范和规范的校验,优雅的提交,方便团队协作和快速定位问题,首推Commitlint

3、前端文件过滤的工具Lint-staged,对于较大型的项目,文件众多,首先遇到的就是性能问题,虽然如Eslint之类的也有文件过滤配置,但毕竟还是对于匹配文件的全量遍历,如全量的.js文件,基本达不到性能要求,有时还会误格式化其他同学的代码,因此我们引入Lint-staged,一个仅仅过滤出Git代码暂存区文件(被committed的文件)的工具。

4、 StyleLint 是『一个强大的、现代化的 CSS 检测工具』, 与 ESLint 类似, 是通过定义一系列的编码风格规则帮助我们避免在样式表中出现错误。

5、ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误。

三、具体实施

此方案主要基于node项目工程化的前端代码格式化的工具配置使用,主要包含以下组件:

  1. 代码提交钩子Husky;

  2. 代码的提交规范和规范的校验,优雅的提交Commitlint工具;

  3. Git代码暂存区文件过滤工具Lint-staged

  4. stylus-converter工具包,把现有styl后缀的文件转换成less文件

  5. stylelint和eslint进行样式和js语法校验和修复

具体搭建步骤:

  1. 安装npm包husky、commitlint、Lint-staged、stylus-converter、stylelint、eslint(按照如下版本安装);

yarn add husky@7.0.2 @commitlint/config-conventional@13.1.0 @commitlint/cli@13.1.0 lint-staged@11.1.2 stylus-converter@0.8.1 stylelint@13.13.1 stylelint-order stylelint-config-standard@22.0.0 eslint@7.25.0 -D 
  1. 生成husky配置文件(注:husky 7.x.x版本后需要添加配置文件生效),在package.json的scripts添加"addHusky": "npx husky add .husky/pre-commit 'npm test'"执行后生成husky配置文件commit-msg和pre-commit文件; 

commit-ms文件代码如下:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# 参考https://github.com/leoforfree/cz-customizable
# yarn commit
npx  commitlint --edit $1

pre-commit文件代码如下:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# 这里就是唤醒lint-staged
npx lint-staged

# 获取上面脚本的退出码
exitCode="$?"
exit $exitCode
  1. 根目录新增commitlint.config.js配置文件,详细配置如下:

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      ['feat', 'fix', 'docs', 'style', 'refactor', 'upd', 'test', 'chore', 'revert']
    ],
    'subject-full-stop': [0, 'never'],
    'subject-case': [0, 'never']
  }
}

git commit -m提交格式<type>: <subject>(注意冒号后面有空格)

常用的type类别如下:

upd:更新某功能(不是 feat, 不是 fix)
feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
test:增加测试
chore:构建过程或辅助工具的变动

subject作用:

subject是 commit 目的的简短描述,可以做一些配置,如最大长度限制。

例子如下:

git commit -m 'feat: 增加 xxx 功能'
git commit -m 'bug: 修复 xxx 功能'

  1. 根目录新增lint-staged.config.js文件过滤配置文件(一个仅仅过滤git代码暂存区文件,被git add的文件),Lint-staged不会帮你格式化任何东西,所以没有代码规则配置文件,需要自己配置一下,如:.eslintrc、.stylelintrc等。当文件变化,我们git commit它们,pre-commit钩子会启动,执行lint-staged命令,我们对于lint-staged如下文配置,对本次被commited中的所有.js、.jsx文件执行eslint --fix命令和所有.less、.scss文件执行stylelint --fix命令进行格式化;

// lint-staged.config.js配置文件
module.exports = {
  'src/**/*.{js,jsx}': [
    'eslint --fix'
  ],
  'src/**/*.{less,scss}': [
    'stylelint --fix'
  ]
}

  1. 利用安装好的stylus-converter工具包把.styl文件转换成less文件

命令行脚本示例如下:

stylus-conver -i '复制styl文件相对路径' -o test.less"

  1. 根目录新增stylelint.config.js和.stylelintignore样式规范配置文件和忽略配置文件,详细请参考官方配置

module.exports = {
  plugins: ['stylelint-order'],
  extends: 'stylelint-config-standard', // 这是官方推荐的方式
  rules: {
    'at-rule-no-unknown': [true, {
      ignoreAtRules: ['extend', 'at-root', 'debug', 'warn', 'error', 'if', 'else', 'for', 'each', 'while', 'mixin', 'include', 'content', 'return', 'function']
    }],
    // 'rule-empty-line-before': 'never', // 禁止在 at 规则之前有空行
    'no-descending-specificity': null, // 禁止特异性较低的选择器在特异性较高的选择器之后重写
    'order/order': [
      'custom-properties',
      'declarations'
    ],
    'order/properties-order': [
      'position',
      'top',
      'right',
      'bottom',
      'left',
      'z-index',
      'display',
      'float',
      'width',
      'height'
    ]
  }
}
# Created by .ignore support plugin (hsz.mobi)
**/*.js
node_modules/


  1. 根目录新增.eslintrc.js配置文件

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true
  },

  extends: [
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'eslint:recommended'
  ],

  parser: 'babel-eslint',

  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 12,
    sourceType: 'module'
  },
  plugins: [
    'react'
  ],
  rules: {
    'react/prop-types': 1,
    'react/no-string-refs': 1,
    'react/display-name': 1,
    'react/no-unescaped-entities': 1,
    'no-unused-vars': 1,
    'no-empty': 1,
    'no-useless-escape': 1,
    'no-cond-assign': 1,
    'no-extra-boolean-cast': 1,
    'no-case-declarations': 1,
    'handle-callback-err': 1,
    'new-cap': 1,
    'accessor-pairs': 2,
    'arrow-spacing': [2, {
      'before': true,
      'after': true
    }],
    'block-spacing': [2, 'always'],
    'brace-style': [2, '1tbs', {
      'allowSingleLine': true
    }],
    'camelcase': [0, {
      'properties': 'always'
    }],
    'comma-dangle': [2, 'never'],
    'comma-spacing': [2, {
      'before': false,
      'after': true
    }],
    'comma-style': [2, 'last'],
    'constructor-super': 2,
    'curly': [2, 'multi-line'],
    'dot-location': [2, 'property'],
    'eol-last': 2,
    'eqeqeq': ['error', 'always', { 'null': 'ignore' }],
    'generator-star-spacing': [2, {
      'before': true,
      'after': true
    }],
    'indent': [2, 2, {
      'SwitchCase': 1
    }],
    'jsx-quotes': [2, 'prefer-single'],
    'key-spacing': [2, {
      'beforeColon': false,
      'afterColon': true
    }],
    'keyword-spacing': [2, {
      'before': true,
      'after': true
    }],
    'new-parens': 2,
    'no-array-constructor': 2,
    'no-caller': 2,
    'no-console': 'off',
    'no-class-assign': 2,
    'no-const-assign': 2,
    'no-control-regex': 0,
    'no-delete-var': 2,
    'no-dupe-args': 2,
    'no-dupe-class-members': 2,
    'no-dupe-keys': 2,
    'no-duplicate-case': 2,
    'no-empty-character-class': 2,
    'no-empty-pattern': 2,
    'no-eval': 2,
    'no-ex-assign': 2,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    'no-extra-parens': [2, 'functions'],
    'no-fallthrough': 2,
    'no-floating-decimal': 2,
    'no-func-assign': 2,
    'no-implied-eval': 2,
    'no-inner-declarations': [2, 'functions'],
    'no-invalid-regexp': 2,
    'no-irregular-whitespace': 2,
    'no-iterator': 2,
    'no-label-var': 2,
    'no-labels': [2, {
      'allowLoop': false,
      'allowSwitch': false
    }],
    'no-lone-blocks': 2,
    'no-mixed-spaces-and-tabs': 2,
    'no-multi-spaces': 2,
    'no-multi-str': 2,
    'no-multiple-empty-lines': [2, {
      'max': 1
    }],
    'no-native-reassign': 2,
    'no-negated-in-lhs': 2,
    'no-new-object': 2,
    'no-new-require': 2,
    'no-new-symbol': 2,
    'no-new-wrappers': 2,
    'no-obj-calls': 2,
    'no-octal': 2,
    'no-octal-escape': 2,
    'no-path-concat': 2,
    'no-proto': 2,
    'no-redeclare': 2,
    'no-regex-spaces': 2,
    'no-return-assign': [2, 'except-parens'],
    'no-self-assign': 2,
    'no-self-compare': 2,
    'no-sequences': 2,
    'no-shadow-restricted-names': 2,
    'no-spaced-func': 2,
    'no-sparse-arrays': 2,
    'no-this-before-super': 2,
    'no-throw-literal': 2,
    'no-trailing-spaces': 2,
    'no-undef': 2,
    'no-undef-init': 2,
    'no-unexpected-multiline': 2,
    'no-unmodified-loop-condition': 2,
    'no-unneeded-ternary': [2, {
      'defaultAssignment': false
    }],
    'no-unreachable': 2,
    'no-unsafe-finally': 2,
    'no-useless-call': 2,
    'no-useless-computed-key': 2,
    'no-useless-constructor': 2,
    'no-whitespace-before-property': 2,
    'no-with': 2,
    'one-var': [2, {
      'initialized': 'never'
    }],
    'operator-linebreak': [2, 'after', {
      'overrides': {
        '?': 'before',
        ':': 'before'
      }
    }],
    'padded-blocks': [2, 'never'],
    'quotes': [2, 'single', {
      'avoidEscape': true,
      'allowTemplateLiterals': true
    }],
    'semi': [2, 'never'],
    'semi-spacing': [2, {
      'before': false,
      'after': true
    }],
    'space-before-blocks': [2, 'always'],
    'space-before-function-paren': [2, 'never'],
    'space-in-parens': [2, 'never'],
    'space-infix-ops': 2,
    'space-unary-ops': [2, {
      'words': true,
      'nonwords': false
    }],
    'spaced-comment': [2, 'always', {
      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
    }],
    'template-curly-spacing': [2, 'never'],
    'use-isnan': 2,
    'valid-typeof': 2,
    'wrap-iife': [2, 'any'],
    'yield-star-spacing': [2, 'both'],
    'yoda': [2, 'never'],
    'prefer-const': 2,
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
    'object-curly-spacing': [2, 'always', {
      objectsInObjects: false
    }],
    'array-bracket-spacing': [2, 'never']
  }
}

  1. postcss.config.js配置第一行新增require('stylelint')({})

module.exports = {
  plugins: [
    // 放在最前面防止插件干扰规则
    require('stylelint')({}),
    require('autoprefixer')
  ]
}

  1. 新增package.json的scripts脚本;

// ...
  "scripts": {
    "addHusky": "npx husky add .husky/pre-commit 'npm test'",
    "stylelint": "stylelint 'src/**/*.less'",
    "stylelintFix": "stylelint 'src/**/*.less' --fix",
    "eslint": "eslint --ext .js,.jsx src/",
    "eslintFix": "eslint 'src/**/*.js' --fix",
    "stylusConverFile": "stylus-conver -i '复制styl相对路径' -o test.less"
  },
// ...

四、有益效果

与之前开发系统相比,基于代码风格自动化的建设方案存在以下优点:

  1. Husky在代码被提交到Git仓库之前,我们可以在这里做一些预检查或者格式化

  2. Commitlint代码的提交规范和规范的校验,例如feat:新功能(feature)、fix:修补bug、style: 样式修改,方便问题跟踪

  3. Lint-staged过滤出Git代码暂存区文件(被committed的文件)的工具,避免全量遍历和格式其他人代码

  4. 结合上面工具利用Stylelint和ESlint检查和帮我们自动修复css和js错误代码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于前端开发,vscode有很多优秀的代码提示插件可供选择。其中一些主要的插件包括: 1. HTML CSS Support:该插件提供了对HTML和CSS的语法高亮和智能提示,使你在编写前端代码时更加高效准确。 2. Auto Close Tag:这个插件可以自动关闭HTML标签,避免标签不匹配的错误。 3. Auto Rename Tag:当你修改一个HTML标签的名称时,该插件会自动重命名与之对应的结束标签,避免手动修改的麻烦。 4. IntelliSense for CSS class names in HTML:这个插件可以根据你的CSS文件中定义的类名,为HTML标签提供智能提示,方便你快速选择正确的类名。 5. ESLint:这是一个JavaScript代码检查工具,它可以帮助你在编写代码时遵循一些最佳实践和代码风格规范,并给出相应的错误和警告。 6. Prettier - Code formatter:这个插件可以自动格式化你的代码,使其符合统一的代码风格,这在协作开发中非常有用。 7. Vue 2 Snippets:针对Vue.js框架,提供了一些常用代码片段,让你更快地编写Vue组件。 8. Vetur:这是一个专门为Vue.js开发而设计的插件,提供了对Vue文件的语法高亮、智能提示、格式化、错误提示等功能。 以上是一些常用的vscode前端代码提示插件,你可以根据自己的需求选择安装使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vscode推荐插件的安装](https://download.csdn.net/download/joyce198800/10270764)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vscode css智能补全_高效率工具:web前端开发VScode必备插件大全](https://blog.csdn.net/weixin_39879522/article/details/110335132)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值