代码生成
将你的单仓库拆分成独立的工作区是组织代码、加速任务和改善本地开发体验的好方法。借助 Turborepo 的代码生成功能,可以轻松地以结构化的方式生成用于包、模块甚至单个 UI 组件的新源代码,这些代码与你的仓库的其余部分集成在一起。
添加空工作区
向你的单仓库添加一个新的空应用或包。
turbo gen workspace
查看所有可用的 选项 用于 gen workspace
。
复制现有工作区
你可以使用现有工作区作为新应用或包的模板。这适用于现有单仓库中的工作区,也适用于来自其他仓库的远程工作区(通过 GitHub URL 指定)。
示例
通过复制仓库中现有工作区来在你的单仓库中创建一个新的工作区。
turbo gen workspace --copy
通过复制远程工作区来在你的单仓库中创建一个新的工作区。
turbo gen workspace --copy https://github.com/vercel/turbo/tree/main/examples/with-tailwind/packages/tailwind-config
注意:从远程源添加时,Turborepo 无法验证你的仓库是否具有所有必需的依赖项,以及是否使用正确的包管理器。在这种情况下,可能需要进行一些手动修改才能使新工作区在你的仓库中按预期工作。
查看所有可用的 选项 用于 gen workspace --copy
。
自定义生成器
如果内置生成器不符合你的需求,可以使用 Plop (在新标签页打开) 配置来创建自己的自定义生成器。Turborepo 会自动检测你的仓库中的任何生成器配置,并使其可供从命令行运行。
注意:虽然 Turborepo 生成器构建在 Plop 之上,但它们不需要在你的仓库中安装 plop
作为依赖项。
虽然 Turborepo 理解所有 Plop 配置选项和功能,但它提供了一些额外的功能来改善在使用 Turborepo 配置的仓库中编写生成器的体验。
- 生成器会自动发现、加载和按工作区组织(无需在单个配置文件中手动
load
它们) - 生成器会自动从定义它们的 workspace 的根目录运行
- 生成器可以从你的仓库中的任何位置调用(或者通过
--root
标志从仓库外部调用) - Typescript 生成器支持零配置
plop
不需要安装为你的仓库的依赖项
注意:ESM 依赖项目前在自定义生成器中不受支持
入门
要构建和运行自定义生成器,请使用 Turborepo 从你的单仓库中的任何位置运行以下命令。
turbo gen
系统会提示你选择一个现有的生成器,或者如果你还没有生成器,则创建一个新的生成器。你也可以在你的仓库的根目录(或任何工作区)中的 turbo/generators/config.ts
(或 config.js
)中手动创建你的配置。
注意:如果您使用的是 Typescript,则需要安装 @turbo/gen
(在新标签页中打开) 包作为 devDependency
以访问所需的 TS 类型。
例如,以下示例说明了一个包含三个生成器配置的单仓库项目。
- root
- apps/web
- packages/ui
├── package.json
├── turbo.json
├── README.md
├── apps
│ └── web
│ ├── package.json
│ └── turbo
│ └── generators
│ ├── config.ts
│ └── templates
├── packages
│ └── ui
│ ├── package.json
│ └── turbo
│ └── generators
│ ├── config.ts
│ └── templates
├── turbo
│ └── generators
│ ├── config.ts
│ └── templates
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
在工作区内创建的生成器会自动从工作区根目录运行,而不是从仓库根目录或生成器配置的位置运行。
这使得您的生成器更容易编写。在 [workspace-root]
创建一个文件只需要指定为 <file>
,而不是 ../../<file>
。
了解更多关于 使用 Plop 创建自定义生成器 (在新标签页中打开)。
编写生成器
生成器配置文件是一个函数,它返回一个 Plop (在新标签页中打开) 配置对象。配置对象用于定义生成器的提示和操作。
在最简单的形式中,生成器配置文件看起来像
import type { PlopTypes } from "@turbo/gen";
export default function generator(plop: PlopTypes.NodePlopAPI): void {
// create a generator
plop.setGenerator("Generator name", {
description: "Generator description",
// gather information from the user
prompts: [
...
],
// perform actions based on the prompts
actions: [
...
],
});
}
提示
提示使用 Plop 提示 (在新标签页中打开) 编写,用于从用户那里收集信息。
操作
操作可以使用 内置的 Plop 操作 (在新标签页中打开),或者 您自己定义的自定义操作函数 (在新标签页中打开)
import type { PlopTypes } from "@turbo/gen";
const customAction: PlopTypes.CustomActionFunction = async (answers) => {
// fetch data from a remote API
const results = await fetchRemoteData();
// add the response to the answers, making this data available to actions
answers.results = results;
// return a status string
return 'Finished data fetching!';
}
export default function generator(plop: PlopTypes.NodePlopAPI): void {
// create a generator
plop.setGenerator("Generator name", {
description: "Generator description",
prompts: [
...
],
actions: [
customAction
{/* actions now have access to `answers.results` */}
...
],
});
}
运行生成器
创建生成器配置文件后,您可以跳过选择提示,并直接使用以下命令运行指定的生成器:
turbo gen [generator-name]
也可以使用 --args
将参数直接传递给生成器提示。
turbo gen [generator-name] --args answer1 answer2 ...
有关更多信息,请参阅 Plop 文档中的 跳过提示 (在新标签页中打开)。
查看 gen
的所有可用 选项。
示例
vercel/turbo (在新标签页中打开) 单仓库项目包含多个用于我们自身开发的自定义 Turborepo 生成器。
- 创建一篇新的博客文章 (在新标签页中打开) - 创建一个新的发布 博客文章,其中包含从 NPM 和 Github API 获取的实时统计数据。
- 创建新的代码转换 (在新标签页中打开) - 为
@turbo/codemod
(在新标签页中打开) 创建新的代码转换,包括所有样板代码和测试。
Turborepo 示例