
简介这是一份面向前端工程师、前端团队负责人及技术新人的开发规范文档聚焦多人协作中命名混乱、代码风格不统一、样式污染等常见问题。内容依托阿里巴巴集团内部前端实践系统梳理了命名、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 命名、注释、目录约定为什么还得靠文档格式化规则能自动修但这个工具函数该叫什么机器给不出有意义的答案。命名承载的是语义判断标准依赖业务上下文——formatDate和toDisplayTime哪个更清楚只有了解调用方的人才知道。注释同理规范里反复强调注释解释为什么而不是做什么这句话本身就是给评审者看的判据lint 顶多检查有没有注释、格式对不对判断不了内容质量。目录约定更典型features/还是modules/、公共组件放哪一层涉及的是整个团队的认知模型写进文档的目的不是约束机器而是让新人在没有老人带的情况下也能猜对文件位置。这一层的关键是写得短、给例子、配一张目录树别写成三千字散文否则没人翻。2.2 能交给 lint 判定的条目就别留在评审清单反过来说凡是能自动判的就绝对不该占用人的注意力。下面这张表是我通常用来做条目归类的思路左边是规范里常见的说法右边是它该落到哪个工具上。规范条目判定方式落地工具统一使用单引号、行尾分号格式Prettier禁止使用var优先const静态规则ESLint变量名小驼峰、常量全大写命名规则ESLintcamelcase 等组件文件大驼峰、目录小写中划线文件命名脚本或自定义 lint样式类名禁止下划线与大写样式规则Stylelint提交信息遵循类型前缀提交校验commitlint组件职责单一、目录分层合理人工判断评审清单这张表的用法是上线前先对照它整理一遍规范文档把右边有工具的那几行从评审必查项里删掉。评审清单瘦下来之后大家才会认真看剩下的部分。我见过太多团队把格式化要求和架构原则并列写进 checklist最后评审者两头都草草扫过。2.3 从规范条目到工具选型的取舍工具不是越多越好。ESLint、Prettier、Stylelint 三个是前端主流组合覆盖 JS/TS、样式、格式化三块。但如果项目是纯 TS CSS-in-JSStylelint 的价值就有限可以省掉如果团队用的是 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-var、eqeqeq这类是硬错误用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 又容易在分屏时读不下singleQuote和semi决定引号与分号风格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.name和node.property.name分别对应console和log。要让它生效还得在插件入口里导出并在.eslintrc的plugins和rules里注册成自定义前缀/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。本文还有配套的精品资源点击获取