news 2026/9/27 11:20:53

turborepo-caching - SKILL

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
turborepo-caching - SKILL

name: turborepo-caching
description: “Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.”
risk: critical
source: community
date_added: “2026-02-27”

Turborepo 缓存

Turborepo 构建优化的生产模式。

不要使用本技能的情况

  • 任务与 turborepo 缓存无关
  • 您需要此范围之外的不同领域或工具

说明

  • 澄清目标、约束和所需的输入。
  • 应用相关的最佳实践并验证结果。
  • 提供可操作的步骤和验证方法。
  • 如果需要详细示例,请打开resources/implementation-playbook.md。

何时使用本技能

  • 设置新的 Turborepo 项目
  • 配置构建流水线
  • 实现远程缓存
  • 优化 CI/CD 性能
  • 从其他 monorepo 工具迁移
  • 调试缓存未命中

核心概念

1. Turborepo 架构

Workspace Root/ ├── apps/ │ ├── web/ │ │ └── package.json │ └── docs/ │ └── package.json ├── packages/ │ ├── ui/ │ │ └── package.json │ └── config/ │ └── package.json ├── turbo.json └── package.json

2. 流水线概念

概念描述
dependsOn必须先完成的任务
cache是否缓存输出
outputs要缓存的文件
inputs影响缓存键的文件
persistent长时间运行的任务(开发服务器)

模板

模板 1:turbo.json 配置

{"$schema":"https://turbo.build/schema.json","globalDependencies":[".env",".env.local"],"globalEnv":["NODE_ENV","VERCEL_URL"],"pipeline":{"build":{"dependsOn":["^build"],"outputs":["dist/**",".next/**","!.next/cache/**"],"env":["API_URL","NEXT_PUBLIC_*"]},"test":{"dependsOn":["build"],"outputs":["coverage/**"],"inputs":["src/**/*.tsx","src/**/*.ts","test/**/*.ts"]},"lint":{"outputs":[],"cache":true},"typecheck":{"dependsOn":["^build"],"outputs":[]},"dev":{"cache":false,"persistent":true},"clean":{"cache":false}}}

模板 2:包特定的流水线

// apps/web/turbo.json{"$schema":"https://turbo.build/schema.json","extends":["//"],"pipeline":{"build":{"outputs":[".next/**","!.next/cache/**"],"env":["NEXT_PUBLIC_API_URL","NEXT_PUBLIC_ANALYTICS_ID"]},"test":{"outputs":["coverage/**"],"inputs":["src/**","tests/**","jest.config.js"]}}}

模板 3:使用 Vercel 的远程缓存

# Login to Vercelnpx turbo login# Link to Vercel projectnpx turbolink# Run with remote cacheturbo build --remote-only# CI environment variablesTURBO_TOKEN=your-tokenTURBO_TEAM=your-team
# .github/workflows/ci.ymlname:CIon:push:branches:[main]pull_request:env:TURBO_TOKEN:${{secrets.TURBO_TOKEN}}TURBO_TEAM:${{vars.TURBO_TEAM}}jobs:build:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v4-uses:actions/setup-node@v4with:node-version:20cache:'npm'-name:Install dependenciesrun:npm ci-name:Buildrun:npx turbo build--filter='...[origin/main]'-name:Testrun:npx turbo test--filter='...[origin/main]'

模板 4:自托管远程缓存

// Custom remote cache server (Express)importexpressfrom'express';import{createReadStream,createWriteStream}from'fs';import{mkdir}from'fs/promises';import{join}from'path';constapp=express();constCACHE_DIR='./cache';// Get artifactapp.get('/v8/artifacts/:hash',async(req,res)=>{const{hash}=req.params;constteam=req.query.teamId||'default';constfilePath=join(CACHE_DIR,team,hash);try{conststream=createReadStream(filePath);stream.pipe(res);}catch{res.status(404).send('Not found');}});// Put artifactapp.put('/v8/artifacts/:hash',async(req,res)=>{const{hash}=req.params;constteam=req.query.teamId||'default';constdir=join(CACHE_DIR,team);constfilePath=join(dir,hash);awaitmkdir(dir,{recursive:true});conststream=createWriteStream(filePath);req.pipe(stream);stream.on('finish',()=>{res.json({urls:[`${req.protocol}://${req.get('host')}/v8/artifacts/${hash}`]});});});// Check artifact existsapp.head('/v8/artifacts/:hash',async(req,res)=>{const{hash}=req.params;constteam=req.query.teamId||'default';constfilePath=join(CACHE_DIR,team,hash);try{awaitfs.access(filePath);res.status(200).end();}catch{res.status(404).end();}});app.listen(3000);
// turbo.json for self-hosted cache{"remoteCache":{"signature":false}}
# Use self-hosted cacheturbo build--api="http://localhost:3000"--token="my-token"--team="my-team"

模板 5:过滤和作用域

# Build specific packageturbo build--filter=@myorg/web# Build package and its dependenciesturbo build--filter=@myorg/web...# Build package and its dependentsturbo build--filter=...@myorg/ui# Build changed packages since mainturbo build--filter='...[origin/main]'# Build packages in directoryturbo build--filter='./apps/*'# Combine filtersturbo build--filter=@myorg/web--filter=@myorg/docs# Exclude packageturbo build--filter='!@myorg/docs'# Include dependencies of changedturbo build--filter='...[HEAD^1]...'

模板 6:高级流水线配置

{"$schema":"https://turbo.build/schema.json","pipeline":{"build":{"dependsOn":["^build"],"outputs":["dist/**"],"inputs":["$TURBO_DEFAULT$","!**/*.md","!**/*.test.*"]},"test":{"dependsOn":["^build"],"outputs":["coverage/**"],"inputs":["src/**","tests/**","*.config.*"],"env":["CI","NODE_ENV"]},"test:e2e":{"dependsOn":["build"],"outputs":[],"cache":false},"deploy":{"dependsOn":["build","test","lint"],"outputs":[],"cache":false},"db:generate":{"cache":false},"db:push":{"cache":false,"dependsOn":["db:generate"]},"@myorg/web#build":{"dependsOn":["^build","@myorg/db#db:generate"],"outputs":[".next/**"],"env":["NEXT_PUBLIC_*"]}}}

模板 7:根 package.json 设置

{"name":"my-turborepo","private":true,"workspaces":["apps/*","packages/*"],"scripts":{"build":"turbo build","dev":"turbo dev","lint":"turbo lint","test":"turbo test","clean":"turbo clean && rm -rf node_modules","format":"prettier --write \"**/*.{ts,tsx,md}\"","changeset":"changeset","version-packages":"changeset version","release":"turbo build --filter=./packages/* && changeset publish"},"devDependencies":{"turbo":"^1.10.0","prettier":"^3.0.0","@changesets/cli":"^2.26.0"},"packageManager":"npm@10.0.0"}

调试缓存

# Dry run to see what would runturbo build --dry-run# Verbose output with hashesturbo build--verbosity=2# Show task graphturbo build--graph# Force no cacheturbo build--force# Show cache statusturbo build--summarize# Debug specific taskTURBO_LOG_VERBOSITY=debug turbo build--filter=@myorg/web

最佳实践

应该做的

  • 定义显式 inputs- 避免缓存失效
  • 使用工作区协议-"@myorg/ui": "workspace:*"
  • 启用远程缓存- 在 CI 和本地之间共享
  • 在 CI 中过滤- 只构建受影响的包
  • 缓存构建输出- 而不是源文件

不应该做的

  • 不要缓存开发服务器- 使用persistent: true
  • 不要在 env 中包含机密- 使用运行时环境变量
  • 不要忽略 dependsOn- 会导致竞争条件
  • 不要过度过滤- 可能遗漏依赖项

资源

  • Turborepo 文档
  • 缓存指南
  • 远程缓存

局限性

  • 仅当任务与上述范围明确匹配时才使用本技能。
  • 不要将输出视为特定环境验证、测试或专家审查的替代品。
  • 如果缺少所需的输入、权限、安全边界或成功标准,请停下来询问澄清。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 11:20:52

常用企业网站模板对比与保姆级建站教程避坑指南

常用企业网站模板对比与保姆级建站教程避坑指南 找建站公司最怕什么?不是怕网站丑,是怕被坑高价。很多老板花几万块,最后拿回来一个加载慢、SEO权重低、甚至备案都过不了的“半成品”。今天这篇 保姆级建站教程 ,不聊虚的,直接拆解 常用企业网站模板对比…

作者头像 李华
网站建设 2026/9/27 11:20:45

电子网站建设考试新手入门:避开模板陷阱,3步拿高分

电子网站建设考试新手入门:避开模板陷阱,3步拿高分 还在用那些千篇一律的模板网站?别闹了,那种套壳的东西在 电子网站建设考试 里根本过不了关。评审老师一眼就能看出来你是直接拖拽生成的,代码冗余、结构混乱,直接判低分。 很多 新手入门…

作者头像 李华
网站建设 2026/9/27 11:20:16

2026最新WordPress搜索页报价单:揭秘5000到5万背后的坑

2026最新WordPress搜索页报价单:揭秘5000到5万背后的坑 别再被那些“高大上”却丑得掉渣的模板站忽悠了,很多老板花大钱做的官网,用户根本搜不到想要的产品,搜索页卡顿半天还报错,这钱花得冤不冤?…

作者头像 李华
网站建设 2026/9/27 11:19:42

避开建站报价陷阱:网站建设的课件如何选

避开建站报价陷阱:网站建设的课件如何选 域名服务器搞不懂,是不是你最大的心病?很多老板拿着预算找供应商,对方张嘴就是“建站报价”几千到几万不等,但你心里没底:这钱花得值不值?技术到底行不行?…

作者头像 李华
网站建设 2026/9/27 11:19:20

网站推广入口速查手册:5步打通流量任督二脉

网站推广入口速查手册:5步打通流量任督二脉 自己不会代码想做网站,是不是光看教程就头晕?别慌,这份速查手册专治各种“找不到入口”的焦虑。很多站长卡壳,不是因为技术难,而是压根不知道去哪点。…

作者头像 李华
网站建设 2026/9/27 11:19:13

用微魔方做的网站一定要加这5个模块才是最佳实践

用微魔方做的网站一定要加这5个模块才是最佳实践 别再用那种一眼假的模板糊弄客户了,那种“太丑不够用”的站点,上线三天就被甲方骂回炉。 微魔方虽好,但直接套用模板只是及格线。想让项目从“能用”变成“好用”,甚至让甲方觉得你懂行、懂业务,必须在模板基础上做深度定制。…

作者头像 李华