Skip to content

(Chore) Add Turborepo #2016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task done
drwpow opened this issue Nov 21, 2024 · 5 comments · Fixed by #2027
Closed
1 task done

(Chore) Add Turborepo #2016

drwpow opened this issue Nov 21, 2024 · 5 comments · Fixed by #2027
Assignees
Labels
enhancement New feature or request

Comments

@drwpow
Copy link
Contributor

drwpow commented Nov 21, 2024

Description

As we’re running a TS monorepo, using Turborepo would help speed up local dev and simplify configuration

Proposal

We don’t have a ton of packages, but even understanding the build order from openapi-typescript → openapi-fetch → openapi-react-query can be an annoyance. pnpm does handle some of this, but a simple version. But it can’t handle, say, testing, where running pnpm run test knows that packages need to be built (or rebuilt). At best you end up with complex configuration; at worst, a small change breaks everything

Turborepo is an elegant, drop-in solution for what we have already. It doesn’t change how packages are built or tested. It only reduces misconfigurations and mistakes when working locally. Unlike some other build systems, Turborepo doesn’t tell you how your packages should or shouldn’t be built, and can be added without disrupting anything. It can also be easily removed if we don’t like it (no lock in). For all these reasons, I’ve really enjoyed projects that use it, and would like to add it here.

Turborepo also has configurable caching. That’s a secondary benefit to the real advantage—simpler cross-package dependency management (it “just works”). But in case the caching causes any undesirable results, it can be tuned down or opted out of, which is nice.

There are really no downsides with Turborepo; this just simplifies monorepo configuration.

Alternatives

Nx and Bazel are the two other popular build systems. Nx I’ve had bad experiences with (the plugins are invasive, and each one comes with its own set of debugging woes—nice when you get it running but the setup can be painful). Bazel is a nonstarter because it’s completely incompatible with JS. I’m not aware of any other alternatives.

Checklist

@drwpow drwpow added the enhancement New feature or request label Nov 21, 2024
@gzm0
Copy link
Contributor

gzm0 commented Nov 22, 2024

Bazel is a nonstarter because it’s completely incompatible with JS.

My 2 cts here: We use bazel extensively to build all our JS (rules_js is what you're looking for, if you want to see how we do it: https://github.com/datahouse/bazel_buildlib).

That being said, IMO bazel mainly shines:

  • If you need to build multiple languages
  • If you have builds that benefit significantly from caching.
  • If you need abstraction capability in your builds (i.e. abstract build pieces into "functions", bazel calls them macros).

AFAICT, none of these apply to openapi-typescript (and turborepo seems to solve caching as well). So I do not think paying the additional complexity of managing a bazel build is worth it and turborepo is indeed a better alternative.

@drwpow
Copy link
Contributor Author

drwpow commented Nov 22, 2024

We use bazel extensively to build all our JS (rules_js is what you're looking for, if you want to see how we do it: https://github.com/datahouse/bazel_buildlib).

Thanks for sharing! I think the thing I want to avoid, which I’m not sure is possible with Bazel, is manually declaring every input & output file in Starlark, which is unmanageable for JS at scale (especially when using different build systems like Rollup/webpack/Vite—the outputs are known only by the bundler, especially when you factor in hashing and codesplitting). Works wonders for other languages, but for JS I’ve just found Bazel can only handle the most simplistic of build tools, and even the simplest usecases come with drawbacks.

Turborepo does cache! But it takes a more “hands-off” approach with inputs & outputs, instead allowing glob matching. So it might not be technically as perfect as Bazel, but it’s pretty darn close for JS, and is just as easy to remove as it is to add (fun fact: Vercel bought the Turborepo startup after trying to integrate Bazel, and determining it wasn’t sufficient)

@kerwanp
Copy link
Contributor

kerwanp commented Nov 27, 2024

I tried bazel a while ago but literally gave up because of its complexity. It seems great for large monorepo containing different languages but overkilled and overcomplicated for our use case.

NX drastically improved over the years but is extremely opinionated making it painful to implement on an existing monorepo.

I think turborepo is the best choice here. And as it is well known by the community it should not scare potential new contributors.

@htunnicliff
Copy link
Member

I think trying Turborepo sounds great!

I've used Lerna (Nx) in recent years but found it to be a little tricky, so Turborepo sounds like a good step to me.

@drwpow drwpow mentioned this issue Dec 2, 2024
3 tasks
@drwpow
Copy link
Contributor Author

drwpow commented Dec 2, 2024

Turborepo added! It works more-or-less the same as before. Here are the rules:

  • Every package should have a build, lint, and test command. How they work is up to the individual package, but Turborepo will orchestrate the order of what needs to happen
  • Turborepo is only at the workspace (root) level. Running commands per-package bypass it. So if you run pnpm run build in one package, only that package is built. I usually prefer this for simpler / faster debugging.
  • turbo.json controls the commands. You’ll notice it is missing things like outputs. That’s because I find the defaults to be pretty good, but we can always add more here as-needed.

Advantages

  • Turborepo is better at helping remember the order of commands. For example, if you ran pnpm test, it would make sure every package was built before testing. Same for linting.
  • Turborepo is better at parallelizing. While pnpm run is great, it does require manual setup. And introducing a new package can be painful as it can disrupt the chain. Turborepo is great at knowing what to parallelize, and when
  • It’s 100% removable. If the weirdest inconvenience crops up because of it, we can eject at any time at no cost.

If y’all notice anything weird with it, please let me know! I am only adding it as a convenience; the moment it stops being so, we can reconfigure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants