Material UI (MUI Core) 贡献指南:从本地环境搭建到 PR 通过全部 CI 检查

发布时间:2026/9/7 5:35:35
Material UI (MUI Core) 贡献指南:从本地环境搭建到 PR 通过全部 CI 检查 Material UI (MUI Core) 贡献指南从本地环境搭建到 PR 通过全部 CI 检查【免费下载链接】material-uiMaterial UI: Comprehensive React component library that implements Googles Material Design. Free forever.项目地址: https://gitcode.com/GitHub_Trending/ma/material-ui本篇指南基于 MUI 官方仓库根目录的 CONTRIBUTING.md完整覆盖 Material UI 与 MUI System 的贡献流程如何搭建本地文档站与 playground 开发环境、如何规范地提交 PR、如何逐项修复 CI 检查以及如何生成组件 API 文档、为文档新增演示示例和使用尚未发布的包。读完后你将能够独立完成一次从修改源码到合并入master分支的完整贡献闭环。一、贡献体系概览代码只是其中一部分MUI 项目采用 Contributor Covenant 作为行为准则并强调贡献的“宽光谱”编写代码只是贡献的一种形式文档改进与代码变更同等重要。官方建议的流程是——先开 issue 讨论再动手写 PR尤其是较大的改动。针对第一次贡献的开发者官方提供了两类入口good first issue范围有限、且已有可用方案的讨论适合新开发者或新接触该库的贡献者。可在 issue 列表中使用标签检索is:issue is:open label:good first issue。ready to take已经在讨论中至少部分解决、下一步方向明确的问题适合希望降低“踩坑”成本的开发者检索式is:issue is:open label:ready to take。认领 issue 的约定CONTRIBUTING.md先查看评论线程确认是否已有人在修若无人处理留言说明你已开始着手避免重复劳动若某人认领后超过一周无后续可以接手但仍需留言说明issue 若 714 天无活动可视为无人处理。二、标准 PR 流程从 Fork 到 PushPR 应当保持小步快跑一个 PR 不要捆绑多个 feature 或 bug fix与其做一个大 PR不如拆成两个小 PR。标准流程CONTRIBUTING.md# 1. Fork 仓库后克隆你的 fork 并添加 upstream 远程 git clone https://github.com/your username/material-ui.git cd material-ui git remote add upstream https://github.com/mui/material-ui.git # 2. 将本地 master 与上游同步 git checkout master git pull upstream master # 3. 用 pnpm 安装依赖不支持 yarn / npm pnpm install # 4. 创建主题分支 git checkout -b my-topic-branch # 5. 修改、提交并推送到你的 fork git push -u origin HEAD关于“只支持 pnpm”这一点仓库源码中有硬性保障根 package.json 中定义了preinstall: npx only-allow pnpm如果尝试用 npm 或 yarn 安装安装过程会直接失败。推送后在仓库中发起 PR核心团队会持续监控新 PR并以“合并 / 要求修改 / 关闭并说明原因”三种结果回应。分支目标与 master 策略PR 应指向master分支。master的代码必须与最新稳定版保持兼容可以有新 feature但不允许破坏性变更——原则上任何时候都应当能从master的最新提交直接发布一个新的 minor 版本CONTRIBUTING.md。三、本地验证文档站与 Playground 两套环境3.1 文档站维护者日常开发环境文档站本身就用 Material UI 构建包含所有组件的示例是实验改动效果的最佳场所pnpm start对应地根 package.json 中该脚本实际执行pnpm install pnpm docs:dev其中docs:dev由 docs/package.json 中的next dev --turbopack驱动。启动后访问http://localhost:3000对文档的修改会热更新。3.2 Playground 隔离环境在文档站上直接改现有 demo 有三大痛点CONTRIBUTING.md修改现有 demo 无法让你隔离地调试单个组件实例清空页面做隔离实验会让git diff变得很“吵”静态检查器可能报告你并不关心的既有问题。官方方案是 playgroundpnpm docs:create-playground pnpm start访问http://localhost:3000/playground/。从源码看根 package.json 的docs:create-playground会过滤到 docs 包执行其 create-playground 脚本cpy --cwdscripts playground.template.tsx ../pages/playground/ --renameindex.tsx即把 playground 模板文件 复制为docs/pages/playground/index.tsx。要创建更多隔离页面只需把index.tsx复制一份改名为file_name.tsx新页面即可通过http://localhost:3000/playground/file_name访问。四、提高 PR 被接收概率合并前自检清单CI 会在 PR 打开时自动运行一组检查。若不确定能否通过可以先开 PR由界面展示结果汇总再对照下文的修复方法。官方列出的合并前提CONTRIBUTING.md分支层面分支目标为master所有测试通过且符合“随时可发 minor 版本”的兼容性要求分支不能落后于目标分支需要保持与master同步。功能层面新增 feature 时若该能力用核心库现有 API 已经可以实现你需要解释为什么必须进核心库若是常见用法要在文档中补充示例新增或修改功能必须附带测试测试体系详见 test/README.md新增 prop 或修改 prop 类型时必须同步更新 TypeScript 声明提交新组件时组件先加入 packages/mui-lab实验室包而非直接进核心包。代码层面代码已格式化改动过代码则运行pnpm prettier代码已通过 lint运行pnpm eslint类型安全改动过 TypeScript 源码或声明时运行pnpm typescriptAPI 文档为最新改动过 API 时运行pnpm proptypes pnpm docs:apiDemo 为最新改动过 demo 时运行pnpm docs:typescript:formattedPR 标题遵循[product-name][Component] Imperative commit message格式例如[material-ui][Button] Fix loading state handling。这些脚本在仓库中的真实定义根 package.json脚本实际命令pnpm prettierpretty-quick --ignore-path .lintignore --branch masterpnpm eslinteslint . --cache --report-unused-disable-directives --max-warnings 0pnpm typescriptlerna run --no-bail typescriptpnpm proptypestsx ./scripts/generateProptypes.tspnpm docs:api清理旧 api-docs 后执行tsx ./scripts/buildApiDocs/index.tspnpm docs:typescript:formattedtsx ./docs/scripts/formattedTSDemos.mjspnpm test:unitcross-env TZUTC vitestpnpm test:browsercross-env TEST_SCOPEbrowser pnpm test:unit另外两点约定若 PR 解决了某个 issue务必在 PR 描述中使用受支持的 GitHub 关键词如Fixes #xxx关联 issue这样 PR 合并后 issue 会自动关闭若某个步骤遗漏了不要担心CI 会运行完整测试集维护者也会协助排查。五、CI 检查逐项解析与本地修复方法检查失败时点击Details查看构建日志CONTRIBUTING.md 对各检查的说明如下本文补充了对应的本地命令。checkout依赖与 lockfile 的预检。运行pnpm install和pnpm deduplicate可修复大多数问题。test_static检查代码格式并对整个仓库做 lint同时会执行一些会生成或修改文件的命令如pnpm docs:api。因此这类失败最常见的修复方式是本地重跑失败的命令把生成结果提交进 PR。test_unit-1在jsdom环境中跑单元测试。失败时本地pnpm test:unit通常也会失败可用pnpm test:unit --grep ComponentName缩小范围。若本地通过而 CI 失败要考虑可访问性树排除这一差异测试中 a11y 树校验默认在本地被禁用、在 CI 中启用见 test/README.md这往往是 “Unable to find an accessible element with the role” 这类报错的根源本地可设置环境变量CItrue来对齐行为。test_browser通过 Playwright 在多个浏览器中跑单元测试。失败日志会列出是哪个浏览器失败Chrome 失败时本地pnpm test:browser也会失败其他浏览器可用VITEST_BROWSERSfirefox,webkit pnpm test:browser调试。这与 test/README.md 中记录的“vitest browser mode 无头 Chrome/Firefox/WebKit”三端测试方案一致。test_regressions构建回归 fixture 应用Vite并在真实浏览器中跑 Playwright做两类回归截图比对视觉回归与 axe-core可访问性回归。从根 package.json 可见其实现链test:regressions:buildvite buildtest:regressions:runvitesttest:regressions:servervite preview5001 端口并发执行最后还会对docs/data/material/components/**/*.a11y.json跑一次 prettier。若可访问性结果过期本地重跑pnpm test:regressions并提交更新后的文件即可。test_types / test_bundle_size_monitor前者对整个仓库做类型检查日志会列出具体问题本地对应pnpm typescript后者监控 bundle size仅在超过阈值时报错失败通常意味着包或文档的构建方式出了问题。Continuous Releases / argos / deploy/netlify / codecovContinuous Releases把每个 PR 的包发布为 pkg.pr.new 预览包理论上不应单独失败可用于测试复杂场景argos评估test/regressions/tests截到的截图发现差异即失败——但这不必然意味着 PR 会被拒绝变化可能是预期的点开 Details 查看差异即可deploy/netlify成功后渲染一个包含你改动的文档预览失败时本地pnpm docs:build通常也会失败。从源码看文档构建docs/package.json 的build脚本会执行next build 构建 service worker 断链检查reportBrokenLinks.mts这正是 CI 中“Netlify 其他完整性检查”的来源codecov/project监控测试覆盖率覆盖率下降不是致命问题但若能提升总是受欢迎的。六、组件 API 文档的自动生成机制组件 API 文档即文档站各组件页的 API 表格不是手写的而是从 TypeScript 声明文件中的 JSDoc 自动生成。流程更新对应.d.ts文件中的文档例如Button的 packages/mui-material/src/Button/Button.d.ts——每个 prop 的 JSDoc 描述、default标注都会成为 API 文档内容运行pnpm proptypes pnpm docs:api。pnpm proptypes的入口是 scripts/generateProptypes.ts其工作机制值得了解L250-L299它扫描各包源码目录中“目录名与文件名一致”的大驼峰组件文件如Button/Button.d.ts即 generateProptypes.ts 中的 glob 过滤逻辑支持--pattern参数只对匹配的文件做处理通过 TypeScript 语言服务getPropTypesFromFile解析出组件的 props 与 JSDoc并按shouldInclude规则决定哪些 prop 进入文档——外部继承的 prop 默认不展开除非列入了 useExternalDocumentation 白名单如Button的disableRipple、InputBase系列共享的 22 个 prop结果被injectPropTypesInFile注入回组件的 JS/TS 源文件并附上醒目注释L220-L227┌────────────────────────────── Warning ──────────────────────────────┐ │ These PropTypes are generated from the TypeScript type definitions. │ │ To update them, edit the TypeScript types and run pnpm proptypes. │ └─────────────────────────────────────────────────────────────────────┘这解释了“修改 prop 必须同步更新 TypeScript 声明”这条规则的底层原因运行时propTypes与 API 文档同源于类型定义。而pnpm docs:apiscripts/buildApiDocs/index.ts则负责把这些数据整理为文档站消费的 api-docs 文件因此两个命令必须配合使用。七、为文档新增一个演示Demo以 Button 组件为例完整步骤CONTRIBUTING.md1. 添加新的组件文件把新文件放进该组件的演示目录。需要说明的是原文档给出的路径是docs/src/pages/components/buttons/而从当前仓库结构看演示文件实际已迁移到产品化目录 docs/data/material/components/buttons/系统演示在docs/data/system/等对应目录下以SuperButtons.tsx为例命名。2. 编写 demo 代码官方要求演示以 TypeScript.tsx编写创建后运行pnpm docs:typescript:formatted自动生成同样必需的 JavaScript 版本。从 docs/scripts/formattedTSDemos.mjs 的注释可确认其职责“Transpiles TypeScript demos to formatted JavaScript. Can be used to verify that JS and TS demos are equivalent. No introduced change would indicate equivalence.”——即它既负责生成也充当 JS/TS 双版本一致性校验。不熟悉 TypeScript 的贡献者可以先用 JS 写再由核心成员协助迁移。一个真实示例BasicButtons.tsx 演示了 Button 的三种基础变体import Stack from mui/material/Stack; import Button from mui/material/Button; export default function BasicButtons() { return ( Stack spacing{2} directionrow Button varianttextText/Button Button variantcontainedContained/Button Button variantoutlinedOutlined/Button /Stack ); }3. 编辑页面的 Markdown 文件组件目录下的 Markdown 文件当前仓库中为 docs/data/material/components/buttons/buttons.md是文档内容的唯一来源改动会直接反映到站点上。为新 demo 添加小节、描述与{{demo: ...}}注入语句例如### Super buttons To create a super button for a specific use case, add the super prop: {{demo: pages/components/buttons/SuperButtons.js}}真实页面中的写法可对照 buttons.md## Basic button小节紧随{{demo: BasicButtons.js}}注入语句——注意 demo 引用的是JS 文件与“TS 为主、JS 由脚本生成”的规则一致。4. 提交 PR按第二节的流程开 PR。文档类 PR 都会经过编辑审阅计划长期贡献的开发者建议先熟悉官方的写作风格指南可以加快编辑流程。找文档任务可以用 issue 检索is:issue is:open label:docs label:ready to take。八、如何使用尚未发布的改动三种方式CONTRIBUTING.md方式一pkg.pr.new 预览包。每个 PR 都会通过 Continuous Releases 任务发布预览版本从该状态中取得 URL 后把依赖指向它diff --git a/package.json b/package.json index 791a7da1f4..a5db13b414 100644 --- a/package.json b/package.json -61,7 61,7 dependencies: { babel/runtime: ^7.4.4, mui/styled-engine: ^5.0.0-alpha.16, - mui/material: ^5.0.0-alpha.15, mui/material: https://pkg.pr.new/mui/material-ui/mui/materialb0f26aa, mui/system: ^5.0.0-alpha.16,方式二Netlify 文档预览。打开文档的 Netlify 预览把任意 demo 打开到 CodeSandbox 或 StackBlitz文档会自动配置好预览包依赖。方式三本地打包。以mui/material为例任何 npm 包同理$ cd packages/mui-material # 或任意其他 mui 包的路径 $packages/mui-material pnpm build $packages/mui-material cd ./build $packages/mui-material pnpm pack到该包的 build 目录找到mui-material-x.x.x.tar.gz拷贝到目标测试项目中安装$test-project npm i ./path-to-file/mui-material-x.x.x.tar.gz注意如果该包此前已安装重新安装不会反映你的改动。一个快捷修法是运行pnpm build前先在package.json中临时提高版本号。九、路线图与许可证项目未来方向见 Material UI 官方文档站上的 Roadmap 页面可在仓库文档 docs/data/material/discover-more/ 中找到对应页面源文件。最后向仓库提交代码即表示同意你的贡献遵循 MIT 许可证。附贡献者命令速查目的命令安装依赖仅 pnpmpnpm install启动文档站http://localhost:3000pnpm start创建 playgroundpnpm docs:create-playground pnpm start单元测试jsdompnpm test:unit可加--grep ComponentName缩小范围浏览器端测试pnpm test:browserVITEST_BROWSERSfirefox,webkit pnpm test:browser调试指定浏览器视觉/可访问性回归pnpm test:regressions开发模式pnpm test:regressions:devpnpm test:regressions:run格式化 / lint / 类型检查pnpm prettier/pnpm eslint/pnpm typescript重新生成 propTypes 与 API 文档pnpm proptypes pnpm docs:api生成 TS demo 的 JS 版本pnpm docs:typescript:formatted本地构建单个包cd packages/mui-material pnpm build pnpm pack适用前提以上均以当前仓库的 pnpm workspace Lerna Vitest/Playwright 工具链为准命令定义见根 package.json根目录另有 AGENTS.md 与 CLAUDE.md 供 AI 辅助开发参考。【免费下载链接】material-uiMaterial UI: Comprehensive React component library that implements Googles Material Design. Free forever.项目地址: https://gitcode.com/GitHub_Trending/ma/material-ui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考