I’m of two minds about the monorepo approach.
At NoRedInk, our main application is basically a monorepo—and if it’s not, it’s at least very central to the majority of our engineering staff’s work.
When working on that, I’ve had a good experience developing modules internally with the rest of our code before packaging and releasing them. This is how
List.Selection happened, among others. We figured out the minimal API, documented it (our top level modules have their docs enforced by CI anyway), and eventually published it as a package. It’s a a very compelling use case to me, because it tells a nice story about software being developed against a concrete use case before being generalized and released.
This would have been much harder to do if we had jumped straight to a package model, and I’m concerned that by making private packages available, we may discard this nice feedback loop. At least, we may make it harder for people to have the nice experience I’ve had.
Contrast the above with “well, we need some package to do this, better go make one.” (not a straw man—I’ve literally done this in other contexts, much to my chagrin.) By doing this too early, you throw up barriers to quickly converging on a solution: it’s harder to release new versions and bump them in your target repo than it is to make the changes directly inline. Worse, you’ve now committed resources to a thing that you maybe find out shouldn’t exist later! That sounds like a worse experience subjectively, and in my experience leads organizations to double down on the thing they created, rather than cutting their losses.
This is not exactly a rosy picture, but I think it’s a plausible failure case. I hope I don’t seem to overwrought about it. I’ve just experienced it several times in places where private repos were available! /
We also have
noredink-ui. It’s public because we’re fine with making it public, but I don’t think it’s optimal. In this situation, we chose to publish in this way because we previously chose to not use the monorepo strategy for two very different projects. They have different tech stacks, deployment patterns, CI, etc. The short story is that the second project, which needs to share this code, is using several experimental strategies which we want to shield the rest of the organization from. If they work out, maybe we’ll bring them into the main project! Who knows!
Anyway, this would be the right time, in my mind, to have a private package. This is code that we’re OK with, but not code that we necessarily planned to ever publish. Some areas were rough, some abstractions didn’t make sense, but we needed to share the code because of decisions made earlier in our lives, and found that this approach was the least bad among those available.
I have seen similar things happen when consulting from organizations who were bit by the microservices bug—now all those little critters are living in their own repos. Whoops! I’d love to hear from someone who is facing this specific problem when using Elm, because I know it exists… but what’s the actual lived experience of it in this case?
I’d also like to point out that frequently when people find that their API boundaries are messy, it’s because they have not designed their modules around a single data structure. Wanting to publish a package to encapsulate some messy API boundary is just going to throw up more of those barriers around making it better, so maybe there are better solutions to this particular affliction.