Turborepo简易教程
参考官网:https://turbo.build/repo/docs
开始
安装全新的项目
pnpm dlx create-turbo@latest
测试应用包含:
- 两个可部署的应用
- 三个共享库
运行:
pnpm install
pnpm dev
会启动两个应用web(http://localhost:3000/)、docs(http://localhost:3001/)。
可以看到,两个应用都依赖了packages下的ui组件。
安装到已有项目中
按官方的说法,Turborepo可以安装到所有类型的应用中,不仅仅是multirepo,还有singlerepo。
安装turbo
官方建议是同时安装到全局和应用中
# Global install
pnpm add turbo --global
# Install in repository
pnpm add turbo --save-dev
新增一个turbo.json
文件
# 示例应用中的json
{"$schema": "https://turbo.build/schema.json","globalDependencies": ["**/.env.*local"],"pipeline": {"build": {"dependsOn": ["^build"],"outputs": [".next/**", "!.next/cache/**"]},"lint": {"dependsOn": ["^lint"]},"dev": {"cache": false,"persistent": true}}
}
编辑.gitignore
+ .turbo
初始化仓库
下面以monorepo为例。
目录结构:
最低要求
包管理
官方推荐apps目录下存放应用,packages目录下存放公共库或者工具类。
packages:- "apps/*"- "packages/*"
monorepo用pnpm比较好,所以只贴了pnpm的例子,如果要看yarn的,可以看Structuring a repository | Turborepo
使用此配置,apps或packages目录中包含package.json的每个目录都将被视为一个包。
Turborepo不支持嵌套,例如apps/或者packages/。
如果一定要嵌套,可以配置为packages/和packages/group/,然后不要创建packages/group/package.json文件
根目录package.json
示例:
{"private": true,"scripts": {"build": "turbo run build","dev": "turbo run dev","lint": "turbo run lint"},"devDependencies": {"turbo": "latest"},"packageManager": "pnpm@9.0.0"
}
packageManager不可少,否则报错。
根目录turbo.json
turbo.json用于配置turbo的行为。
lockfile
例如pnpm-lock.yaml
,这是复用缓存的关键。
依赖管理
依赖分为外部依赖和内部依赖。
{"dependencies": {"next": "latest", // External dependency"@repo/ui": "workspace:*" // Internal dependency}
}
创建一个内部包示例
在packages中新建math目录,作为公共仓库。
创建package.json
{"name": "@repo/math","type": "module","scripts": {"dev": "tsc --watch","build": "tsc"},"exports": {"./add": {"types": "./src/add.ts","default": "./dist/add.js",},"./subtract": {"types": "./src/subtract.ts","default": "./dist/subtract.js",},},"devDependencies": {"@repo/typescript-config": "workspace:*","typescript": "latest"}
}
exports: 为包定义多个入口点,以便可以在其他包中使用。import { add } from '@repo/math'
Turborepo会将@repo/math识别为@repo/typescript-config的依赖项,用于对任务进行排序。
添加tsconfig.json
,使用extends关键字继承公共配置:
{"extends": "@repo/typescript-config/base.json","compilerOptions": {"outDir": "dist","rootDir": "src"},"include": ["src"],"exclude": ["node_modules", "dist"]
}
在src中编写源码:
./packages/math/src/add.ts
export const add = (a: number, b: number) => a + b;
./packages/math/src/subtract.ts
export const subtract = (a: number, b: number) => a - b;
最后在应用中使用该库:
apps/web/package.json
"dependencies": {
+ "@repo/math": "workspace:*","next": "latest","react": "latest","react-dom": "latest"
},
apps/web/src/app/page.tsx
import { add } from '@repo/math/add';function Page() {return <div>{add(1, 2)}</div>;
}export default Page;
在turbo.json
中添加编译缓存"dist/**"
,这样以后编译时就可以跳过math的编译:
{
"tasks": {"build": {"dependsOn": ["^build"],"outputs": [".next/**", "!.next/cache/**", "dist/**"]},
}
任务配置
定义tasks
tasks中每个key都是一个会被turbo run
执行的任务。Turborepo会在每个package.json
中查找同名脚本来执行。
例如一个最基础的task,不包含dependencies和outputs:
{"tasks": {"build": {} // Incorrect!}
}
使用该配置,turbo将不会使用缓存,导致每次构建时间都很长。
指定tasks顺序
dependsOn
用于指定在另一个任务开始运行之前必须完成的任务。
假如你需要在应用编译前先执行公共仓库的构建,可以这样配置:
{"tasks": {"build": {"dependsOn": ["^build"] }}
}
依赖^
的任务
^
告诉Turbo从依赖树的最底层开始构建。
假如你的应用依赖了一个仓库ui
且这个ui
有一个build
脚本,那么这个build
脚本会先执行。一旦这个ui
的build
任务执行完毕,应用的build
就会立即执行。
依赖同一个package中的任务
假如在当前应用中,你想在执行test
前先执行build
任务,test
需要定义dependsOn
为build
。(没有^
!)
{"tasks": {"test": {"dependsOn": ["build"] }}
}
依赖特定包中的任务
有时你可能需要依赖特定包中的任务。
例如在所有lint
任务执行前先执行util
库中的build
任务:
{"tasks": {"lint": {"dependsOn": ["utils#build"] }}
}
还可以更具体地说明相关任务,将其限制为某个包:
{"tasks": {"web#lint": {"dependsOn": ["utils#build"] }}
}
使用此配置,web包中的lint任务只能在utils包中的构建任务完成后运行。
无依赖
在这种情况下,可以省略dependsOn键或提供一个空数组。
{"tasks": {"spell-check": {"dependsOn": [] }}
}
定义outputs
outputs告诉Turborepo在任务成功完成后应该缓存的文件和目录。如果不配,就不会使用缓存。
{"tasks": {"build": {"outputs": ["dist/**"] }}
}
定义inputs
inputs用于指定要包含在任务哈希中以进行缓存的文件。默认情况下,Turborepo将包含Git跟踪的包中的所有文件。但是,您可以使用inputs键来更具体地确定哪些文件包含在散列中。
例如,在Markdown文件中查找拼写错误的任务可以这样定义:
{"tasks": {"spell-check": {"inputs": ["**/*.md", "**/*.mdx"] }}
}
这样的话只有md文件的变更才会让turbo不使用缓存。
高级用例
有副作用的任务
有些任务无论如何都应该运行,比如在缓存构建之后运行部署脚本。可以使用"cache": false
:
{"tasks": {"deploy": {"dependsOn": ["^build"],"cache": false},"build": {"outputs": ["dist/**"]}}
}
相关文章:

Turborepo简易教程
参考官网:https://turbo.build/repo/docs 开始 安装全新的项目 pnpm dlx create-turbolatest测试应用包含: 两个可部署的应用三个共享库 运行: pnpm install pnpm dev会启动两个应用web(http://localhost:3000/)、docs(http://localhost…...

初中物理知识点总结(人教版)
初中物理知识点大全 声现象知识归纳 1 .声音的发生:由物体的振动而产生。振动停止,发声也停止。 2.声音的传播:声音靠介质传播。真空不能传声。通常我们听到的声音是靠空气传来的。 3.声速:在空气中传播速度是:340…...
ChatGPT-4o大语言模型优化、本地私有化部署、从0-1搭建、智能体构建等高级进阶
目录 第一章 ChatGPT-4o使用进阶 第二章 大语言模型原理详解 第三章 大语言模型优化 第四章 开源大语言模型及本地部署 第五章 从0到1搭建第一个大语言模型 第六章 智能体(Agent)构建 第七章 大语言模型发展趋势 第八章 总结与答疑讨论 更多应用…...

【开源项目】LocalSend 局域网文件传输工具
【开源项目】LocalSend 局域网文件传输工具 一个免费、开源、跨平台的局域网传输工具 LocalSend 简介 LocalSend 是一个免费的开源跨平台的应用程序,允许用户在不需要互联网连接的情况下,通过本地网络安全地与附近设备共享文件和消息。 项目地址&…...
ARM/Linux嵌入式面经(十一):地平线嵌入式实习
地平线嵌入式实习面经 1.自我介绍 等着,在给大哥们准备了。 2.spi与iic协议可以连接多个设备吗?最多多少个?通讯时序。 这是几个问题,在回答的时候。不要一问就开口,花几秒钟沉吟思考整理一下自己的思路。 这个问题问了几个点?每个点的回答步骤。 是我的话,我会采用以…...

基于Redis的分布式锁
分布式场景下并发安全问题的引发 前面通过加锁解决了单机状态下一人一单的问题,但是当出现了分布式,前面的加锁形式不再适用 ,每个jvm有一个自己的锁监视器,只能被内部线程获取,其他jvm无法使用,那么多台j…...

如何将 Apifox 的自动化测试与 Jenkins 集成?
CI/CD (持续集成/持续交付) 在 API 测试 中的主要目的是为了自动化 API 的验证流程,确保 API 发布到生产环境前的可用性。通过持续集成,我们可以在 API 定义变更时自动执行功能测试,以及时发现潜在问题。 Apifox 支持…...

【FFmpeg】av_write_frame函数
目录 1.av_write_frame1.1 写入pkt(write_packets_common)1.1.1 检查pkt的信息(check_packet)1.1.2 准备输入的pkt(prepare_input_packet)1.1.3 检查码流(check_bitstream)1.1.4 写入…...

【算法专题】双指针算法
1. 移动零 题目分析 对于这类数组分块的问题,我们应该首先想到用双指针的思路来进行处理,因为数组可以通过下标进行访问,所以说我们不用真的定义指针,用下标即可。比如本题就要求将数组划分为零区域和非零区域,我们不…...

Lock与ReentrantLock
在 Java 中,Lock 接口和 ReentrantLock 类提供了比使用 synchronized 方法和代码块更广泛的锁定机制。 简单示例: import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {pr…...
ARM/Linux嵌入式面经(十三):紫光同芯嵌入式
static关键字 static关键字一文搞懂这个知识点,真的是喜欢考!!! stm32启动时如何配置栈的地址 在STM32启动时配置栈的地址是一个关键步骤,这通常是在启动文件(如startup_stm32fxxx.s,其中xxx代表具体的STM32型号)中完成的。 面试者回答: STM32启动时配置栈的地址主…...
名企面试必问30题(二十四)—— 说说你空窗期做了什么?
回答示例一 在空窗期这段时间,我主要进行了两方面的活动。 一方面,我持续提升自己的专业技能。我系统地学习了最新的软件测试理论和方法,深入研究了自动化测试工具和框架,例如 Selenium、Appium 等,并通过在线课程和实…...
基础权限储存
一、要求: 1、建立用户组shengcan,其id为2000工 2、建立用户组 caiwu,其id为2001 3、建立用户组 jishu,其id 为 2002 4、建立目录/sc,此目录是 shengchan 部门的存储目录,只能被 shengchan 组的成员操作,其他用户没有…...
Could not find a package configuration file provided by “roscpp“ 的参考解决方法
文章目录 写在前面一、问题描述二、解决方法参考链接 写在前面 自己的测试环境: Ubuntu20.04 ROS-Noetic 一、问题描述 编译程序时出现如下报错: -- Could NOT find roscpp (missing: roscpp_DIR) -- Could not find the required component roscpp.…...

运维系列.Nginx配置中的高级指令和流程控制
运维专题 Nginx配置中的高级指令和流程控制 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/…...
Virtualbox和ubuntu之间的关系
1、什么是ubuntu Ubuntu 是一个类似于 Windows 的操作系统,但它是基于 Linux 内核开发的开源操作系统 2、什么是Virtualbox VirtualBox 是一款虚拟机软件,使我们可以物理机上创建和运行虚拟机 也就是说,VirtualBox 提供了一个可以安装和运行其他操作系…...

【在Linux世界中追寻伟大的One Piece】HTTPS协议原理
目录 1 -> HTTPS是什么? 2 -> 相关概念 2.1 -> 什么是"加密" 2.2 -> 为什么要加密 2.3 -> 常见的加密方式 2.4 -> 数据摘要 && 数据指纹 2.5 -> 数字签名 3 -> HTTPS的工作过程 3.1 -> 只使用对称加密 3.2 …...

【WebRTC实现点对点视频通话】
介绍 WebRTC (Web Real-Time Communications) 是一个实时通讯技术,也是实时音视频技术的标准和框架。简单来说WebRTC是一个集大成的实时音视频技术集,包含了各种客户端api、音视频编/解码lib、流媒体传输协议、回声消除、安全传输等。对于开发者来说可以…...

【Unity】RPG2D龙城纷争(八)寻路系统
更新日期:2024年7月4日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、寻路系统二、寻路规则(角色移动)三、寻路规则(角色攻击)四、角色移动寻路1.自定义寻路规则2.寻…...

C++ 函数高级——函数重载——基本语法
作用:函数名可以相同,提高复用性 函数重载满足条件: 1.同一个作用域下 2.函数名称相同 3.函数参数类型不同 或者 个数不同 或者 顺序不同 注意:函数的返回值不可以作为函数重载的条件 示例: 运行结果:...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...