30分钟彻底搞懂前端工程化

254 阅读6分钟

基于EditorConfig+Eslint+Prettier+stylelint+commitizen+husky+lint-staged+commitlint,实现前端代码规范

创建.editorconfig配置文件 editorconfig

  1. 作用: 统一IDE编码风格 (例如: vscode、webstore)各别IDE需要安装对应插件,webstore已内置,vscode需要安装插件,其他IDE可以查看editorconfig官网查看。

  2. 使用:在项目根目录创建.editorconfig

  3. 常用配置项:

root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
  1. 配置项说明:
indent_style    设置缩进风格(tab是硬缩进,space为软缩进)
indent_size     用一个整数定义的列数来设置缩进的宽度,如果indent_style为tab,则此属性默认为  tab_width
tab_width       用一个整数来设置tab缩进的列数。默认是indent_size
end_of_line     设置换行符,值为lf、cr和crlf
charset         设置编码,值为latin1、utf-8、utf-8-bom、utf-16be和utf-16le,不建议使用utf-8-bom
trim_trailing_whitespace  设为true表示会去除换行行首的任意空白字符。
insert_final_newline      设为true表示使文件以一个空白行结尾
root           表示是最顶层的配置文件,发现设为true时,才会停止查找.editorconfig文件  

安装Eslint

  1. 安装依赖
yarn add --dev eslint eslint-define-config eslint-plugin-vue vue-eslint-parser
  1. 创建eslint配置文件 eslint-config
  • 在根目录下创建.eslintrc.js文件
const { defineConfig } = require("eslint-define-config");
module.exports = defineConfig({
    env: {
        browser: true,
        es2021: true,
        jest: true
    },
    extends: [
        /** * 继承 eslint-plugin-vue 插件的规则 * @link https://eslint.vuejs.org/user-guide/#installation */
        "plugin:vue/recommended",
        "plugin:prettier/recommended"
    ],
    parserOptions: {
        ecmaVersion: "latest",
        sourceType: "module",
        parse: "vue-eslint-parser",
    },
    plugins: ["vue"],
    rules: {},
});
  1. 添加eslint过滤规则配置
  • 在根目录下创建.eslintignore文件

安装prettier

  1. 安装依赖
yarn add --dev prettier eslint-config-prettier eslint-plugin-prettier
  1. 在根目录创建.prettierrc.js配置文件
module.exports = {
    tabWidth: 4,
};
  1. 修改Eslint配置文件,使Eslint兼容prettier规则
const { defineConfig } = require('eslint-define-config')

module.exports = defineConfig({
  /// ...
  extends: [
    /**
     * 继承 eslint-plugin-vue 插件的规则
     * @link https://eslint.vuejs.org/user-guide/#installation
     */
    'plugin:vue/recommended',
    /**
     * 继承 eslint-plugin-prettier 插件的规则
     * @link https://github.com/prettier/eslint-plugin-prettier
     */
    'plugin:prettier/recommended'
  ],
  // ...
})

自动格式化代码

  1. 使用的IDE vscode,可以在配置文件设置,根据上面我们的配置,在保存文件时直接可以格式化代码了。在工作区里设置,只对当前的项目起作用。

常用设置.png

{
    // Eslint配置
    "editor.codeActionsOnSave": {
        "source.fixAll": true, // 控制是否应在文件保存时运行自动修复操作
        "source.fixAll.eslint": true  // 保存时,根据Eslint规则格式化代码
    }
}

css代码格式化 (配置支持stylelint@14.x版本,13.x包含及一下版本不适用此配置)

  1. 安装依赖
yarn add --dev stylelint stylelint-config-prettier stylelint-config-rational-order stylelint-order stylelint-config-standard
  1. 在根目录下创建.stylelintrc.js
module.exports = {
    root: true,
    extends: [
        "stylelint-config-standard",
        "stylelint-config-rational-order",
        "stylelint-config-prettier",
    ],
    defaultSeverity: "warning",
    plugins: ["stylelint-order"]
}

3.在根目录下创建.eslintignore文件

dist
  1. 启用支持vue文件 在stylelint@14版本默认是不支持vue文件样式自动检测,官方迁移指南
yarn add --dev stylelint-config-html postcss-html postcss-scss
  1. 修改.eslintrc.js配置文件
module.exports = {
    root: true,
    extends: [
        "stylelint-config-standard",
        "stylelint-config-rational-order",
        "stylelint-config-prettier",
        "stylelint-config-html/vue", //需要放在最后
    ],
    defaultSeverity: "warning",
    plugins: ["stylelint-order"],
    overrides: [
        {
            files: "**/*.scss",
            customSyntax: "postcss-scss"
        },
        {
            files: ["*.vue", "**/*.vue"],
            rules: {
                "selector-pseudo-class-no-unknown": [
                    true,
                    {
                        ignorePseudoClasses: ["deep", "global"],
                    },
                ],
                "selector-pseudo-element-no-unknown": [
                    true,
                    {
                        ignorePseudoElements: [
                            "v-deep",
                            "v-global",
                            "v-slotted",
                        ],
                    },
                ],
            },
        },
    ],
}
  1. 修改vscode工作区配置
{
    // Eslint配置
    "editor.codeActionsOnSave": {
        "source.fixAll": true,
        "source.fixAll.eslint": true
    },
    "stylelint.validate": [
        "css",
        "postcss",
        "scss",
        "sass",
        "vue"
    ],
}

检查typescript

如果项目中使用了typescript,添加以下配置

  1. 安装依赖
  1. 修改.eslintrc.js配置文件
module.exports = defineConfig({
    /// ...
    extends: [
        "eslint:recommended",
        /**
         * 继承 eslint-plugin-vue 插件的规则
         * @link https://eslint.vuejs.org/user-guide/#installation
         */
        "plugin:vue/recommended",
        /**
         * 继承 eslint-plugin-prettier 插件的规则
         * @link https://github.com/prettier/eslint-plugin-prettier
         */
        "plugin:prettier/recommended",
        "prettier/@typescript-eslint",
        "plugin:@typescript-eslint/recommended",
  ],
  parser: "vue-eslint-parser",
    parserOptions: {
        ecmaVersion: 2020,
        sourceType: "module",
        parser: "@typescript-eslint/parser",
    },
  plugins: ["vue", "@typescript-eslint"],
  // ...
}

注意: parser: 'vue-eslint-parser' ,这里要区分和 parserOptions.parser 的区别,vue-eslint-parser 是解析 .vue 文件,而 parserOptions.parser:@typescript-eslint/parser 是我们自定义来解析 TypeScript 文件的,否则就无法正确的检验 TypeScript 相关内容

全部配置

const { defineConfig } = require("eslint-define-config");
module.exports = defineConfig({
    env: {
        browser: true,
        node: true,
        es2021: true,
        jest: true,
    },
    extends: [
        "eslint:recommended",
        /**
         * 继承 eslint-plugin-vue 插件的规则
         * @link https://eslint.vuejs.org/user-guide/#installation
         */
        "plugin:vue/recommended",
        /**
         * 继承 eslint-plugin-prettier 插件的规则
         * @link https://github.com/prettier/eslint-plugin-prettier
         */
        "plugin:prettier/recommended",
        "prettier/@typescript-eslint",
        "plugin:@typescript-eslint/recommended",
    ],
    parser: "vue-eslint-parser",
    parserOptions: {
        ecmaVersion: 2020,
        sourceType: "module",
        parser: "@typescript-eslint/parser",
    },
    plugins: ["vue", "@typescript-eslint"],
    rules: {
        "no-fallthrough": [
            "error",
            { commentPattern: "break[\\s\\w]*omitted" },
        ],
        // 关闭vue标签不能出现v-html属性
        "vue/no-v-html": 0,
        // 关闭vue组件名称必须是多词
        "vue/multi-word-component-names": 0,
        // vue2.x选项无用
        "vue/no-lone-template": 0,
        // 关闭正则转义
        "no-useless-escape": 0,
        "vue/html-indent": 0,
        "vue/html-self-closing": 0,
        "vue/max-attributes-per-line": [
            "error",
            {
                singleline: {
                    max: 4,
                },
                multiline: {
                    max: 1,
                },
            },
        ],
        "vue/singleline-html-element-content-newline": 0,
        "no-case-declarations": 0,
    },
    globals: {
        _: true,
        mapActions: true,
        mapGetters: true,
        mapState: true,
        mapMutations: true,
        _MEIQIA: true,
        mapboxgl: true,
        $nuxt: true,
        regExp: true,
    },
});

Git Hook

和其他版本控制系统一样,Git也能在特定的重要动作发生时出发自定义脚本。有两种这样的钩子:客户端和服务器端。客户端钩子由诸如提交和合并这样的操作调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。

  1. 客户端钩子
  • pre-commit: 在提交 commit message 前运行。用于检查即将提交的快照,例如检查是否有遗漏、运行测试、检查代码。如果该钩子以非零值退出,那么Git将放弃此次提交,可以用该钩子来做一写代码提交前的准备工作,例如,提交的代码变动是否符合工程的代码lint规则。
  • prepare-commit-msg: 在 commit message 提交后,commit message 被保存之前运行。该钩子接收一下信息并将其作为参数:存有当前提交信息的文件的路径、提交类型和修补提交的SHA-1校验。在大多数情况下,这样对一般的提交作用不大,然而对于那些会自动产生默认信息的提交,如提交信息模板、合并提交、压缩提交、和修订提交和修改提交等非常实用。可以结合提交模板来使用它,动态的插入信息。
  • commit-msg: 接收存有当前提交信息的临时文件的路径并将其作为参数。如果该钩子脚本以非零值退出,那么Git将放弃提交。因此,可以使用该钩子在提交通过前验证项目状态或提交信息。
  • post-commit: 在整个提交过程完成后运行。不接受任何参数,一般用于提交通知,触发一些自定义行为。
  • pre-push: 在 git push 运行时更新了远程引用但尚未传送对象时被调用。接收远程分支的名字和位置并将其作为参数,同事从标准输入中读取一系列待更新的引用。可以在推送开始之前,用它验证对应用的更新操作。如果它以非零值退出,则终止推送课程。
  1. 服务端钩子
  • pre-receive
  • update
  • post-receive

commitizen

commitizen是一个格式化commit message的工具

  1. 全局安装依赖
yarn global add commitizen   // 全局安装

全局安装commitizen时,就可以把git commit 替换为 git cz来提交commit message信息了

commitizen init cz-conventional-changelog --yarn --dev --exact

初始化cz-conventional-changelog后,在package.json里会生成如下配置

{
    //...
    "config": {
        "commitizen": {
            "path": "./node_modules/cz-conventional-changelog"
        }
    }
}

WechatIMG221.png 2. 局部安装

yarn add --dev commitizen

需要在package.json中的scripts属性下设置如下命令

{
    ///...
    commit: 'cz'
    ///...
}
npx commitizen init cz-conventional-changelog --yarn --dev --exact

和全局安装生成的配置一样

husky

husky 是一个开源社区的Git Hook 工具,属于前端工程化搭建中必不可少的部分。它可以让开发人员更加便捷快速地使用Git Hook

  1. 安装依赖
yarn add --dev husky lint-staged @commitlint/cli @commitlint/config-conventional
  1. 生成.husky配置文件夹
yarn husky install
  • 添加pre-commit配置文件
yarn husky add .husky/pre-commit
  • 创建.lintstagedrc.js配置文件
module.exports = {
    "*.{js,ts,jsx,tsx}": ["prettier --write", "eslint --fix"],
    "*.vue": ["stylelint --fix", "prettier --write", "eslint --fix"],
    "*.{scss,css}": ["stylelint --fix", "prettier --write"],
}
  • 修改.husky/pre-commit文件
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged

经过以上配置之后,我们就可以在每次提交之前对所有代码进行格式化,保证线上代码的规范性。

  • 创建.commitlintrc.js配置文件
module.exports = {
    extends: ["@commitlint/config-conventional"]
};
  • 添加commit-msg配置文件
yarn husky add .husky/commit-msg "npx commitlint --edit $1"

在git commit-msg时进行检查

  1. Commit Message格式

约定式提交規范.png

自定义规范

英文看不懂,可以自己自定义成中文,或者添加其他的提交规范

  1. 添加依赖
yarn add --dev commitlint-config-cz cz-customizable

2.创建.cz-config配置文件

module.exports = {
    types: [
        { value: "init", name: "init:     初始提交" },
        { value: "feat", name: "feat:     增加新功能" },
        { value: "fix", name: "fix:      修复bug" },
        { value: "docs", name: "docs:      添加或修改了文档" },
        { value: "ui", name: "ui:       更新UI" },
        {
            value: "style",
            name: "style:    修改格式、书写错误、空格等不影响代码逻辑的操作",
        },
        {
            value: "refactor",
            name: "refactor: 修改的代码不是新增功能也不是修改bug,比如代码重构",
        },
        { value: "perf", name: "perf:     修改了提升性能的代码" },
        { value: "test", name: "test:     增删测试" },
        { value: "build", name: "build:     修改了编译配置文件" },
        { value: "chore", name: "chore:    无src或test的操作" },
        { value: "revert", name: "revert:   回滚操作" },
        { value: "add", name: "add:      添加依赖" },
        { value: "delete", name: "del:      删除代码/文件" },
        { value: "merge", name: "merge:      合并文件" },
    ],
    scopes: [
        { name: "components" },
        { name: "styles" },
        { name: "utils" },
        { name: "store" },
        { name: "config" },
        { name: "plugins" },
        { name: "deps" },
    ],
    messages: {
        type: "选择更改类型:\n",
        // 如果allowcustomscopes为true,则使用
        scope: "选择一个 scope(可选):\n",
        customScope: "请输入自定义的 scope:",
        subject: "简短描述:\n",
        body: '详细描述. 使用"|"换行:\n',
        breaking: "Breaking Changes列表:\n",
        footer: "关闭的issues列表. E.g.: #31, #34:\n",
        confirmCommit: "确认提交?",
    },
    allowCustomScopes: true,
    allowBreakingChanges: ["feat", "fix"],
};

3.修改package.json,改为自定义规范

{
    ///...
    "config": { //替换之前的配置
        "commitizen": {
          "path": "./node_modules/cz-customizable"
        }
      }
}
  1. 修改.commitlintrc.js文件
  • cz: 自定规范
  • @commitlint/config-conventional: Angular 团队使用的规范
  • extends: 可以同时使用多个规范
module.exports = {
    extends: ["@commitlint/config-conventional", "cz"],
    rules: {
        // Header
        "header-max-length": [2, "always", 200],
        // <type>枚举
        "type-enum": [
            2,
            "always",
            [
                "init", // 初始化
                "feat", // 增加新功能
                "fix", // 修复bug
                "docs", // 修改文档
                "ui", // 更新ui
                "style", // 样式修改不影响逻辑
                "refactor", // 代码重构
                "perf", // 提升性能
                "test", // 单元测试修改
                "build", // 编译配置
                "chore", // 无src或test的操作
                "revert", // 回滚操作
                "add", // 添加依赖
                "delete", // 删除代码/文件
                "merge", // 合并分支
            ],
        ],
        // <type> 不能为空
        "type-empty": [2, "never"],
        // <scope> 不能为空
        "scope-empty": [2, "never"],
        // <subject> 不能为空
        "subject-empty": [2, "never"],
        // <subject> 以.为结束标志
        "subject-full-stop": [2, "never", "."],
        "subject-case": [2, "never", []],
        // <body> 以空行开头
        "body-leading-blank": [1, "always"],
        // <footer> 以空行开头
        "footer-leading-blank": [1, "always"],
    },
};

需要安装的vscode插件

  • EditorConfig for VS Code
  • ESlint
  • Prettier - Code formatter
  • Stylelint 都选择启用工作区的选项

启用.png