Replies: 8 comments 7 replies
-
@zaripych in the meantime, here’s a workaround for you. In my projects, I have been duplicating package scripts just as you described. But, I try to abstract away all of the details. I have many package.json files that look like: {
"scripts": {
"turbo:build": "../../../bin/nextjs/build",
"turbo:clean": "../../../bin/clean/all",
"turbo:dev": "../../../bin/nextjs/dev",
"turbo:test:ci": "../../../bin/jest/ci",
}
} The only thing is, most packages have 40+ scripts, not 4. I find that abstracting the scripts into a common bin folder helps a lot (I also like prefixing shared scripts with As my monorepo has grown, I have different types of packages. Some for nodejs, some for reactjs, some for apps, some for configs. There’s only a few scripts that are actually run in every single repo due to turbo disallowing circular dependencies. This abstraction allows me to group sub-packages and sub-apps like As for ensuring every package has a particular script, I find that using a template generator is awesome (see plop and hygen). Or, writing a short script in bash or the language of your choice is straightforward. Anyway, the developer experience of turbo is interesting to explore. Reminds me of:
While I prefer convention over configuration too, it’s important not to become overspecialized and ensure exceptions can be specified. |
Beta Was this translation helpful? Give feedback.
-
@jlarmstrongiv Actually, already doing that. I have a dev package that is mounted as
That's a lot.
Ok. I'm talking about different tasks that do not belong in scripts of a package but which I still want to cache and benefit from turbo. Developers won't ever care to run them manually.
Agreed. Code generation is ok as long as you do it within a monorepo and can regenerate it a little differently at any time 👍 FYI - I was annoyed and fixed that by wrapping standard
It's still a little raw and a bit buggy for now. (E.g. at the moment running a canary because previous version was hitting the cache too much) I'm very enthusiastic though to see how this will evolve further and really considering using it in more projects at work.
Agree. Customisation is needed at times, but those also might mean that |
Beta Was this translation helpful? Give feedback.
-
Very cool! I like those workarounds. I wonder if it should be a broader discussion on turbo UX. Discussion points include:
How would that look? Curious what your thoughts are on it. There’s a lot to think about and there are tradeoffs in choosing what to support too.
I think there are use cases where devs would want to run some common scripts manually in a package. Examples https://www.npmjs.com/package/sort-package-json and https://www.npmjs.com/package/typesync |
Beta Was this translation helpful? Give feedback.
-
As a shorter term solution (until turbo supports additional config for this in turbo.json), when turbo doesn't find a task in a package's package.json scripts, can it then check if a command with that name exists in the context of that package? If making it possible to declare this for all packages in For example, suppose your "scripts": {
"test": "true",
"test-unit": "jest --passWithNoTests",
"test-ui": "our-custom-ui-testing-script",
...
} Today you can already define a package like @zaripych mentioned providing executables with the same names as those scripts/tasks, so your package.json files become: "scripts": {
"test": "test",
"test-unit": "test-unit",
"test-ui": "test-ui",
...
} Running |
Beta Was this translation helpful? Give feedback.
-
Another use case to throw in here is in our project in each package.json I have a script It would be nice if I could tell turbo that Currently I just use a different fake name for the |
Beta Was this translation helpful? Give feedback.
-
I wanted to share a new approach I am using for these cases: Turbo already recommends having “config” packages (example: After some self-bike-shedding, I arrived at Then, in each workspace/sub-package I can replace Code example.
|
Beta Was this translation helpful? Give feedback.
-
Curious how you all have evolved your solutions to this in the past couple years? We're in the process of getting a new turbo monorepo stood up & the duplication of scripts in each |
Beta Was this translation helpful? Give feedback.
-
I've been trying Microsoft It has the ability to define worker scripts that stay resident between packages, so you don't pay full startup time for those tools for every package. This speeds up my builds by at least 10x compared to turbo. Also it is more flexible in the configuration of dependencies because the dependency file is a JS file so I can use code to define (or not define) the tasks and get very precise about what I want. |
Beta Was this translation helpful? Give feedback.
-
Describe the feature you'd like to request
I've been thinking about this for some time now. The idea keeps nagging me. Imagine - I have a
dts
task that I can run for every package in my monorepo, but that task doesn't have any value for the end user (read developer in a team using the monorepo) by itself - meaning user will never run that task manually viaturbo run
orpnpm run
. The task is needed to run anotherdts-bundle
task - essentiallydts
produces an intermediate artefact that allowsdts-bundle
that depend on it to succeed without errors. Now the problem is thatdts-bundle
needs to rundts
for all dependencies.This seem to work nicely:
But little issues creep up - mostly scalability:
dts
task declared inpackage.json
scripts - it probably wouldn't make sense to have to copy-paste it everywhere since the task is basically single script that can work in every package sub-folder and produces output in that package sub-folder, but has no input other than source code and doesn't need any configuration on per package basisdts
task must be run for every dependency of a package where we about to rundts-bundle
, but a developer might forget to add a script topackage.json
for one of those dependencies - when adding thatdts
script they might also make a mistake and pass wrong parameters or things like thatdts-bundle
for their package they have to go and check every dependency and whether that dependency hasdts
task declared. Hopefully it's very easy change and a quick PR away, but those packages could be owned by other teams.In addition to that it's also possible that
inputs
of some otherbuild
task in one package is different to another package'sinputs
. But the fact that those differences should be specified in the root of the monorepo in a single file is kind of limiting. If we look at monorepos with huge number of packages I feel singleturbo.json
might become a bottleneck (with some merge issues maybe even?). Sometimes a script can determine those inputs/outputs programmatically and can operate in the entire monorepo for any sub-package. E.g. I imagine a script could determine all the dependent*.ts
files imported and build a graph of files that it depends on (inputs) - and that would probably be more efficient than using globs likesrc/**/*.ts
that could hit hundreds of files.Another script could determine which dependencies need to have
dts
task run and which don't. There is generally a lot of things that can and should be automated andturbo
doesn't provide too much here. The CLI could be considered as API andturbo.json
can be generated - but it makes it harder to use hybrid approach - use ability of theturbo
to cache and also allow devs to useturbo.json
without having to deal with a script.Describe the solution you'd like
turbo.json
, example:turbo
would assume the command exists in every package as if it was added to every package's scripts config.turbo.dts.json
file OR preferably - allow it to be passed asstdin
. If location of theturbo.json
implies root of the monorepo we could also add extra parameter or assume it's cwd. This will maketurbo
super powerful tool that would allow caching any task - whether it can be described byturbo.json
manually or generated by a script.Both of the above seem like a simple change on the surface. But there must be some caching implications. E.g. we would need to store hash of the
stdin
config somewhere which could serve as a cache key for the rest of the data associated with the run ...Describe alternatives you've considered
Generating
turbo.json
is possible, but writing scripts to everypackage.json
- seem like a less desired path as it's often modified manually.Beta Was this translation helpful? Give feedback.
All reactions