Electron 代码风格指南:多语言仓库的通用规范、工具链与命名约定
Electron 是一个横跨 C++(Chromium/Node.js 绑定层)、Objective-C++、Python(构建与补丁脚本)、TypeScript/JavaScript(lib/ 下的内置模块与默认应用)、Markdown(API 文档)的多语言大型仓库。为了让跨越几十个子系统的代码保持一致性,Electron 以 docs/development/coding-style.md 为总纲,制定了一套覆盖通用编码习惯、C++/Python 规范、文档写作、JavaScript 语法以及 API 命名约定的风格体系。本文以此为骨架,结合仓库中的实际脚本(script/lint.js、package.json)、规则配置(.oxlintrc.json、.markdownlint-cli2.jsonc)与 API 文档结构,给出可直接落地的规范清单与自检命令,帮助你提交符合 Electron 社区标准的改动。
一句话总览:风格是"规范文档 + 自动化工具"的结合
Electron 的风格要求并不是纸上谈兵——几乎每条规范都有对应的工具在 CI 或 pre-commit 阶段强制执行:
cpplint负责 C++/Objective-C++ 风格检查;oxlint负责 JavaScript/TypeScript 的静态检查;clang-format/oxfmt/gn format分别负责 C++、JS/TS、GN 文件的格式化;markdownlint-cli2与lint-roller系列插件 负责 Markdown 文档的排版与 API 文档结构校验。
仓库根目录的 package.json 中,一条 npm run lint 聚合了全部检查链路。文档中明确指出:直接运行 npm run lint,即可查看 cpplint 与 oxlint 报告的各类风格问题。
通用代码规范:适用于所有语言的底线
coding-style.md 在开篇定义了与语言无关的通用规则,这是所有进入仓库代码的第一道关卡。
以换行符结尾
每个文件必须以一个换行符结尾。这避免了 POSIX 工具解析、diff 合并时出现"missing newline at end of file"问题,也让 git apply、补丁生成等场景更稳定(补丁检查逻辑见 script/lint.js 中对 .patch 文件的尾随空白检查)。
require/import 的排列顺序
CommonJS 时代的规定延续至今,要求 require 语句按以下三类分组排列:
- Node.js 内置模块(如
path、fs) - Electron 内置模块(如
ipc、app) - 本地模块(使用相对路径引用)
在类型检查层,仓库还进一步强制了现代写法:在 build、script、docs、default_app、spec 目录中开启 unicorn/prefer-node-protocol 规则(见 .oxlintrc.json),要求内置模块统一写成 node:fs、node:path 这类带协议前缀的形式,避免与第三方同名包混淆。script/lint.js 对 docs 目录下代码块中的裸内置模块导入同样会报错(见 script/lint.js)。
类成员的排列顺序
类中成员按"静态优先、实例在后"的顺序组织:
- 类方法与静态属性(即方法名前带有
@前缀的装饰器成员,或static成员) - 实例方法与实例属性
这与许多语言规范中"静态成员放在类顶部"的做法一致,便于读者在扫读类定义时先看到不依赖实例的入口。
避免平台相关代码
桌面应用天然要面对 macOS / Windows / Linux 的差异,规范明确要求两条硬性约定:
- 拼接文件路径必须使用
path.join(),禁止手工拼/或\——这保证了在 Windows 上生成正确分隔符; - 需要引用临时目录时必须用
os.tmpdir(),禁止硬编码/tmp——因为 Windows 的临时目录是%TEMP%,而 macOS 则可能是其他系统路径。
这两条同样适用于在 Markdown 文档、测试样例中演示 Node.js 代码的场景。
显式返回时使用裸 return
当需要在函数末尾显式结束流程时,只写 return,不要写 return null、return undefined,也不要直接返回 null 或 undefined。这一约定让"有意结束"与"无返回值"两种语义边界更清晰,也避免在类型推断时引入冗余的 null | undefined。
C++ 与 Python:全面对齐 Chromium 上游风格
Electron 的 shell/ 目录(主进程 C++ 实现)直接依赖 Chromium 的大量抽象与类型,因此其 C++/Python 风格完全跟随 Chromium 的 Coding Style 规范(即 Chromium 官方 styleguide 所定义的缩进、命名、注释与所有权约定)。文档特别建议:若想深入理解 C++ 层的写法,应先熟悉 Chromium 的核心抽象与数据结构文档——其中介绍了一些贯穿 Electron 源码的特殊类型、作用域类型(在超出作用域时自动释放内存的 RAII 封装)、日志机制等。这些模式在 shell/browser/、shell/common/、shell/renderer/ 等目录中随处可见。
当前仓库约定的 Python 版本为 Python 3.9(script/ 下大量构建脚本基于该版本,构建与补丁系统调用 python3 运行)。
在工具层面,文档提到的 script/cpplint.py 由统一入口驱动:script/lint.js 中 C++(.cc/.h)与 Objective-C++(.mm)两条 lint 分支实际执行的是
- 先跑
script/run-clang-format.py(仓库根目录提供 .clang-format 配置)做格式化; - 再调用 depot_tools 中的
cpplint,并传入了经过裁剪的过滤器列表CPPLINT_FILTERS(见 script/lint.js)。
被裁剪的检查项包括 -build/include、-readability/casting、各类 -whitespace/*、-runtime/* 等——它们之所以被关闭,是因为 Electron 的 C++ 层大量使用 Chromium 风格的非标准写法(如自定义的智能指针宏、原生类型别名),若全部开启会产生海量噪声。Objective-C++ 分支还会额外追加 -readability/braces 的放宽(见 script/lint.js)。
对开发者而言,常用的组合命令包括:
# 单独检查 C++(.cc/.h)
npm run lint:cpp
# 单独检查 Objective-C++(.mm)
npm run lint:objc
# 单独检查 Python 脚本(script/ 下 .py)
npm run lint:py
文档:用 markdownlint 与 lint-roller 保证可读性与一致性
Electron 把文档当作代码一样严格审查。规范要求所有文档正文遵循独立的文档风格指南,该指南细化了标题层级、大小写(页面标题用 Title Case,章节用 Sentence Case)、列表符号、代码块语言标识、API 文档固定模板(Methods/Events/Class:/Instance Methods/Instance Properties 等章节的书写格式)以及 API History YAML 块的存放规则。
仓库内可通过 npm run lint:docs 一键校验文档改动格式是否合规。在 package.json 中可以看到,这条命令是一个长长的流水线,依次执行:
lint:js-in-markdown——用 lint-roller 的 markdown-standard 工具,对文档内所有js/ts代码块做 standard 风格 lint;create-typescript-definitions——重新生成 API 类型定义并跑 TS smoke 测试,确保文档与真实 API 对齐;lint:ts-check-js-in-markdown——对文档代码块做 TypeScript 检查;lint:docs-fiddles——对docs/fiddles/下的示例做standard检查;lint:docs-relative-links——校验文档内部相对链接是否存在(防止死链,这也解释了为何文档链接必须以仓库根目录为基准正确书写);lint:markdown与lint:api-history——前者基于markdownlint-cli2按 .markdownlint-cli2.jsonc 的规则(继承自@electron/lint-roller/configs/markdownlint.json)检查全部.md;后者按 docs/api-history.schema.json 校验 API 变更记录块。
script/lint.js 中 Markdown 分支还有几条易踩的硬性约束(见 script/lint.js):
- 代码块语言标识必须全小写;
- 优先用
js/ts作为标识符,而不是javascript/typescript; - 文档代码块若引用了
docs/fiddles/下的真实 fiddle 文件,其内容必须与源文件完全一致(防文档与示例脱节); - 代码块中的 Node 内置模块必须写
node:前缀。
JavaScript / TypeScript:从 standard 到 oxlint 的演进
JavaScript 层(lib/、default_app/、npm/、script/、spec/ 等)要求编写 standard 风格的代码。早期这条规则由 ESLint + standard 插件承载;在本仓库当前版本中,主流检查已迁移到更快的 oxlint(.oxlintrc.json),而 fiddles 与文档内嵌代码块仍通过 @electron/lint-roller 内置的 standard-markdown 保持对 standard 规范的兼容。
核心语法要求包括:
- 文件命名:用
-(kebab-case)连接单词,如file-name.js而非file_name.js。规则源于 Node.js 生态中模块名普遍采用module-name形式(如 npm 包名);该规则只约束.js(及 JS/TS 源文件),在仓库中可观察到lib/browser/api/下的default-menu.ts、ipc-main-impl.ts等文件均遵循此命名。注意代码中大量使用 ES6+ 语法:const与let取代var、箭头函数取代function () { }、模板字符串取代+拼接。
在 .oxlintrc.json 中,这些约定被固化为可执行规则,典型示例:
no-var与prefer-const(destructuring 全开)为error;eqeqeq(always,但对null比较放行)、curly(multi-line)、no-unused-vars、yoda(禁止never)等均强制开启;- 开启了
import/no-duplicates、import/no-absolute-path、import/first等导入规范类规则; - 默认将
correctness大类整体关闭,避免 oxlint 的实验性正确性检查与既定代码产生冲突; - 针对
spec/下的测试代码,加载了两个私有 lint 插件(见 .oxlintrc.json):no-only-tests(禁止.only残留导致 CI 只跑部分用例)与no-floating-spec-helpers。
文件命名与常量风格值得单独强调:
// 符合规范:常量若是原始值,用全大写 + 下划线
const NUMBER_OF_RETRIES = 5;
const DEFAULT_TITLE = 'Electron';
格式化由 oxfmt 统一接管
除 lint 外,仓库用 oxfmt 做 JS/TS/MJS/CJS 的格式化:
# 只检查不修改
npm run lint:fmt
# 直接写入修正
npm run format
format 脚本(见 package.json)覆盖 {lib,spec,script,build,default_app,npm,typings} 等目录下的 *.{js,ts,mjs,cjs} 文件。同时 lint-staged(package.json)会在 pre-commit 时对暂存的 .js/.ts 自动执行 script/lint.js --js --fix --only 与 oxfmt --write,从源头消灭格式分叉。
命名规范:与 Node.js 一致的大小写策略
Electron API 的命名沿用 Node.js 的大小写体系,共四档(coding-style.md 原文):
- 模块本身是类:用
PascalCase。典型代表是窗口类BrowserWindow,对应文档 docs/api/browser-window.md; - 模块是一组 API:用
camelCase。如全局快捷键模块globalShortcut,对应 docs/api/global-shortcut.md;同理还有app、session、dialog等单复数混合风格模块; - API 是某对象的属性且足够复杂、可独立成章:用
mixedCase,如win.webContents(它是BrowserWindow实例上承载页面控制能力的复合对象,可参考 docs/api/web-contents.md 中对webContents的完整章节化描述); - 其他非模块 API:使用自然语言标题,如
<webview>标签(见 docs/api/webview-tag.md)或Process对象(见 docs/api/process.md)。
这套大小写约定同时外溢到文档文件名:docs/api/ 下每个文档都以小写 kebab-case 命名(browser-window.md、global-shortcut.md),与模块自身的导出名错开,读者可凭大小写快速区分"文件"与"标识符"。
方法 API 优先 getter/setter 而非 jQuery 风格
设计新 API 时,Electron 倾向使用成对的 getter/setter 代替 jQuery 式"一函数多用"写法。例如:
- 推荐
.getText()与.setText(text); - 不推荐
.text([text])(参数可选时读、传入时写)。
这一偏好背后有现实工程原因:单函数带可选参数会让类型签名含糊,调用方无法静态确定是读还是写,且对 undefined 这类合法值的处理存在歧义。仓库在规则层面也配套了约束:.oxlintrc.json 将 accessor-pairs 设为 error 且 setWithoutGet: true、enforceForClassMembers: true,确保类中写了 setter 必须配套 getter(见 .oxlintrc.json),从机制上鼓励成对设计。
收尾自查:提交前跑一遍全量流水线
风格文档的意义最终要落到可重复执行的检查上。综合 coding-style.md、style-guide.md 与 script/lint.js 的解析结果,可整理出一套提交前的自检流程:
# 1. 全量检查(等价于依次执行 cpp/objc/js/python/gn/patches/markdown 七个 linter,
# 以及 lint:fmt + lint:docs + lint:chromium-roller,见 package.json)
npm run lint
# 2. 只想检查自己改动过的文件(基于 git 暂存区)
node ./script/lint.js -c
# 3. 只想检查指定文件,并允许自动修复
node ./script/lint.js --js --fix --only -- lib/browser/foo.js
script/lint.js 支持的语言开关(默认全开)为:--cpp、--objc、--javascript(别名 --js)、--python、--gn、--patches、--markdown;其中 --gn 分支以 gn format --dry-run 校验 GN 构建文件的排版,--patches 分支校验 patches/ 下每个 .patch 文件是否在 patches/config.json 描述的目录与 .patches 清单中登记,且每条补丁必须附带"为什么存在、如何移除"的说明。
最后提醒三点容易忽略的细节:所有源文件与 Markdown 必须以换行符结尾;.js/.ts 文件名必须用连字符命名;新增 API 一律参考 docs/development/style-guide.md 中规定的模板格式写文档,并保证文档代码块的 Node 内置模块使用 node: 前缀。规范解决的是"仓库越大越难保持一致"的问题——当每个文件都长得像同一个人写的,代码审查的重点就能从风格争论回到真正的逻辑正确性上。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00