Skip to content

Commit e85dfbf

Browse files
bestandercpojer
authored andcommitted
workspaces install RFC first draft (#60)
* workspaces install RFC first draft * disable workspaces with a .yarnrc flag
1 parent 196261c commit e85dfbf

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

accepted/0000-warkspaces-install.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
- Start Date: 2017-05-04
2+
- RFC PR:
3+
- Yarn Issue: https://github.com/yarnpkg/yarn/issues/3294
4+
5+
# Summary
6+
7+
Add workspaces keyword to package.json to allow multi project dependency installation and management.
8+
When running install command yarn will aggregate all the dependencies in package.json files listed in workspaces field, generate a single yarn.lock and install them in a single node_modules.
9+
10+
# Motivation
11+
12+
This RFC is based on a need to manage multiple projects in one repository [issue #3294 aggregates all related discussions](https://github.com/yarnpkg/yarn/issues/3294 (https://github.com/yarnpkg/yarn/issues/884)).
13+
14+
[Image: https://fb.quip.com/-/blob/CTYAAAX6p4Y/3y0pmJnH2NKkg4ae06hVyw]
15+
We are taking an iterative approach to implement the whole end to end experience of workspaces, there will be RFC and PRs for:
16+
17+
18+
1. Installing dependencies of all workspaces in the root node_modules (this RFC)
19+
2. Commands to manage (add/remove/upgrade) dependencies in workspaces from the parent directory
20+
3. Ability for workspaces to refer each other, e.g. jest-diff → jest-matcher-utils
21+
4. package-hoister for workspaces, e.g. when dependencies conflict and can't be installed on root level
22+
5. Command to publish all workspaces in one go
23+
24+
For a while workspaces will be considered an experimental feature and we will expect breaking changes until it becomes stable.
25+
26+
# Detailed design
27+
28+
I'll use [Jest](https://github.com/facebook/jest) for the example implementation.
29+
30+
Workspaces can be enabled by a flag in .yarnrc:
31+
```
32+
yarn-offline-mirror "path"
33+
disable-self-update-check true
34+
workspaces-experimental true
35+
```
36+
37+
The structure of the source code is following
38+
39+
```
40+
| jest/
41+
| ---- package.json
42+
| ---- packages/
43+
| -------- babel-jest/
44+
| ------------ packjage.json
45+
| -------- babel-preset-jest/
46+
| ------------ packjage.json
47+
...
48+
```
49+
50+
Top level package.json is like
51+
52+
```
53+
{
54+
"private": true,
55+
"name": "jest",
56+
"devDependencies": {
57+
"ansi-regex": "^2.0.0",
58+
"babel-core": "^6.23.1,
59+
},
60+
"workspaces": [
61+
"packages/*"
62+
]
63+
}
64+
```
65+
babel-jest
66+
```
67+
{
68+
"name": "babel-jest",
69+
"description": "Jest plugin to use babel for transformation.",
70+
"version": "19.0.0",
71+
"repository": {
72+
"type": "git",
73+
"url": "https://github.com/facebook/jest.git"
74+
},
75+
"license": "BSD-3-Clause",
76+
"main": "build/index.js",
77+
"dependencies": {
78+
"babel-core": "^6.0.0",
79+
"babel-plugin-istanbul": "^4.0.0",
80+
"babel-preset-jest": "^19.0.0"
81+
}
82+
}
83+
```
84+
85+
babel-preset-jest
86+
```
87+
{
88+
"name": "babel-preset-jest",
89+
"version": "19.0.0",
90+
"repository": {
91+
"type": "git",
92+
"url": "https://github.com/facebook/jest.git"
93+
},
94+
"license": "BSD-3-Clause",
95+
"main": "index.js",
96+
"dependencies": {
97+
"babel-plugin-jest-hoist": "^19.0.0"
98+
}
99+
}
100+
```
101+
102+
If workspaces is enabled and yarn install is run at the root level of jest Yarn would install dependencies as if the package.json contained all the dependencies of all the package.json files combined, i.e.
103+
104+
```
105+
{
106+
"devDependencies": {
107+
"ansi-regex": "^2.0.0",
108+
"babel-core": "^6.23.1,
109+
},
110+
"dependencies": {
111+
"babel-core": "^6.0.0",
112+
"babel-plugin-istanbul": "^4.0.0",
113+
"babel-preset-jest": "^19.0.0"
114+
"babel-plugin-jest-hoist": "^19.0.0"
115+
}
116+
}
117+
```
118+
119+
## Resolving conflicts
120+
121+
The algorithm is the same as in Yarn's [hoisting algorithm](https://github.com/yarnpkg/yarn/blob/master/src/package-hoister.js) during linking phase.
122+
123+
In the example above babel-core is used in both top level package.json and one of the workspaces.
124+
Yarn will resolve the highest possible common version and install it.
125+
If versions are conflicting Yarn will install install the most common used one at the root level and install the other versions in each of workspaces folder.
126+
127+
This should be enough for Node.js to resolve required dependencies when running in each of the workspaces.
128+
129+
### Note: In the first implementation workspaces level hoisting won't be implemented and Yarn would throw an error in case of dependency conflicts between packages.
130+
131+
### Note: linking, i.e. workspaces referring each other is not covered in this RFC, it will come in a next phase
132+
133+
## yarn.lock
134+
135+
After running yarn install at the top level Yarn will generate a yarn.lock for all the used dependencies at the root level in workspaces and save it only at the root level.
136+
Yarn won't save yarn.lock files at workspaces' folders.
137+
138+
139+
## Running yarn install in workspaces folders
140+
141+
Yarn will automatically run all commands as if running in the root folder, i.e. install won't install node_modules in workspaces' folders individually.
142+
143+
## Check command and integrity check
144+
145+
Changes will be needed to [check command](https://github.com/yarnpkg/yarn/blob/master/src/cli/commands/check.js) and [integrity-checker](https://github.com/yarnpkg/yarn/blob/master/src/integrity-checker.js) considering the new patterns added during resolve phase.
146+
147+
148+
# Drawbacks
149+
150+
Not sure how exactly cross-platform symlinks are today. However it looks like
151+
[Microsoft might be catching up](https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/) on this issue.
152+
153+
# Alternatives
154+
155+
Lerna as used in [jest](https://github.com/facebook/jest) now.
156+
Having multi-project dependency management natively in Yarn gives us a more cohesive user experience and because Yarn has access to dependency resolution graph the whole solution should provide more features than a wrapper like Lerna.
157+
158+
# Unresolved questions
159+
160+
Running lifecycle scripts may cause unexpected results if they require a specific folder structure in node_modules.

0 commit comments

Comments
 (0)