Webpack代码规范配置

302 阅读10分钟
Eslint

Eslint是用来规范JavaScript规范的,它更侧重于对于语法方面的规范,这对于一个团队的开发来说是非常重要的。

举个例子,开发A使用双等号 == ,而开发B使用三等号 ===,这会造成合并代码后的错误排查产生困难,所以应该统一成 === ,这就是Eslint的主要作用

Eslint要配置在开发环境还是生产环境中呢?其实看团队的规范了,这里只配置在开发环境中,因为只有开发环境中才会去规范语法。

首先安装以下包:

  • eslint : Eslint的依赖包
  • eslint-config-airbnb-base : Eslint的现成方案
  • eslint-plugin-import :支持Eslint拓展配置
  • eslint-webpack-plugin : 将Eslint配置在webpack中的插件
npm i eslint eslint-config-airbnb-base eslint-plugin-import eslint-webpack-plugin -D

安装之后,我们需要在根目录下创建两个文件 .eslintrc.js、.eslintignore

  • .eslintrc.js : Eslint的配置就写在这
// .eslintrc.js

module.exports = {
    // 不往父级查找
    root: true,
    // 环境配置
    env: {
      node: true,
      browser: true,
      es6: true,
    },
    // 拓展规则
    extends: 'airbnb-base',
    // 自定义规则,会覆盖一部分拓展规则
    // 具体这些参数代表什么规则,可以去eslint官网看
    rules: {
      'no-console': 'warn',
      semi: 'off',
      'eol-last': 'off',
      'no-new': 'off',
      'arrow-parens': 'off',
      'import/no-extraneous-dependencies': 'off',
      'comma-danger': 'off',
      'no-useless-escape': 'off'
    },
    // 语言风格
    parserOptions: {
      // 支持import
      sourceType: 'module'
    }
  }
  • .eslintignore : 忽略哪些文件的Eslint检测,写在这
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin

我们现在只是完成了Eslint的自身配置,但是我们的目的是要开发构建时能在终端提示语法错误,所以需要将Eslint配置在webpack.dev.js中

// 开发环境
const ESlintPlugin = require('eslint-webpack-plugin')
module.exports = merge(base, {
//刚才的代码
    plugins: [
        //刚才的代码
        new ESlintPlugin({
            //运行的时候自动帮你修复错误
            fix: true
        })
    ]
})

这样的话就能在 npm run serve 中提示出你的语法错误了,比如我现在随便搞个错误代码

const nn = 2
nn = 1

此时就会报错

1673012793083.png

vscode插件

但是有一个问题,终端是报错了,可是怎么才能开发时,编辑器直接报错呢?就像这样

image.png

其实很简单,我们只需要安装一个vscode插件 Eslint就行了,这个插件安装完成后,它会自动读取我们刚刚的Eslint配置,然后进行错误提醒:

image.png

配置命令

我们也可以在package.json中自己配置命令来进行代码的Eslint检测

"scripts":{
    "eslint":"eslint ./src"
}

然后在终端 npm run eslint 就可以手动进行Eslint检测

Prettier

Prettier 也是规范JavaScript的一个东西,它跟Eslint的差别在于:

  • Eslint : 更侧重于规范JS语法
  • Prettier : 更侧重于规范JS的编写规范

比如,代码不加分号,这就归Prettier管,而Prettier是归Eslint管的,所以说Prettier的配置需要配置在.eslintrc中

配置

那么配置Prettier之前我们需要安装这些插件

  • prettier : Prettier规范的依赖
  • eslint-plugin-prettier : 能让Eslint配置Prettier插件
npm i prettier eslint-plugin-prettier -D

然后我们到.eslintrc中去配置

// .eslintrc.js

  


module.exports = {

     //拓展插件

     plugins:['prettier'],

    // 自定义规则,会覆盖一部分拓展规则

    // 具体这些参数代表什么规则,可以去eslint官网看

    rules: {

      'prettier/prettier': 'error'

    }

  }

vscode插件

然后如果想开发中提示的话,可以给vscode安装个Prettier这个插件

1673015163865.png

Stylelint

Stylelint 就是规定样式的规范的,包括规则、顺序、样式用法等等

配置

我们需要安装下面的插件

  • stylelint : Stylelint的依赖
  • stylelint-config-prettier : 拓展Stylelint的规则
  • stylelint-config-standard : 拓展Stylelint的规则
  • stylelint-order : 拓展Stylelint样式顺序的插件
  • stylelint-webpack-plugin : 将Stylelint配置到webpack的插件

然后我们在根目录下创建一个stylelint.config.js文件,用来配置Stylelint

// stylelint.config.js

module.exports = {
    root: true,
    // 拓展插件
    plugins: ['stylelint-order'],
    // 拓展stylelint的规则
    extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
    // 自定义规则
    rules: {
      'selector-pseudo-class-no-unknown': [
        true,
        {
          ignorePseudoClasses: ['global'],
        },
      ],
      'selector-pseudo-element-no-unknown': [
        true,
        {
          ignorePseudoElements: ['v-deep'],
        },
      ],
      'at-rule-no-unknown': [
        true,
        {
          ignoreAtRules: [
            'tailwind',
            'apply',
            'variants',
            'responsive',
            'screen',
            'function',
            'if',
            'each',
            'include',
            'mixin',
          ],
        },
      ],
      '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'],
        },
      ],
      // 自定义顺序
      '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',
        'content',
        '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',
        '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'],
  }

之后我们需要把Stylelint配置到webpack.dev.js中

// 开发环境

const path = require('path')
const StylelintWebpackPlugiin = require('stylelint-webpack-plugin')

module.exports = merge(base, {
//之前的代码
    plugins: [
    //之前的代码
        new StylelintWebpackPlugiin({
            context:'src',
            //Stylelint的配置文件读取
            configFile:path.resolve(__dirname,'../stylelint.config.js'),
            //检查文件范围
            files:['**/*.scss'],
        })
    ],
})

现在css文件出现错误,或者顺序错误,都会报错了 image.png

vscode插件

跟之前两个插件一样,Stylelint也可以安装一下vscode的插件Stylelint

image.png

配置命令

我们也可以再package.json中自己配置命令来进行代码的Stylelint检测,加上 --fix,可以自动帮你修复一些样式错误

 "scripts": {
    "lint:style":"stylelint src/**/*.scss --fix"
  },

现在运行npm run lint:style 就可以检测样式错误,并自动修复部分错误了

husky

husky就是用来规范你的git提交的规则的,常用的是对于提交代码commit前的Eslint、stylelint检测,确保提交的代码是无错误的。husky是利用了git的hook

配置

配置husky需要安装下面这些包

  • husky : husky所需的依赖
  • lint-staged : 用来检测提交缓存区的代码的规范,如果不符合规范就阻止git commit
  • @commitlint/cli : 规定git commit文本规范的依赖
  • @commitlint/config-conventional : 规定git commit文本规范的拓展规则
npm i husky lint-staged @commitlint/cli @commitlint/config-conventional -D

然后我们需要在package.json中配置命令

  "scripts": {
    "prepare":"husky install"
  },

这个命令的作用就是:当你项目初始npm i 之后,他会自动运行这个husky install 的命令,然后你的项目中就会出现.husky文件夹

image.png

我们在.husky文件夹新建以下两个文件

  • pre-commit : commit前所要做的事
  • commit-mst : commit文本检验的触发文件

image.png

pre-commit

这个文件是用来执行代码git commit前所做的事,那commit之前我们应该做什么事呢?我们需要对提交缓存区里的代码进行Eslint、Stylelint的检验,如果检验到代码有语法错误,则阻止git commit

所以我们需要用到lint-staged,先在package.json中配置命令

"scripts": {  
    "lint-staged": "lint-staged"  
  },

然后在根目录下创建文件 .lintstagedrc,这个文件配置的是你执行 npm run lint-staged 时会做哪些事情


// .lintstagedrc  
  
{  
  "*.js": "eslint --fix",  
  "*.scss": "stylelint --fix"  
}

然后我们只需要在pre-commit中执行这个 npm run lint-staged 就行了


// .husky/pre-commit  
  
#!/bin/sh  "$(dirname "$0")/_/husky.sh"  
  
npm run lint-staged

现在我们在代码中添加一段错误代码

image.png

提交代码

git add .  
git commit -'msg'

此时会报错,并且阻止git commit

image.png

commit-msg

这是校验git commit文本的文件

我们需要先在根目录下新建一个 commitlint.comfig.js,用来配置git commit的文本规范

// commitlint.config.js  
  
module.exports = {  
  // ↓忽略包含init的提交消息  
  ignores: [(commit) => commit.includes('init')],  
  // ↓按照传统消息格式来验证  
  extends: ['@commitlint/config-conventional'],  
  // 自定义解析器  
  parserPreset: {  
    // 解析器配置  
    parserOpts: {  
      // commit 提交头的规则限制  
      headerPattern/^(\w*|[\u4e00-\u9fa5]*)(?:[\(\(](.*)[\)\)])?[\:\:] (.*)/,  
      // 匹配分组  
      headerCorrespondence: ['type''scope''subject'],  
      // 引用  
      referenceActions: [  
        'close',  
        'closes',  
        'closed',  
        'fix',  
        'fixes',  
        'fixed',  
        'resolve',  
        'resolves',  
        'resolved',  
      ],  
      // 对应issue要携带#符号  
      issuePrefixes: ['#'],  
      // 不兼容变更  
      noteKeywords: ['BREAKING CHANGE'],  
      fieldPattern/^-(.*?)-$/,  
      revertPattern/^Revert\s"([\s\S]*)"\s*This reverts commit (\w*)\./,  
      revertCorrespondence: ['header''hash'],  
      // warn () { },  
      mergePatternnull,  
      mergeCorrespondencenull,  
    },  
  },  
  // ↓自定义提交消息规则  
  rules: {  
    // ↓body以空白行开头  
    'body-leading-blank': [2'always'],  
    // ↓footer以空白行开头  
    'footer-leading-blank': [1'always'],  
    // ↓header的最大长度  
    'header-max-length': [2'always'108],  
    // ↓subject为空  
    'subject-empty': [2'never'],  
    // ↓type为空  
    'type-empty': [2'never'],  
    // ↓type的类型  
    'type-enum': [  
      2,  
      'always',  
      [  
        'feat',  
        'fix',  
        'perf',  
        'style',  
        'docs',  
        'test',  
        'refactor',  
        'build',  
        'ci',  
        'chore',  
        'revert',  
        'wip',  
        'workflow',  
        'types',  
        'release',  
        'update',  
      ],  
    ],  
  },  
}

然后我们只需要在commit-msg文件中读取这个规范,并对提交文本进行相对应的规范就行

// commit-msg  
  
#!/bin/sh  "$(dirname "$0")/_/husky.sh"  
  
npx --no-install commitlint --edit "$1"

现在试一下

git add .  
git commit -'sdsdsdsd'

这个提交文本是不符合规范的所以会报错

image.png

只有符合规范的文本才能完成提交

git add .  
git commit -'fix: 修改bug'

.gitignore

.gitignore的作用是可以忽略git提交的文件夹,比如 node_modules,所以我们需要在根目录下新建一个.gitignore文件

// .gitignore  
  
node_modules

vscode设置

在根目录下新建.vscode文件夹,然后在此文件夹中新建setting.json,这个文件夹就是本项目工作区间的vscode设置

// .vscode/setting.json  
  
{  
  //========================================  
  //============== 编辑器 ===================  
  //========================================  
  // 光标的动画样式  
  "editor.cursorBlinking": "phase",  
  // 光标是否启用平滑插入的动画  
  "editor.cursorSmoothCaretAnimation": true,  
  // vscode重命名文件或移动文件自动更新导入路径  
  "typescript.updateImportsOnFileMove.enabled": "always",  
  // 自动替换为当前项目的内置的typescript版本  
  "typescript.tsdk": "./node_modeles/typescript/lib",  
  // 一个制表符占的空格数(可能会被覆盖)  
  "editor.tabSize": 2,  
  // 定义一个默认和的格式程序 (prettier)  
  "editor.defaultFormatter": "esbenp.prettier-vscode",  
  // 取消差异编辑器忽略前空格和尾随空格的更改  
  "diffEditor.ignoreTrimWhitespace": false,  
  // 定义函数参数括号前的处理方式  
  "javascript.format.insertSpaceBeforeFunctionParenthesis": true,  
  // 在键入的时候是否启动快速建议  
  "editor.quickSuggestions": {  
    "other": true,  
    "comments": true,  
    "strings": true  
  },  
  //========================================  
  //============== Other ===================  
  //========================================  
  // 启用导航路径  
  "breadcrumbs.enabled": true,  
  //========================================  
  //============== Other ===================  
  //========================================  
  // 按下Tab键展开缩写 (例如Html的div,在键入的时候按Tab,快捷生成出来)  
  "emmet.triggerExpansionOnTab": true,  
  // 建议是否缩写 (如Html的<div />)  
  "emmet.showAbbreviationSuggestions": true,  
  // 建议是否展开 (如Html的 <div></div>)  
  "emmet.showExpandedAbbreviation": "always",  
  // 为制定语法文件定义当前的语法规则  
  "emmet.syntaxProfiles": {  
    "vue-html": "html",  
    "vue": "html",  
    "xml": {  
      "arrt_quotes": "single"  
    }  
  },  
  // 在不受支持的语言中添加规则映射  
  "emmet.includeLanguages": {  
    "jsx-sublime-babel-tags": "javascriptreact"  
  },  
  //========================================  
  //============== Files ==================  
  //========================================  
  // 删除行位空格  
  "files.trimTrailingWhitespace": true,  
  // 末尾插入一个新的空格  
  "files.insertFinalNewline": true,  
  // 删除新行后面的所有新行  
  "files.trimFinalNewlines": true,  
  // 默认行尾的字符  
  "files.eol": "\n",  
  // 在查找搜索的时候集成的文件  
  "search.exclude": {  
    "**/node_modules": true,  
    "**/*.log": true,  
    "**/*.log*": true,  
    "**/bower_components": true,  
    "**/dist": true,  
    "**/elehukouben": true,  
    "**/.git": true,  
    "**/.gitignore": true,  
    "**/.svn": true,  
    "**/.DS_Store": true,  
    "**/.idea": true,  
    "**/.vscode": false,  
    "**/yarn.lock": true,  
    "**/tmp": true,  
    "out": true,  
    "dist": true,  
    "node_modules": true,  
    "CHANGELOG.md": true,  
    "examples": true,  
    "res": true,  
    "screenshots": true  
  },  
  // 搜索文件夹时候排外的文件夹  
  "files.exclude": {  
    "**/bower_components": true,  
    "**/.idea": true,  
    "**/tmp": true,  
    "**/.git": true,  
    "**/.svn": true,  
    "**/.hg": true,  
    "**/CVS": true,  
    "**/.DS_Store": true,  
    "**/node_modules": false  
  },  
  // 文件监视器排外的文件 可减少初始化打开项目的占用大量cpu  
  "files.watcherExclude": {  
    "**/.git/objects/**": true,  
    "**/.git/subtree-cache/**": true,  
    "**/.vscode/**": true,  
    "**/node_modules/**": true,  
    "**/tmp/**": true,  
    "**/bower_components/**": true,  
    "**/dist/**": true,  
    "**/yarn.lock": true  
  },  
  "stylelint.enable": true,  
  "stylelint.packageManager": "yarn",  
  //========================================  
  //============== Eslint ==================  
  //========================================  
  // 状态栏显示Eslint的开启状态  
  "eslint.alwaysShowStatus": true,  
  // Eslint的选项  
  "eslint.options": {  
    // 要检查的文件拓展名数组  
    "extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]  
  },  
  // Eslint校验的  
  "eslint.validate": [  
    "javascript",  
    "typescript",  
    "reacttypescript",  
    "reactjavascript",  
    "html",  
    "vue"  
  ],  
  //========================================  
  //============== Prettier ================  
  //========================================  
  //  使用当前项目的prettier配置文件,如果没有则使用默认的配置  
  "prettier.requireConfig": true,  
  "editor.formatOnSave": true,  
  // 以下程序使用prettier默认进行格式化  
  "[typescript]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  "[typescriptreact]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  "[javascriptreact]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  "[html]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  "[css]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  "[less]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  "[scss]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  "[markdown]": {  
    "editor.defaultFormatter": "esbenp.prettier-vscode"  
  },  
  // 保存文件的时候的配置  
  "editor.codeActionsOnSave": {  
    // 使用Eslint格式化代码  
    "source.fixAll.eslint": true,  
    // 使用stylelint格式化代码  
    "source.fixAll.stylelint": true  
  },  
  "[vue]": {  
    "editor.codeActionsOnSave": {  
      // 使用Eslint格式化代码  
      "source.fixAll.eslint": true,  
      // 使用stylelint格式化代码  
      "source.fixAll.stylelint": true  
    },  
    "editor.defaultFormatter": "johnsoncodehk.volar"  
  },  
  "compile-hero.disable-compile-files-on-did-save-code": true,  
  "i18n-ally.localesPaths": ["src/locales", "src/locales/lang"]  
}