TL;DR How can I create an alias for a local yarn workspace dependency?
I've tried yarn workspaces before and never succeeded, and I'm giving it another try.
I've set "workspaces": ["packages/*"]
in package.json
.
For each package, I decided to use the naming convention @-/package-name
to prevent naming conflicts and without worrying about having namespaces for internal packages.
When adding packages as dependencies, I've been following a style where I use an interface name for resolution, but point that towards a concrete implementation. This is what I did before using yarn workspaces:
"dependencies": {
"my-interface-name": "file:some/path/to/packages/some-concrete-implementation"
}
This is basically to allow what I like to call compile-time static dependency injection. And it also means each package can individually name their interface dependencies appropriately to their need and to prevent naming conflicts.
However, I can't figure out how to accomplish this with yarn workspaces. How do I create an alias for my yarn workspaces package @-/some-concrete-implementation
called my-interface-name
?
What I've already tried with no success:
- Defining the dependency like
"my-interface-name": "@-/some-concrete-implementation"}
- for some reason this causes yarn to look for@-/some-concrete-implementation
on the npm registry instead of in the local workspace - I've also tried to use the workspace protocol:
"my-interface-name": "workspace:@-/some-concrete-implementation"}
but it still looks for the package on the npm registry!
What I haven't yet tried and could work but removes benefits of using yarn workspaces in the first place:
"dependencies": {"my-interface-name": "file:../../node_modules/@-/some-concrete-implementation"}"
The workspace: alias protocol (available in pnpm too) seems the direction to take.
Be sure to have yarn 3 installed, otherwise you'll run into weird issues.
Note that the syntax of
"my-interface-name": "workspace:@-/some-concrete-implementation"
looks incorrect.It should be
"@xxx/some-concrete-implementation": "workspace:*",
assuming the name of linked the package is"name": "@xxx/some-concrete-implementation"
.With this in mind you don't even need to create a specific
@-/name
. With workspace protocol, yarn will ensure it's never downloaded from npm. It becomes an internal workspace dependency.PS:
Yarn 3 installation
Generally a simple
yarn set version 3.0.2 && yarn plugin import workspace-tools
) will work.To avoid pnp current limitation, check the generated config
.yarnrc.yml
and ensure nmLinker is set to 'node-modules'PS: you might want to add this to
.gitignore
tooRun a
yarn install
just after.About package.json's
Like you did, the root
package.json
will define the workspace paths:In your app
packages/app/package.json
You consumed package should declare the same name
Bonus: Typescript aliases
If your project is written in ts, you can even replicate your paths through typescript path mapping. It will allow to include the files just as is (no prior compilation needed).
Following your example, just edit a
./packages/xxx/tsconfig.json
in this wayPS: for non typescript: babel/plugin-module-resolver can be used in a similar manner.