How to implement specification of code in Webpack project?

foreword

Hello everyone, I'm Lin Sanxin. The most difficult knowledge point is my motto in the most easy-to-understand words . The foundation is the premise of advanced is my original intention

background

In the previous two articles, I have taken you to do these two things:

  • Basic construction of Vuecli
  • Optimize the scaffolding after construction

Eslint

what is

EslintIt is used to standardize JavaScriptthe specification, and it focuses more on 语法方面the specification of the specification, which is very important for the development of a team.

For example, development A uses a double equal sign ==, while development B uses a triple equal sign ===, which will make it difficult to troubleshoot errors after merging the code, so it should be unified ===, this is Eslintthe main role

configure

I have already done it with you before 开发环境(development), 生产环境(production)so Eslintin which environment should it be configured? In fact, this should depend on the specifications of your team. Here I only configure it 开发环境(development)in , because I think the grammar will only be standardized during development.

First let's install these packages

  • eslint: Eslint dependencies
  • eslint-config-airbnb-base: Out-of-the-box solutions for Eslint
  • eslint-plugin-import: Supports Eslint extension configuration
  • eslint-webpack-plugin: A plugin that configures Eslint in webpack
npm i 
eslint eslint-config-airbnb-base
eslint-plugin-import eslint-webpack-plugin
复制代码

After installation, we need to create two files in the root directory.eslintrc.js、.eslintignore

  • .eslintrc.js: Eslint configuration is written here
// .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: Which files to ignore Eslint detection, write here
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
复制代码

We have only completed our Eslintown configuration now, but our purpose is to prompt syntax errors in the terminal when developing and building, so we need to configure the Eslintconfiguration webpack.dev.jsin

// webpack.dev.js

// 之前的代码...
const ESLintPlugin = require('eslint-webpack-plugin')

module.exports = merge(base, {
  // 之前的代码...
  plugins: [
    // 之前的代码...
    new ESLintPlugin({
      // 运行的时候自动帮你修复错误
      fix: true,
    })
  ]
})
复制代码

In this way, you will be able npm run serveto prompt your grammar errors in the ~~~ For example, I am now randomly making an error code

const nn = 2
nn = 1
复制代码

At this point, the terminal will report an error

vscode plugin

But we found a problem, the terminal is reporting an error, but how can the editor report an error directly when developing? like this

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

配置命令

我们也可以在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

module.exports = {
  // 刚才的代码...
  
  // 拓展插件
  plugins: ['prettier'],
  // 自定义规则,会覆盖一部分拓展规则
  rules: {
    // 刚才的代码...
    
    // prettier提示报错
    'prettier/prettier': 'error'
  },
  // 刚才的代码...
}

复制代码

vscode插件

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

Stylelint

是什么

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

配置

我们需要安装下面的插件

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

然后我们在根目录下新建一个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中去

// webpack.dev.js

// 之前的代码...

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

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

现在scss文件出现错误,或者顺序错误,都会报错了

vscode插件

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

配置命令

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

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

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

husky

是什么

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

配置

配置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文件夹

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

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

接下来我们就讲讲这两个文件所有关的事情~~~

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
复制代码

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

我们提交代码

git add .
git commit -m 'msg'
复制代码

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

commit-msg

这是校验git commit文本的文件

我们需要先在根目录下新建一个commitlint.config.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 () { },
      mergePattern: null,
      mergeCorrespondence: null,
    },
  },
  // ↓自定义提交消息规则
  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 -m 'sdsdsdsd'
复制代码

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

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

git add .
git commit -m 'fix: 修改bug'
复制代码

.gitignore

.gitignore的作用是可以忽略git提交的文件夹,比如node_modules

所以我们需要在根目录下新建一个.gitignore文件

// .gitignore

node_modules
复制代码

vscode设置

最后分享一下我的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"]
}


复制代码

整体结构

到这里我们就完成我们的脚手架三件套了

  • 基本搭建
  • 基本优化
  • 基本规范

结语

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜欢前端,想学习前端,那咱们可以交朋友,一起摸鱼哈哈,摸鱼群,点这个 --> 摸鱼沸点

image.png

Guess you like

Origin juejin.im/post/7084564788365721613