格式化
Rstack CLI 提供了基于 Prettier 的格式化工具。相比直接使用 Prettier,rs fmt 的性能更好,主要得益于以下两点:
- 并行格式化:通过 worker 池并行格式化文件。
- Yuku 解析器:默认使用高性能的 Yuku 解析器处理 JavaScript、JSX 和 TypeScript 文件。
- 持久化缓存:基于文件内容缓存结果,后续运行可以跳过未变化文件的格式化。
rs fmt 兼容 Prettier 的选项和插件,并提供更多内置能力,例如支持排序 package.json 字段。
基本用法
直接运行 rs fmt,即可格式化当前目录中的文件并保存修改:
使用 --check 检查文件是否已格式化,而不修改文件:
更多命令行选项请参考 rs fmt CLI 文档。
配置
在 rstack.config.ts 中使用 define.fmt() 设置格式化规则。它支持所有的 Prettier 选项:
除了 Prettier 选项和 overrides,Rstack 还提供两个选项:
ignorePatterns:使用兼容 Gitignore 的模式排除文件。sortPackageJson:对package.json中的字段排序,默认值为false。
rs fmt 不会自动加载 Prettier 配置文件、.prettierignore 或 .editorconfig。请在 define.fmt() 中设置格式化选项和额外的忽略规则。如需显式加载 ignore 文件,请使用 --ignore-path。
格式化范围
rs fmt 根据命令行中传入的路径确定格式化范围。以下输入可以组合使用:
- 文件:只格式化指定文件。
- 目录:递归扫描目录并格式化支持的文件。
- glob 模式:匹配多个路径,并通过以
!开头的模式排除匹配结果。
不传入路径时,rs fmt 默认格式化当前目录。所有 glob 模式都基于当前工作目录解析。请为 glob 添加引号,避免它们被 shell 提前展开:
扫描目录或 glob 时,rs fmt 会遵循 .gitignore 规则、跳过二进制文件,并且不会遍历版本控制目录或 node_modules。Prettier 无法推断解析器的文件也会被跳过。
.gitignore 只在扫描目录和 glob 时生效,不会排除命令行中显式传入的文件。如果需要始终排除某个文件,请使用 ignorePatterns。
忽略文件
使用 ignorePatterns 排除不需要格式化的文件:
这些模式遵循 Gitignore 语法,并且基于 Rstack 配置文件所在的目录解析。由于规则会在确定格式化范围后生效,因此也会排除命令行中显式传入的文件。
Lock 文件
rs fmt 默认忽略常见的 lock 文件,包括 package-lock.json 和 pnpm-lock.yaml。
如果你需要格式化这些文件,可以使用否定模式主动包含它们:
忽略顺序
rs fmt 会通过以下三个步骤,决定需要格式化哪些路径:
- 处理命令行参数和
.gitignore:首先处理命令行中指定的文件、目录和 glob 模式。以!开头的 glob 模式用于排除路径。扫描目录或 glob 模式时会遵循.gitignore,直接指定的文件则不会。在这一步被排除的路径无法被后续规则重新包含。 - 应用默认忽略规则和
ignorePatterns:默认忽略 lock 文件,随后应用ignorePatterns。这些规则按顺序匹配,后面的规则优先。例如,!pnpm-lock.yaml可以重新包含默认忽略的文件。 - 应用
--ignore-path指定的文件:每个 ignore 文件单独匹配,同一文件中后面的规则优先。不同 ignore 文件与ignorePatterns的排除结果会叠加:只要任一来源忽略某个路径,该路径就会保持排除,即使其他来源尝试重新包含它。
即使命令行直接指定了某个文件,默认忽略规则、
ignorePatterns和--ignore-path中的规则仍然有效。通过--stdin-filepath指定的路径也是如此。
排序 package.json 字段
启用 sortPackageJson 后,rs fmt 会使用 sort-package-json 对每个待格式化的 package.json 中的字段排序:
覆盖配置
通过 overrides 字段,可以为特定文件单独设置格式化选项。每一项都支持以下字段:
files:需要应用格式化选项的文件或 glob 模式。options:应用于匹配文件的格式化选项。excludeFiles:可选,需要从匹配结果中排除的文件或 glob 模式。
模式匹配
files 和 excludeFiles 模式都基于 Rstack 配置文件所在目录解析。
在 files 中,不包含 / 的模式会匹配任意深度的文件名,包含 / 的模式则匹配相对路径。下面示例中的 *.md 会匹配任意目录中的 Markdown 文件,而 scripts/**/*.js 会匹配相对于 Rstack 配置文件所在目录的路径:
合并顺序
如果同一文件匹配多条 override 规则,Rstack 会按声明顺序合并配置,后面的值优先。下面的 README.md 会同时匹配两条规则,因此最终的 printWidth 为 80:
缓存
rs fmt 默认会在基于文件的 --write、--check 和 --list-different 调用中使用持久化缓存。缓存条目基于文件内容和最终格式化选项;任意一项发生变化时,文件都会重新格式化。使用自定义 Prettier 插件的文件目前会绕过缓存。
默认缓存目录位于 Rstack 配置根目录下的 .rstack/cache/fmt。从子目录运行命令时,仍会使用解析到的 rstack.config.* 文件旁的缓存。stdin 格式化不会使用该缓存。
使用 --no-cache 可以在运行时跳过缓存读取、创建和更新:
可以安全删除 .rstack/cache 来清理缓存结果。不要将整个 .rstack 目录视为可随意删除的内容,因为其中还可能包含用户维护的 Git hook 脚本。
Prettier 插件
如果需要使用 Rstack 未内置的格式化能力,可以安装相应的 Prettier 插件,并添加到 plugins 中。插件支持通过包名、文件路径或 URL 引用,其中包名和相对路径基于 Rstack 配置文件所在的目录解析。
由于 rs fmt 会在 worker 中加载插件,因此不支持直接传入插件对象。请通过包名、路径或 URL 引用插件。例如,安装并启用 prettier-plugin-tailwindcss:
如果只需要为特定文件启用插件,可以在 overrides 的 options 中配置 plugins。