Closed szymon-99 closed 5 months ago
Thank you for adding this, I've linked this issue through a discussion board as well. Hopefully gains some traction with the turborepo team.
@anricoj1 do you have a link to that discussion?
Would love to see this as well
I know that you recommend to install everything in workspaces
Where is that discussed?
I've grown increasingly convinced over the past year that the TypeScript monorepos should move towards installing everything at the root of the monorepo. This is also what Nx recommends, at least for brand-new monorepos:
This strategy has a lot of elegance to it, as it makes working in the repo ultra-simple and rips out a ton of the crappy complexity that we had before:
1) You only have one node_modules
directory, and it's at the root of the monorepo. The mental model here is super clean.
2) You don't use the "workspaces" feature of the package manager whatsoever. It's very annoying to have to remember to put in workspace-related command-line flags whenever e.g. adding a new dep. This brings parity between "normal" single-project repos and monorepos.
3) You don't have to worry about making somewhat-arbitrary distinctions between "ESLint-like" deps that should apply to the entire mono-repo, and "library-like" deps that should only apply to specific packages. Everything just goes into the root as a normal dep.
4) Updating dependencies becomes ultra simple - you don't need some over-engineered monorepo tool to do it! You can just run conventional tools like npm-check-updates
, and then after updating a single "package.json" file, you can simply run npm/yarn/pnpm install
.
- And checking for breaking changes after a new dep update also becomes easy. After updating, we can trigger a commit, and TypeScript will take over and let you know in CI in any of the new API changes broke one of your existing packages. Then we can revert the commit if needed, or continue to go on and make another commit to fix to the individual broken packages (or coordinate with other teams, if necessary).
- In some monorepos, some packages are published to npm, so they need their own individual "package.json" files. Nx offers the option to automatically create package.json files when publishing, but sometimes you will want more control over them, and will choose to manually manage them yourself. (Does Turborepo have an analogous feature?) If you do manually manage "package.json" files, then you need an additional tool to propagate version changes downward from the root "package.json". With that said, even in this situation, I think it is preferable to use simple tools like [`syncpack`](https://github.com/JamieMason/syncpack) to do this, rather than complicated tools like e.g. `lerna`. (`syncpack` is essentially just a glorified copy-paster, so even in this situation, we are still maintaining the simple mental model of how dependencies work.)
@Zamiell:
I've grown increasingly convinced over the past year that the TypeScript monorepos should move towards installing everything at the root of the monorepo. This is also what Nx recommends, at least for brand-new monorepos:
This is what I've been doing, for most of your reasons, but the approach seems to prevent me from testing and debugging within VSCode. See the discussion I opened.
Unless someone can tell me how to get this working, I'll be migrating me repo to package-level-only installations.
UPDATE: I've listed some possible solutions in that discussion thread, but I'm not happy with any yet.
I agree with @Zamiell's point about preferring root-level dependencies. Here's why.
I installed my first Turborepo monorepo by following this wonderful tutorial, which initializes everything with npx create-turbo@latest
, rips out the default apps, and then installs a new app via yarn create next-app
.
Unfortunately, this left me with react, react-dom, and their typings at different versions between apps/myapp
and packages/ui
, causing compilation errors. It cost me some time to troubleshoot. I thought it much wiser to have the packages use single root-level versions of these dependencies than to try to manually keep the versions in sync between packages. I moved all my packages to the root.
I have not yet explored the downside of trying to publish packages under this approach.
While this root-level dependency approach works for fresh turborepo projects I think we need documentation around combining already existing projects into a turborepo mono repo. This kind of scenario would contain projects with different versions of dependencies, so the approach of defining dependencies at the root level doesn't work.
I've been experimenting with running and debugging tests in VSCode using root-level dependencies and am finding it a pain to get working. When I do get things working, I'm not happy with how it works. VSCode fundamentally requires a package-level node_modules
, and symbolically linking to the root node_modules
doesn't work for all package configurations.
So now I'm thinking that if you want to be able to run and debug tests from within VSCode, you should keep package dependencies within each package and only put dev dependencies at the root.
I'm now looking for ways to synchronize package versions. The syncpack tool should work with Turborepo, but I'm not sure I want to be dealing with this extra chore. On the other hand, Rush and Bit both automatically keep versions consistent.
I now have testing/debugging working from within VSCode despite putting all dependencies in the root.
I solved the problem by changing the VSCode extension I was using to run Jest tests. The vscode-jest extension does not require a local node_modules
, while the vscode-jest-runner extension does.
However, both still require that you set up a a VSCode project.code-workspace
file and open VSCode in workspaces mode.
So I think I'm going back to recommending installing all dependencies at the root level.
UPDATE: Except I am unable to individually debug tests using vscode-jest on a Mac. It seems there is no end to the tooling trouble when you attempt to go with root-level dependencies.
@patoncrispy Apologies for the late response but I've tracked down the discussion board I was referencing.
However, there hasn't been a response on it and the last message was from me on September 23, 2022 linking users to this thread.
any updates here?
any updates here?
Yes. I've spent months researching this issue, gaining experience, collecting notes, and writing a four-part article on managing dependencies in Turborepo and Nx, which I'll be publishing shortly. Follow me or JavaScript in Plain English to see the article when it finally comes out. I enumerate special considerations for React, Svelte, Vue, Jest, and VSCode.
There is only one right way to manage dependencies in Turborepo. I have come to understand that it was my reading about Nx that caused my confusion with Turborepo, as Nx is more flexible with dependency strategies, though with tradeoffs. And you'll want to do so with pnpm to reduce issues (my article explains this too).
If you want Turborepo to rebuild (or perform some other task) whenever a dependency changes, you MUST isolate that dependency as a package within the monorepo and add a dependency on that package to package.json
. If you rely on root-level dependencies, you will have to manually force a rebuild without the cache for any change, which is especially not advised if you're working on a team and need everyone to rebuild for the change.
So if you have a common tsconfig, jest config, eslint config, tailwind config, etc., and if you want any changes to those configurations to induce a rebuild (or retest, etc.), you'll need to make each of these configurations its own package and configure your projects to use these package configurations rather than strictly local configurations. (My article explains every detail of how to do this with the popular tools.)
The Turborepo example monorepos do exactly this for most tools, so you can degit or model these examples to create your own monorepos.
Also, with just minor additions to a Turborepo monorepo, the monorepo will also work with Nx (though the reverse isn't generally true). My article also covers this.
Hey everyone, I just finished my series on monorepos with Turborepo, also covering Nx for the case where they can both run on the same monorepo. Please let me know of any issues you find.
RoyalDevGit
Hi @jtlapp, Can you please help with the turborepo issue I have? I have several apps in monorepo and these are using different react versions. These apps are coming from different repos, so using different versions make more sense. But when I run npm install, dependencies are installed in both root and workspace directories, and makes some test scripts fail because of version incompatibilities. I would like to install dependencies in only workspace directory for each app. Do you know how to achieve this?
I think this is off-topic for this thread, and I'm not sure I can help, but feel free to email me at arachnojoe@gmail.com to have this conversation.
FYI for those following along with this issue: I've got a new version of the documentation currently underway on the docs-new
branch, including the guide being requested: https://github.com/vercel/turbo/blob/docs-new/docs/content/repo-docs/crafting-your-repository/managing-dependencies.mdx
(Very work-in-progress but in case you want to check it out ahead of time!)
I am getting the same issue in #4019 (https://github.com/vercel/turbo/discussions/4019#discussioncomment-8621465). How are you guys able to solve it?
This guide is now live at https://turbo.build/repo/docs/crafting-your-repository/managing-dependencies.
Describe the feature you'd like to request
Hello, I know in some monorepos people are installing packages on the root package.json so they only have one place to specify required packages.
In other repos people are doing it not consistently like some packages are in root package.json and some in workspaces eg. mantine.
And others only install devDependencies in the root package.json eg. material ui
I know that you recommend to install everything in workspaces, but are there any things that should be "hoisted" to the root package like eg. devDeps, do you have any recommendations on that?
Describe the solution you'd like
You could provide some docs so people won't make mistakes about managing deps and willl have a clear vision how to do it from the start, something similar to the nx one but maybe more monorepo beginner friendly? 😄
Describe alternatives you've considered
https://nx.dev/concepts/integrated-vs-package-based