【工程化】如何配置lint 01

关键词: lint-staged、husky、commitlint、eslint、stylelint、prettier、commitlint

这些是我们日常生活中必不可可少的,有些是框架就帮你做好了,你可能不知道在precommit之前都做了什么

如何避免每次新建项目拷贝eslint、stylelint、preitter等规则,建立一个预设或extends?

eslint规则为什么老是和preitter规则冲突?

如何自己写一个plugins?

husky

第一步安装husky

它是一个git hook,husky支持的git hooks,常用的是 pre-commit、commit-msg

js 复制代码
// 1.  Install `husky`
npm install husky --save-dev

// 2.  Enable Git hooks
npx husky install

// 3. 在package.json的scripts 下面添加
  "prepare": "husky install"  // yarn2+ 不支持,用postinstall
  

第二步创建hook

js 复制代码
// 创建pre-commit hooks并且添加脚本,这个脚本的内容根据使用的工具会有所区别,但意思就是在我commit之前使用lint-staged帮我校验一些东西,比如eslint、stylelint等修复
npx husky add .husky/pre-commit "npx --no-install lint-staged --quiet"

//创建commit-msg,使用commitlint规范commit msg
npx husky add .husky/commit-msg "npx -r exec commitlint --edit $1"

npx --no-install lint-staged究竟是什么意思,pnpm 中是怎么配置,lerna呢

  • --no-install 是npx的参数,不要安装缺少的依赖,而是从本地中安装

  • --quiet 安装期间禁止输出详细信息,只输出关键结果

  • --edit 以在交互模式下编辑提交信息

更多npx参数

注意点

4升级到8这是一个大的break change,由之前的.huskyrc json文件变成.huskyrc/commit-msg

lint-staged

在commit 之前,可以自动prettier、eslint、stylelint等

下面逐一分析eslint、stylelint、prettier

js 复制代码
// 一个简单package.json lint-staged相关的配置的实力
{
  "**/*.{js,jsx,tsx,ts,less,scss,md,json}": [
    "prettier --cache --write"
  ],
  "*.{js,jsx,ts,tsx}": [
    "elintint --fix ",
  ],
  "*.{css,less}": [
    "stylelint --fix",
  ],
   "lint-staged": {
    "**/*.less": "pnpm lint:style --fix",
    "**/*.{js,jsx,ts,tsx}": "pnpm lint:js --fix",
    "**/*.{js,jsx,tsx,ts,less,scss,md,json}": [
      "prettier --write"
    ]
  }

eslint

umi中eslint的配置

注意,配置文件的优先级,降序排列,其他的配置文件也是类似的顺序

  1. .eslintrc.js
  2. .eslintrc.cjs
  3. .eslintrc.yaml
  4. .eslintrc.yml
  5. .eslintrc.json
  6. package.json

eslint参数

参数配置太多,咱们就是挑重点的讲

parser

@typescript-eslint/parser举例子

js 复制代码
import @typescript-eslint/parser from "@typescript-eslint/parser";

{
      parser: require.resolve('@typescript-eslint/parser'),
      plugins: ['@typescript-eslint/eslint-plugin'],
      files: ['**/*.{ts,tsx}'],
      parseroptions:{
        ecmaFeatures: {  
         jsx: true
        }
    }
}

总共也就是三个parser

plugins
js 复制代码
module.exports = {
  extends: [
    'plugin:react/recommended'
  ],
  plugins: ['react'], // 安装依赖会是  eslint-plugin-react
  rules:{
  // 通常规则都是会以react/xx开头
   'react/jsx-uses-react': 'error',
   'react/jsx-uses-vars': 'error',
   'react/xxx'
  }
processor

处理器允许ESLint将文本转换成ESLint可以检测的代码片段。

js 复制代码
import markdown from "eslint-plugin-markdown";

export default [
   {
       files: ["**/*.md"],
       plugins: {
           markdown
       },
       processor: "markdown/markdown",
       settings: {
           sharedData: "Hello"
       }
   }
];
settings

如果在settings下设置参数,则会应用于每一个规则

css 复制代码
  settings: {
    react: {
      version: 'detect',
    },
  },
rules

这可以不用多说,就是就是各种各样的eslint规则。有一点注意: off-0 是关闭规则,warn-1是警告,error-2 打开规则

languageOptions
js 复制代码
export default [
    {
        files: ["**/*.js"],
        languageOptions: {
            ecmaVersion: 5
        }
    }
];
  • ecmaVersion: 配置JavaScript类型

参数有"module", "commonjs", or "script", 默认是 module

  • parser: 自定义parser
js 复制代码
// 覆盖默认的parser ,注意parser 和parserOptions可以不用写在languageOptions里面
import babelParser from "@babel/eslint-parser";

export default [
    {
        files: ["**/*.js", "**/*.mjs"],
        languageOptions: {
            parser: babelParser,
            parserOptions: {
                requireConfigFile: false,
                babelOptions: {
                    babelrc: false,
                    configFile: false,
                    // your babel options
                    presets: ["@babel/preset-env"],
                }
            }
        }
    }
];
  • globals: 设置全局变量
css 复制代码
  globals: {
    NodeJS: 'writable/readable',
    JSX: 'writable/readable',
    Formily: 'writable/readable'
  },

📢注意: 有些地方配置是false === readable ===readonly ,true === writeable === writable

其实更推荐这么用, 因为eslint 不会预定义, 推荐globals这个包

python 复制代码
import globals from "globals";
export default [
    {
        languageOptions: {
            globals: {
                ...globals.browser
            }
        }
    }
];

eslint配置示例

这是一个支持ts的react版本简单实例

js 复制代码
pnpm add eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-react -D

然后使用pnpm eslint --init,根据提示选择

就会得到这样一份初始文件

js 复制代码
// .eslintrc.js
module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:react/recommended"
    ],
    "overrides": [
        {
            "env": {
                "node": true
            },
            "files": [
                ".eslintrc.{js,cjs}"
            ],
            "parserOptions": {
                "sourceType": "script"
            }
        }
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint", // @typescript-eslint/eslint-plugin
        "react" // eslint-plugin-react
    ],
    "rules": {
    }
}

};

ts支持

主要是安装了@typescript-eslint/parser@typescript-eslint/eslint-plugin,

  • @typescript-eslint/parser 解析ts代码,否则eslint不认识,直接报错
  • @typescript-eslint/eslint-plugin 在代码中,可以使用Typescipt-eslint规则,依赖于 @typescript-eslint/parser
  • plugin:@typescript-eslint/recommended

你可能会好奇,为什么extends 和 plugin 名字奇奇怪怪的,让人有点蒙圈。 其实他们是有规则

比如, plugins: ['react', '@typescript-eslint']的写法, plugins具体名字就是eslint-plugin-react@typescript-eslint/eslint-plugin, extend 对应的名字是 plugin:react/recommondplugin:@typescript-eslint/recommended

一般来说,plugins 和 extends 是成对出现的,当然可以只有extends. 比如官方提供的eslint:recommended ,还有非官方的airbnb(对应的依赖是eslint-config-airbnb)

所以你看到这张图还会蒙圈吗,是不是敏锐地发现plugins 少写了参数,但是这不影响, 对应的还是能被正确的安装

plugins: ['@typescript-eslint','react','react-hooks','preitter']

react 支持

  • eslint-plugin-react
  • plugin:react/recommended

stylelint

umi中stylelint的配置

pnpm add stylelint stylelint-config-standard -D

js 复制代码
stylelintrc.js
{
  "extends": "stylelint-config-standard",
  "rules": {
    "property-no-vendor-prefix": [
      true,
      {
        "severity": "warning"
      }
    ]
  },
 customSyntax: require.resolve('postcss-less'),
 overrides: [
    {
      files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
      customSyntax: require.resolve('@stylelint/postcss-css-in-js'),
    },
  ],
}

常用几个extend

熟悉customSyntax,在实际过程中经常冲突。我以为只要配置stylelint-config-standard就好了,实际还有很多配合一起使用

prettier

arduino 复制代码
npm install --save-dev prettier eslint-config-prettier
ignore
js 复制代码
// ..prettierignore
node_modules
...
集成linter
preitter --write 和 preitter --check
  • preitter --write 自动修复和eslint --fix差不多
  • preitter --check 就是check

更多查看

配置文件
ini 复制代码
module.exports = { ...require("@company/prettier-config"), semi: false, };
  • editortconfig
js 复制代码
// 这里的配置会覆盖prettierrc, 所以最好不要重复
 # Non-configurable Prettier behaviors
[*] charset = utf-8 
insert_final_newline = true
# Caveat: Prettier won't trim trailing whitespace inside template strings, but your editor might.  Prettier不会删除字符串模板的尾随空格,当时编辑器会
# trim_trailing_whitespace = true

# Configurable Prettier behaviors # (change these if your Prettier config differs)
# https://prettier.io/docs/en/options.html 有类似的参数
end_of_line = lf
indent_style = space 
indent_size = 2 
max_line_length = 80

所以笔记写到的时候,我忽然悟了。总是你本地代码格式化与团队的不一致,是不是因为这里

eslint、stylelint、preitter合集解决方案

有没有觉得eslint、stylelint、preitter 一套下来,配置的东西还是有点多,可以参考社区的解决方案fabric

commitlint

commit 规范,参考zhuanlan.zhihu.com/p/51894196

changelog

主要是开源库当中会用,具体后续补充

问题

1、如何自己写一个plugin?

TODO: 后续补充

2、熟悉常用的规则,如果是通用的,应该怎么封装起来

如果但是rules的话,直接抽成一个公用的文件;如果还有其他配置的话, 用extends

js 复制代码
 module.exports = {
  extends: ['../../.eslintrc.js', 'plugin:react/jsx-runtime']
};

3、 为什么我们经常碰到因为配置器导致格式化不一致的问题?

TODO: 下篇接着写

相关推荐
前端啊龙3 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠7 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds27 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app
bysking2 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓3 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4113 小时前
无网络安装ionic和运行
前端·npm
理想不理想v3 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试