阿里前端开发规范落地:ESLint+Prettier+CI自动化检查
2026/9/18 4:34:08 网站建设 项目流程

简介:这是一份面向前端工程师、前端团队负责人及技术新人的开发规范文档,聚焦多人协作中命名混乱、代码风格不统一、样式污染等常见问题。内容依托阿里巴巴集团内部前端实践,系统梳理了命名、HTML、CSS、LESS、JavaScript 等模块的编码约定:命名部分细分为项目命名、目录命名、JS/CSS/SCSS/HTML/PNG 文件命名及命名严谨性要求;HTML 规范覆盖 HTML5 类型声明、四空格缩进、分块注释、语义化标签与双引号使用;CSS 规范则涉及选择器命名、优先使用 class 选择器、缩写属性、单行单属性书写、省略 0 后单位以及避免 ID 与全局标签选择器造成样式污染;LESS 部分强调代码组织与嵌套层级控制。压缩包为 1 个 PDF 文件,共计 1 个文件,大小约 401KB,目录层级清晰,便于按章节跳转查阅。目前已有 4001 人学习下载,适合用作团队代码评审、新人上手参照与个人编码自查的规范手册。

1. 一份 PDF 规范最容易死在"没人看",活下来的是能跑的检查

接手一个五到八人的前端小组,最磨人的往往不是技术选型,而是同一个仓库里混着三种缩进、两套命名,有人写var有人写const,评审会上为分号该不该加争半小时。阿里前端开发规范.pdf这类文档被传来传去,真正读完并落进项目里的却没几个——不是内容不好,而是它更像一本字典,不像一套会自动执行的机制。规范的价值从来不在纸面排版,而在于把"应该怎样"翻译成"提交就会被拦下来"的检查链路。所以这篇不逐条复述那份 PDF,而是讲一件更实在的事:怎么把里面的命名、编码、注释、提交信息等约定,拆成能写进配置、能挂进钩子、能跑在流水线上的东西。适合前端团队 leader、做工程化的同学,以及刚被安排"推规范"的人。

2. 阿里前端开发规范的两层结构:写给人看的部分和交给机器跑的部分

很多人推规范失败,根因是把两类完全不同的条目混在一份文档里用同一种方式推行。阿里前端开发规范这套体系实际可以切成两层:一层是机器能判定对错的,比如缩进、引号、相等运算符、命名格式;另一层是机器判不了、只能靠人和评审把关的,比如目录分层是否合理、组件职责是否单一、注释有没有讲清"为什么"。两层混着推,结果就是评审会变成格式化现场,真正该讨论的设计问题反而没人提。先把边界划清,后面每一层用各自的工具和节奏处理,落地成功率会高很多。

2.1 命名、注释、目录约定为什么还得靠文档

格式化规则能自动修,但"这个工具函数该叫什么"机器给不出有意义的答案。命名承载的是语义,判断标准依赖业务上下文——formatDatetoDisplayTime哪个更清楚,只有了解调用方的人才知道。注释同理,规范里反复强调"注释解释为什么而不是做什么",这句话本身就是给评审者看的判据,lint 顶多检查有没有注释、格式对不对,判断不了内容质量。目录约定更典型,features/还是modules/、公共组件放哪一层,涉及的是整个团队的认知模型,写进文档的目的不是约束机器,而是让新人在没有老人带的情况下也能猜对文件位置。这一层的关键是写得短、给例子、配一张目录树,别写成三千字散文,否则没人翻。

2.2 能交给 lint 判定的条目就别留在评审清单

反过来说,凡是能自动判的,就绝对不该占用人的注意力。下面这张表是我通常用来做条目归类的思路,左边是规范里常见的说法,右边是它该落到哪个工具上。

规范条目判定方式落地工具
统一使用单引号、行尾分号格式Prettier
禁止使用var,优先const静态规则ESLint
变量名小驼峰、常量全大写命名规则ESLint(camelcase 等)
组件文件大驼峰、目录小写中划线文件命名脚本或自定义 lint
样式类名禁止下划线与大写样式规则Stylelint
提交信息遵循类型前缀提交校验commitlint
组件职责单一、目录分层合理人工判断评审清单

这张表的用法是:上线前先对照它整理一遍规范文档,把右边有工具的那几行从"评审必查项"里删掉。评审清单瘦下来之后,大家才会认真看剩下的部分。我见过太多团队把格式化要求和架构原则并列写进 checklist,最后评审者两头都草草扫过。

2.3 从规范条目到工具选型的取舍

工具不是越多越好。ESLint、Prettier、Stylelint 三个是前端主流组合,覆盖 JS/TS、样式、格式化三块。但如果项目是纯 TS + CSS-in-JS,Stylelint 的价值就有限,可以省掉;如果团队用的是 Vue,还得配上eslint-plugin-vue。选型时问自己三个问题:这条规则报错后,开发者能不能在十秒内理解并改对?它会不会和另一个工具的规则打架?开启后误报率能不能压到可接受范围?误报高的规则宁可不加,一条天天误报的规则会让人整片地关掉 lint。这一步做完,规范才算真正分了层,接下来就是把它写成配置。

3. 用 ESLint + Prettier + Stylelint 把阿里前端开发规范翻译成配置

分完层之后要面对的问题是:这些约定怎么变成一份别人 clone 下来就能用的配置。核心原则是"配置集中、可继承、可覆盖"——共享配置放一个包里,各项目 extends 它,个性化规则在项目层覆盖。这样规范升级时改一处,所有项目跟着走,而不是挨个仓库改.eslintrc。下面按依赖安装、ESLint、Prettier、Stylelint 的顺序给一套可直接抄的配置。

3.1 依赖安装与镜像加速

# 初始化项目(已有项目跳过) npm init -y # 安装规范相关依赖,-D 表示开发依赖 npm install -D eslint prettier \ eslint-config-prettier eslint-plugin-prettier \ stylelint stylelint-config-standard stylelint-config-prettier # 国内网络环境可切换镜像源加速安装 npm config set registry https://registry.npmmirror.com

逻辑说明:eslint负责静态检查与部分风格规则;prettier只做格式化;eslint-config-prettier的作用是关闭 ESLint 里所有和 Prettier 冲突的格式规则,避免两个工具左右互搏;eslint-plugin-prettier则把 Prettier 当成一条 ESLint 规则来跑,让格式问题也能在 lint 阶段报出来。参数上-D不能省,这些是构建期工具,打进生产依赖会白白增大体积。镜像源那条命令是把默认 registry 指向国内镜像,装包速度会明显快,团队如果没配私有源,这是最省事的一步。

3.2 ESLint 核心配置

// .eslintrc.js module.exports = { root: true, // 阻止向上冒泡到用户目录的配置,保证规则来源唯一 env: { browser: true, es2022: true, node: true }, parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, extends: [ 'eslint:recommended', // 官方推荐基线,先兜住明显错误 'plugin:prettier/recommended' // 接入 Prettier 并关闭冲突规则 ], rules: { 'no-var': 'error', // 统一 let/const 'prefer-const': 'warn', // 未重新赋值就用 const 'eqeqeq': ['error', 'always'], // 强制 ===,避免隐式转换 'camelcase': ['warn', { properties: 'always' }],// 变量/属性小驼峰 'no-console': ['warn', { allow: ['warn', 'error'] }], 'no-unused-vars': ['error', { argsIgnorePattern: '^_' }] } };

逻辑说明:root: true很关键,如果项目嵌套在用户主目录下,不加它 ESLint 会一路往上找配置,最后用了一堆意想不到的规则,排查起来非常费劲。extends数组从通用到具体依次叠加,eslint:recommended先兜住语法级错误,plugin:prettier/recommended再接管格式。rules里逐条覆盖团队约定,no-vareqeqeq这类是硬错误用error,命名规范用warn给过渡期留余地。argsIgnorePattern: '^_'让以_开头的未用参数免报,这是处理回调签名不得不留占位参数时的常见技巧。

3.3 Prettier 与 ESLint 的分工边界

{ "printWidth": 100, "singleQuote": true, "semi": true, "trailingComma": "all", "tabWidth": 2, "arrowParens": "always" }

逻辑说明:这份.prettierrc覆盖了最容易引发争论的几项。printWidth设成 100 是比较克制的取值,80 会让 JSX 频繁折行、120 又容易在分屏时读不下;singleQuotesemi决定引号与分号风格;trailingComma: 'all'让多行结构末尾带逗号,好处是以后再增删一行时 git diff 只变动一行而不是两行;arrowParens: 'always'强制单参数箭头函数也带括号,配合后续加类型注解时不用回头改。分工上的铁律是:格式只认 Prettier,风格以外的代码质量只认 ESLint,两边规则绝不重复定义,重复了就会互相覆盖。

3.4 Stylelint 收口样式规范

{ "extends": ["stylelint-config-standard", "stylelint-config-prettier"], "rules": { "selector-class-pattern": "^[a-z][a-zA-Z0-9]+$", "declaration-block-no-duplicate-properties": true, "no-descending-specificity": null } }

逻辑说明:stylelint-config-standard提供基础样式规则,stylelint-config-prettier同样关掉和格式化冲突的项。selector-class-pattern用正则约束类名为小驼峰,项目如果用 BEM 就改成对应正则;declaration-block-no-duplicate-properties抓同一块里重复声明的属性,这是复制粘贴最容易留下的问题。no-descending-specificity在大型项目里误报率偏高,我这里直接关了,它不是没用,而是维护成本大于收益,属于该舍弃的那类规则。

注意:三份配置一定要放进共享 npm 包或 monorepo 的公共目录,各项目 extends,不要在十几个仓库里各抄一份,否则半年后你会发现它们已经长得完全不一样了。

4. 提交信息与 CI:让阿里前端开发规范在流水线上拦截问题

配置写完只解决了"存不存在",不解决"会不会被执行"。真正让规范生效的是三层拦截:本地提交时的钩子、提交信息的格式校验、以及在 CI 上跑一遍保证没人能绕过。少了任何一层,都会有人因为赶需求而git commit -m "fix"一把梭,几周之后仓库历史就变成一锅粥。

4.1 用 commitlint 约束提交信息

# 安装校验工具链 npm install -D husky lint-staged @commitlint/cli @commitlint/config-conventional # 初始化 husky,生成 .husky 目录 npx husky install # 添加 commit-msg 钩子,提交时校验信息格式 npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
// commitlint.config.js module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'chore']], 'subject-max-length': [2, 'always', 72] } };

逻辑说明:type-enum规定提交类型只能从这八种里选,这是 Conventional Commits 的常见集合,feat新功能、fix修复、refactor重构,语义清晰到能自动生成 changelog。subject-max-length限制标题 72 字符,超过这个长度在 git log 单行视图里会被截断。第一个参数2表示 error 级别,1是 warn。$1是 husky 传给脚本的提交信息文件路径,--edit让 commitlint 去读这个文件。这一层挡住的不是格式洁癖,而是"这条改动到底在干嘛"的沟通成本。

4.2 lint-staged 只检查改动文件

{ "lint-staged": { "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"], "*.{css,less,scss}": ["stylelint --fix"], "*.{json,md}": ["prettier --write"] } }

逻辑说明:配置写在package.json里,key 是文件匹配模式,value 是要跑的命令数组,按顺序执行。--fix--write都会自动修掉能修的问题,只有修不了的才报错拦提交。为什么用 lint-staged 而不是全量 lint?老仓库全量跑一遍可能几十秒甚至几分钟,开发体验会崩,只检查暂存区里改动的文件,通常一两秒结束,人愿意等才会一直用。最后别忘了加pre-commit钩子触发它:npx husky add .husky/pre-commit 'npx lint-staged'

4.3 在 CI 里兜住最后一道

#!/usr/bin/env bash # ci-lint.sh:在流水线上运行,任何一步非零退出即中止 set -euo pipefail npm ci # 按 lockfile 精确安装,保证环境一致 npx eslint "src/**/*.{js,jsx,ts,tsx}" # 全量静态检查 npx stylelint "src/**/*.{css,less,scss}"# 样式检查 npx prettier --check "src/**/*" # 只校验格式,不改文件

逻辑说明:set -euo pipefail让脚本遇到错误立即退出,避免 lint 报错但 CI 仍显示绿色的尴尬。npm ci按 lockfile 安装,和本地npm install的结果不一致问题在这里被消掉。prettier --check是关键——本地钩子用--write自动改,CI 上必须用--check只做校验,因为 CI 不应该悄悄改代码。这套脚本是最低配置,配合远端缓存可以把耗时压到合理范围。本地钩子能被--no-verify绕过,CI 不会,所以它才是真正的底线。

提示:CI 里如果发现大量历史文件报错,先别急着全量修,改成只对本次 diff 涉及的文件跑 lint,历史遗留另开任务逐步清理,否则第一个 PR 就会被几百个报错劝退。

5. 规范落地进阶:自定义规则、老项目接入与效果度量

到这一步,标准配置、钩子、CI 都齐了,剩下的是怎么让它适应团队的真实情况。通用规则总有覆盖不到的地方,比如你们团队禁止在业务代码里直接console.log、禁止某个内部模块被随意引用,这些得自己写规则。老项目往往没法一步到位,需要渐进式接入。最后还得有办法判断规范到底有没有起作用,否则推了半天也只是自我感觉良好。

5.1 写一条自定义 ESLint 规则

// eslint-rules/no-console-log.js module.exports = { meta: { type: 'suggestion', docs: { description: '禁止在业务代码中直接使用 console.log' } }, create(context) { return { // 匹配形如 console.log(...) 的成员调用 MemberExpression(node) { const isConsoleLog = node.object.name === 'console' && node.property.name === 'log'; if (isConsoleLog) { context.report({ node, message: '请移除 console.log,改用统一的日志工具提交前清理' }); } } }; } };

逻辑说明:meta.type声明规则类别,suggestion表示建议级,方便后续按类别筛选。create返回一个访问器对象,ESLint 遍历 AST 时遇到MemberExpression节点就调用它,node.object.namenode.property.name分别对应consolelog。要让它生效,还得在插件入口里导出,并在.eslintrcpluginsrules里注册成自定义前缀/no-console-log: 'error'。这条规则只有几十行,但能替你省掉无数次"You should remove console.log before commit"的评审留言,这就是自定义规则的意义——把口头约定变成可复用的判定。

5.2 老项目渐进式接入的三个阶段

第一步是"只加不拦":把 Prettier 装上,对全仓库跑一次prettier --write,单独提一个格式化 PR,先让历史代码干净下来,这个 PR 不掺任何逻辑改动,方便快速过审。第二步是"增量拦截":ESLint 用 lint-staged 只检查改动文件,历史文件的问题不阻塞新提交,同时给规则设 warn 级别,让开发者先看到问题再逐步接受。第三步是"全量收口":等新代码稳定一段时间,把 warn 升为 error,再用脚本按目录一块块清理历史遗留。这个节奏快的团队两三个月能走完,慢的半年也正常。硬推全量报错是最常见的翻车方式,几乎必然导致有人直接关掉 lint。

5.3 用数据判断规范有没有真的生效

指标采集方式期望趋势
提交信息合规率统计 CI 里 commitlint 通过次数逐月上升
lint 报错数CI 日志里 eslint 错误行数缓慢下降
格式化相关 PR 评论检索评审里关键词显著下降
平均修复轮次PR 从提交到合并的往返次数下降

表格里第三条最有说明力:如果评审里"这里缩进不对""加个分号"这类留言明显少了,说明规范和工具真的接上了,人的注意力被释放到了设计层面。反过来,如果 lint 报错数一直不降,多半是规则误报太高,得回头砍规则。度量不是为了考核谁,而是为了判断工具链该往哪调,让规范跟着团队走,而不是让团队迁就一份 PDF。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询