Everything you need to know about monorepos
monorepo.tools
monorepo.tools
https://news.ycombinator.com/item?id=30424279
"Ask HN: Is there any way to detect websites that are SEO-optimized on Google?"
Unfortunately, those seem to even get into HN. This page is a perfect example. This is how the page starts:
Everything you need to know about monorepos,
and the tools to build them.
Understanding Monorepos
Monorepos are hot right now, especially among Web
developers. We created this resource to help developers
understand what monorepos are, what benefitsthey can
bring, and the tools available to make monorepo
development delightful.
There are many great monorepo tools, built by great
teams, with different philosophies...
I got so tired at this point that I stopped reading.In my mind, I see the job description on Fiverr "Fast SEO writer wanted! Please write a 3000 word page about monorepos. Make sure to mention 'monorepos' and related terms like 'web developers', 'tools', 'development' etc frequently."
Here's a screenshot for your convenience [1]
I agree with you that I prefer to get straight to the point, but this pet-peeve tangent doesn't seem to be a productive discussion of the actual merits of the tooling.
"The tools we'll focus on are: Bazel (by Google), Gradle Build Tool (by Gradle, Inc), Lage (by Microsoft), Lerna, Nx (by Nrwl), Rush (by Microsoft), and Turborepo (by Vercel). We chose these tools because of their usage or recognition in the Web development community."
Contributors:
- Alex Eagle / Bazel
- Kenneth Chau / Lage
- Jeff Cross / Nx
- Victor Savkin / Nx
- Pete Gonzalez / Rush
- Justin Reock / Gradle
So, yeah, it would be a focused website.
You didn't even read past the fourth paragraph. You should be ashamed for derailing what could have been a productive discussion about an interesting topic with your shallow dismissal.
Sorry.
Monorepo is a way to morph dependency management problem into source control problem within your organization. Currently, FOSS tools solve none of them.
But, this is what you get when the barrier of entry for software development has been set so low :)
Millions of developers using tools that they don't fully understand to produce sub-par solutions.
I am so happy that this is the state, so people who can build working, delivered on time solutions are getting paid very well.
Also, with an unsolved problem you get paid to make whatever crazy attempt you want, which is absolutely a perk.
Here's an example: let's say that is you've got a single product with a backend server, database, web frontend, and a iOS app. How would you release all those projects as an atomic unit?
If there's a new field in this release, the database schema needs to be changed on the servers before the backend is released. The backend needs to change before the frontends do. You have no control over the deployment speed of some of those components, so releasing them all at the same time is impossible.
Similar issues would happen if you update 3rd party library, and software using the new Vs. old versions of the library are incompatible.
So the value of this monorepo isn't that you could cut a release for all of the components at once. It is that everyone doing development has a shared view of the current state of the system.
- git on large repo 100% pain 0% fun. hg is slightly better, but not much.
- No version means no prebuilt libraries, which translates to "you need a great build cache to keep build time reasonable".
- "passes all the tests everything is good" if only we can run all the tests on such changes.
- People hate coordinating on imported/pinned third-party dependency versions, sometimes you need tools for large-scale automated changes to make progress, but :(
- Similarly, not all places make all their codes accessible to all engineers.
i.e. source control problem is, sometimes, harder.
somehow, the authors of this website neglect to even mention Nix. maybe that has something to do with the fact that this is a marketing page for the tool they named Nx (seriously?).
I was actually about to mention Nix in my post as well. Being a casual NixOS user myself I wonder if there is any kind of monorepo tooling based on Nix? Without ever having used Bazel myself I always thought of it as Nix-like.
We use josh[0] to let people clone "just in time" repos with the tooling needed for our setup[1]. We've also started a consultancy (tvl.su) that helps companies move onto this setup, and have customers going for it already.
The reasons we've not been making a lot of noise about this are that we have other large projects(like Tvix[2]) taking up time, and also the integration with customers moving to this setup lets us more confidently figure out what parts we need to smoothen for "non-TVL" use-cases.
As for using Nix in a Bazel-like way, the common experience with Nix is that language-specific build systems are wrapped. This being possible enables projects written in any language to be wrapped in Nix, and integrated in a Nix-based monorepo (something which makes it distinctly more powerful than other solutions).
However, there's nothing in principle preventing Nix from dropping down a layer to the project level itself, and we've implemented (and use) this for Go[3] and Common Lisp[4].
[0]: https://github.com/josh-project/josh
[1]: https://cs.tvl.fyi/depot/-/blob/views/kit/README.md
[2]: https://tvl.fyi/blog/rewriting-nix
The most important one being that you need to have an org/team structure that is set up to support it. You cannot say that it will make the org more efficient as organizations are not all the same. In order to push monorepos, the decision makers ought to know what those caveats and tradeoffs are, or they're going to be in for a sad time.
Site does do a good job of going over the tooling around it. Now this might be a matter of perception, it seems that the tooling is getting better, though not yet very mature. I see a few instances of "write your own" where the tooling is lacking, which is not a great way to go about things, and once again, makes assumptions about the nature of the orgs.
Is the tool going to help me detect when I accidentally bypass the declared dependencies?
For example, in a basic monorepo it's very easy to accidentally rely on the file layout on disk (require'ing a dependency not in your package.json but that has been hoisted because it's a dependency of a different package accidentally succeeds, cp'ing files from `../some-other-project` should not be allowed but is possible). All of these invalidate some optimizations that monorepo tools want to make.
At scale with many contributors, it's HARD to teach and remember and apply all these rules, and so the monorepo tool really should help you detect and fix them (basically: fail the build if you mess up).
The article doesn't really make it clear which tools will do that for you. Pretty sure that Bazel does, Nx probably does, and lerna and turborepo don't.
TBF, if you have centralized dependencies or your dependency on another module affects your dependencies, you are probably doing it wrong. APIs between parts should be well defined and not require the entire dependency runtime to be loaded to interact with it.
It’s nice to suddenly see 10 missing explicit dependencies simply by virtue of running ‘pnpm install’ instead of ‘npm install’.
This was an absolute nightmare to try managing in separate repos. I've finally settled on two monorepos: a Yarn/TypeScript/React frontend monorepo, and a Rust/Docker backend monorepo.
Does anyone have any advice on these? I sort of stumbled into this pattern on my own and haven't optimized any of it yet.
For Rust, I'm curious if folks have used Bazel for true monorepo build optimization. I don't want to rebuild the world on every push to master.
Likewise for the frontend, is there any way to not trigger Netlify builds for all projects if only one project (or its dependencies) change?
Would super appreciate any advice.
The target bucket I use has a very short object lifecycle setting so I don't even have to clean up old artifacts manually.
I'm using Github to run builds. I'll have to investigate your setup, because that sounds perfect. I don't know if Github can do that.
What do you do if you need an artifact that gets garbage collected? Manually force a rebuild of that SHA? Have things on continuous deploy and update regularly? I may need better CI/CD practices.
There could be smarter ways to do so tbh, like having time&date_<Sha of commit>, but I didn't have the need for any of that yet.
About GitHub I am not sure, bit cloud build can be triggered by GitHub commits: https://cloud.google.com/build/docs/automating-builds/build-... . I hope it helps!
If your API is not schema-based, you have no way of knowing something broke without FE/UI testing.
The only thing I'm convinced of these days is: whatever way you choose is the right way.
In target repo you create a folder and in that folder you rebase your dependency repository.
Maybe I can find better documentation that I remember writing it down somewhere.
Assuming you have repos `foo` and `bar` and want to move them to the new repo `mono`.
$ ls
foo
bar
# Prepare for import: we want to move all files into a new subdir `foo` so
# we don't get conflicts later. This uses Zsh's extended globs. See
# https://stackoverflow.com/questions/670460/move-all-files-except-one for
# bash syntax.
$ cd foo
$ setopt extended_glob
$ mkdir foo
$ mv ^foo foo
$ git add .
$ git commit -m "Prepare foo for import"
# Follow those "move to subdir" steps for `bar` as well.
# Now make the final monorepo
$ cd ..
$ mkdir mono
$ cd mono
$ git init
$ touch README.md
$ git add README.md
$ git commit -m "Initial commit in mono"
$ git remote add foo ../foo
$ git fetch foo
$ git remote add bar ../bar
$ git fetch bar
# Substitute `main` for `master` or whatever branch you want to import.
$ git merge --allow-unrelated-histories foo/main
$ git merge --allow-unrelated-histories bar/main
# Inspect the final history:
$ git log --oneline --graph
* 8aa67e5 (HEAD -> main) Import bar
|\
| * eec0abd (bar/main) Prepare bar for import
| * 9741d6d More stuff in bar
| * 634ba3d Initial commit bar
* 43be6e9 Import foo
|\
| * d4805a0 (foo/main) Prepare foo for import
| * 4d2ca10 More stuff in foo
| * 72072a1 Initial commit foo
* bfcb339 Initial commit in monoUse git-filter-repo's --to-subdirectory-filter and --tag-rename:
https://github.com/newren/git-filter-repo#solving-this-with-...
[0]: https://github.com/josh-project/josh
[1]: https://manpages.debian.org/testing/git-man/git-subtree.1.en...
Do you more often have trouble articulating yourself in written text? I think you can most likely do better! Please try.
I find mono repos much better in all cases the code inside the individual repos is even the slightest dependent on eachouther.