feat(yarn-plugin-external-workspaces): Add a yarn plugin for adding external workspace support#3504
Merged
JasonVMo merged 55 commits intomicrosoft:mainfrom Mar 13, 2025
Merged
Conversation
tido64
reviewed
Feb 4, 2025
NikoAri
reviewed
Feb 5, 2025
…nd a shared package for the behavior
Member
|
This build error: Is caused by "esbuild": "npm:esbuild-wasm@^0.23.0",(See yarnpkg/berry/packages/yarnpkg-builder/package.json:17) This is a hack to get diff --git a/package.json b/package.json
index 2a1dbed4..749cfbe3 100644
--- a/package.json
+++ b/package.json
@@ -62,6 +62,7 @@
"@react-native-community/cli-types": "^15.0.0",
"@rnx-kit/react-native-host": "workspace:*",
"@vue/compiler-sfc": "link:./incubator/ignore",
+ "@yarnpkg/builder/esbuild": "^0.23.0",
"react-native-macos/@react-native/assets-registry": "^0.76.0",
"react-native-macos/@react-native/codegen": "^0.76.0",
"react-native-macos/@react-native/community-cli-plugin": "^0.76.0",But I don't know what breaks if you do. This issue was also filed on their repo: yarnpkg/berry#6176 |
…aces with supporting code in tools-workspaces
tido64
reviewed
Mar 11, 2025
Member
tido64
left a comment
There was a problem hiding this comment.
I'm not 100% sure what all of this does so it's mostly superficial.
incubator/yarn-plugin-external-workspaces/bin/install-plugin.cjs
Outdated
Show resolved
Hide resolved
Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com>
tido64
approved these changes
Mar 13, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Open Issues
All blocking issues have been resolved. Direct fallback to tgz can be investigated separately if needed.
Bug in resolution causing local paths to appear in lockfileNeed to test whether the full protocol needs to be implemented to avoid lockfile changes on project changesLockfile is stable, local is working correctly, fallthrough logic for lookups not working correctly.Removing version from .json output, unnecessary and will reduce churn in the output.output files should be relative to repo root, transform can happen on lookup but gives flexibility for JS implementations to vary paths based on environment.Need to look at Windows paths more closely, error in CI from a path getting d:\d:\ at the start.Description
(Copied from README)
A plugin for yarn v4, that allows multiple monorepos to reference one another
when present on disk, automatically falling back to npm semver lookups when the
local files are not present. This is particularly useful for enterprise scale
monorepos that contain multiple JS project roots.
In the case where the large scale monorepos support some form of project
scoping, where the various projects may or may not be present on disk, this
allows dynamic fallback to standard npm resolution in the case a project is not
present. This happens without lockfile modification.
Details
This plugin works by creating two new protocols,
external:which is a softlink type, used to create the local file links, and
fallback:a hard link typeprotocol which routes to the
npm:protocol. Theexternal:entries aresupported by the
ExternalResolverandExternalFetcherclasses. Thefallback:protocol is supported by theFallbackResolverclass which takesthe
fallback:descriptors and binds them tonpm:locators. In this way thefallback:entries in the lockfile share their resolution with thenpm:entries and the
NpmSemverFetcherwill end up being the one to drive the cachebehavior.
This is all driven by use of the
reduceDependencieshook which willautomatically process dependencies during resolution, routing local dependencies
to the
external:protocol, and non-local dependencies to thefallback:protocol. To avoid lockfile mutation the resolvers set up a dependency chain via
the
Resolver.getResolutionDependenciesmethod to chain the three protocols(external, fallback, and npm). The chain ordering is:
external:->fallback:->npm:fallback:->external:->npm:This chaining ensures that all three protocols exist in the lockfile, regardless
of their presence on disk. Because the lockfile entries are alphabetical, the
lockfile remains identical, even if projects on disk change their local/remote
state.
Installation
The plugin needs to be installed via yarn plugin install command. This needs to
reference the produced bundle out of the dist folder.
The package itself also has a bin command that can be used as a self-installer,
so if you add the plugin as a dependency to your scripts folder, you can tell it
to install itself by executing
install-external-workspaces-pluginfrom withinthe yarn repo where the plugin should be installed.
Usage
There are two parts to using the plugin, which are effectively configuring the
inputs and outputs.
Inputs
To be able to determine the external workspaces the plugin needs to have the
externalWorkspacesProviderconfiguration option set. This can either point toa .json file or a .js/.cjs file.
JSON Configuration
The format of the JSON is derived from the
WorkspaceOutputJsontype which hasthe following format:
As mentioned in the comments, anything outside of the generated section is
ignored. When looking up the workspace paths to see if they exist on disk, the
path is constructed via joining the path to the config file, the repo path, and
the relative paths within.
JS Configuration
To configure via JavaScript, the specified JS file will be loaded via
requireand should return a function as the default export with the following type:
The existence of returned
PackagePathswill cause this package to be treatedas external, even if the path is null. If the path is set the plugin will check
for the existence of a
package.jsonfile at that location to treat it aslocal. Each package name will only be checked once per session, caching will
happen within the plugin.
Outputs
The plugin also has the ability to write out .json files in the format of
WorkspaceOutputJsonby using a command or during yarn install. The outputlocation is set via the
externalWorkspacesOutputPath. If it is set to a .jsonfile it will write to that file, if it is a directory name, it will create a
file with a the name of the root package in the repo. So if your root
package.json has the name set to
my-repo, it will write out a filemy-repo-workspaces.jsonat the specified directory.By default this output will happen automatically on install. It will check the
contents of the file before writing and will skip the write if no changes are
required. This automatic write behavior can be suppressed by setting
externalWorkspacesOutputOnlyOnCommandto true viayarn config set externalWorkspacesOutputOnlyOnCommand true.The output can be triggered explicitly by running
yarn external-workspaces outputwith the ability to override settings or checkfor changes.
See the command
--helpentry for options.