Skip to content

Commit 4368a2c

Browse files
committed
Updated README.md
1 parent 10b556e commit 4368a2c

File tree

1 file changed

+34
-236
lines changed

1 file changed

+34
-236
lines changed

apps/rush/README.md

Lines changed: 34 additions & 236 deletions
Original file line numberDiff line numberDiff line change
@@ -1,260 +1,58 @@
11
# @microsoft/rush
22

3-
## Why Rush?
4-
A typical web project may consume hundreds of NPM packages, each developed
5-
independently by a random stranger somewhere on the internet. Each project
6-
has its own Git repository, is conceptually self-contained, and tries to
7-
maintain an API contract conforming to [SemVer](http://semver.org/). When
8-
there is a bug in one of these packages, a pull request is merged, the version
9-
is bumped, and a new release is published. The new release then begins a
10-
slow propagation across the internet, as each downstream project upgrades
11-
and reacts to any incompatibilities that may arise in a delightful symphony
12-
of distributed collaboration.
133

14-
At the root of this massive dependency tree is your client-side web application.
15-
Unlike everything else, it is one huge monolith. The bigger it grows,
16-
the more you begin to think "This is stupid -- we should break this thing up
17-
into 30 small NPM packages that can be reused and versioned independently."
18-
One heroic Saturday night, you create 30 Git repos and refactor everything.
4+
![rush](https://github.com/Microsoft/web-build-tools/blob/master/common/wiki-images/rush-logo.png)
5+
<br />
6+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; https://aka.ms/rush
197

20-
Eventually people start complaining. Your team isn't 30 strangers making
21-
frivolous little "left-pad" utilities. They are application developers
22-
creating a mission-critical product with messy business logic. The components
23-
interact in complex ways, and every time you change one package, you seem
24-
to be breaking other packages. It feels wrong to be cloning and building
25-
30 different Git repositories every day, when there's only 10 people on your team.
26-
Publishing is getting tedious. Running "npm link" is a minefield. This is no
27-
way to work!
8+
<!-- -------------------------------------------------------------------------- -->
9+
<!-- Text below this line should stay in sync with Rush.md from the GitHub wiki -->
10+
<!-- -------------------------------------------------------------------------- -->
2811

29-
And so, you consolidate all your NPM packages into one central Git repository, and
30-
write a script that runs "npm install", "npm link", and "gulp" 30 times, in the
31-
right order. This is way better! In the past, when Bob made a big change to a
32-
core library and then left for a backpacking trip across Europe, it could take
33-
a week for Alice to upgrade to the new version and realize that something was broken.
34-
Even though Bob caused the trouble, his victims unfairly had to shoulder the cost
35-
of debugging it. Having a unified build means that Bob _cannot even merge his PR_
36-
(let alone publish a new release) without passing all the unit tests for every
37-
downstream project. Catching problems early makes everyone more efficient.
38-
Having a central repository forces library owners pay attention to the source code
39-
and PRs that consume their APIs; no more "out of sight, out of mind."
12+
**Rush** makes life easier for JavaScript developers who build and publish many NPM packages at once. If you're looking to consolidate all your projects into a single repo, you came to the right place! Rush is a fast, professional solution for managing this scenario. It gives you:
4013

41-
There is just one problem... Builds are slowwwww. If "npm install" takes
42-
1 minute (on a good day), then 30 installs take 30 minutes. Building 30 small projects
43-
is slower than building one big project. Other details like managing
44-
[shrinkwrap](https://docs.npmjs.com/cli/shrinkwrap) and publishing can be tricky.
14+
- **A single NPM install:** In one step, Rush installs all the dependencies for all your projects into a common folder. This is not just a "package.json" file at the root of your repo (which might set you up to accidentally `require()` a sibling's dependencies). Instead, Rush uses symlinks to reconstruct an accurate "node_modules" folder for each project, without any of the limitations or glitches that seem to plague other approaches.
4515

46-
## Rush is here to help!
16+
- **Automatic local linking:** Inside a Rush repo, all your projects are automatically symlinked to each other. When you make a change, you can see the downstream effects without publishing anything, and without any "npm link" headaches.
4717

48-
Rush formalizes this model and makes it quick. It works completely within
49-
the conventional NPM system: Each package will still have its own Gulpfile.
50-
Each package can still run "npm install" without Rush if desired.
51-
You are always free to move your projects around between Git repositories
52-
without any changes to package.json.
18+
- **Fast builds:** Rush detects your dependency graph and builds your projects in the right order. If two packages don't directly depend on each other, Rush parallelizes their build as separate NodeJS processes (and showing live console output in a [readable order](https://www.npmjs.com/package/@microsoft/stream-collator)). In practice this multi-process approach can yield more significant gains than all those async functions in your single-threaded Gulpfile.
5319

54-
But when you use Rush, you get some big improvements:
20+
- **Subset and incremental builds:** If you only plan to work with a few projects from your repo, `rush rebuild --to <project>` does a clean build of just your upstream dependencies. After you make changes, `rush rebuild --from <project>` does a clean build of the affected downstream projects. And if your toolchain is [package-deps-hash](https://www.npmjs.com/package/@microsoft/package-deps-hash) enabled, `rush build` delivers a powerful cross-project incremental build (that also supports subset builds).
5521

56-
- Save time by installing all dependencies for all packages via a single
57-
"npm install" invocation
22+
- **Cyclic dependencies:** If you have hammers that build hammer factory factories, Rush has you covered. When a package indirectly depends on an older version of itself, projects in the cycle use the last published version, whereas other projects still get the latest bits.
5823

59-
- Rush automatically generates a shrinkwrap file for the entire repository.
60-
NPM shrinkwrap is the only way to avoid maddening problems of "what are you talking
61-
about, it works on my PC!"
24+
- **Bulk publishing:** When it's time to do a release, Rush can detect which packages have changes, automatically bump all the appropriate version numbers, and run "npm publish" in each folder. If you like, configure your server to automatically run "rush publish" every hour.
6225

63-
- All projects are automatically hooked up with "npm link" (using local
64-
symlinks so multiple Git folders won't get cross-linked)
26+
- **Changelog tracking:** Whenever a PR is created, you can require developers to provide a major/minor/patch log entry for the affected projects. During publishing, these changes will be automatically aggregated into a nicely formatted [CHANGELOG.md](https://github.com/Microsoft/web-build-tools/blob/master/core-build/web-library-build/CHANGELOG.md) file.
6527

66-
- A dependency solver uses package.json to automatically determine
67-
the build order.
28+
- **Enterprise policies:** Want to review new libraries before developers add them to package.json, but avoid hassling people about already approved cases? Want to enforce that all your projects depend on the same library version numbers? Are dorky personal e-mail addresses showing up in your company's Git history? Rush can help maintain a consistent ecosystem when you've got many developers and many projects in the mix.
6829

69-
- Since each project has its own Gulpfile, Rush can spawn multiple NodeJS
70-
processes in parallel, making the build go significantly faster. (No matter
71-
how many promises you write, your Gulpfile is still fundamentally single-threaded.)
30+
- **Lots more!** Rush was created by the platform team for [Microsoft SharePoint](http://aka.ms/spfx). We build hundreds of production NPM packages every day, from internal and public Git repositories, for third party SDKs and live services with millions of users. If there's an important package management problem that needs solvin', it's likely to end up as a feature for Rush.
7231

73-
- Use a single command to run "npm publish" for many packages
32+
# 3 Minute Demo
7433

75-
- Git-based incremental builds, so you only rebuild a project if a source file
76-
in that project folder has changed.
77-
78-
- Support for cyclic dependencies: For example, suppose that **my-gulp-task**
79-
depends on **my-library**, but **my-library**'s Gulpfile has a devDependency
80-
on **my-gulp-task**. Rush can install the last published version of these
81-
packages for the Gulpfile, while still creating local links for other
82-
projects outside the cyclic dependency.
83-
84-
- Support for enforcing certain Git policies, such as enforcing that Git committer
85-
email addresses conform to a well-defined pattern.
86-
87-
# Usage
88-
89-
At any time, you can see the `--help` flag to find command-line usage information.
90-
91-
## Building a repo that is configured for Rush
92-
93-
1. Run "**npm install -g @microsoft/rush**". To confirm that it's working,
94-
run "rush -h" which prints the version number and usage information.
95-
96-
2. From anywhere in your git working folder, run "**rush install**". This
97-
will install NPM modules in Rush's "Common" folder.
98-
99-
NOTE: If you are troubleshooting build issues, try
100-
"**rush install --full-clean**" instead.
101-
102-
3. From anywhere in your Git working folder, run "**rush link**". This creates
103-
symlinks so that all the projects will reuse the packages from "common/node_modules"
104-
(rather than having to run "npm install" in each project folder). It will
105-
also link projects to the folders for their local dependencies, so that you don't need
106-
to do "npm publish" to test your changes.
107-
108-
NOTE: The "**rush.json**" config file specifies how this linking is performed.
109-
110-
> IMPORTANT: DO NOT run "npm install" inside project folders that have been linked
111-
> by the Rush tool. If you want to do that, you need to "**rush unlink**" first.
112-
113-
4. Do your initial build by running "**rush rebuild**" . This will
114-
recurse through each project folder and run "gulp clean", "gulp",
115-
and "gulp test", and then give you a report of anything that failed to build.
116-
117-
NOTE: To suppress verbose output, use "**rush rebuild -q**".
118-
119-
## Pull -> Edit -> Build -> Run -> Push
120-
121-
The above steps are only necessary when you need to do a clean full build (e.g.
122-
after pulling changes that affected common/package.json). Otherwise, you can
123-
run "gulp" in individual project folders as usual. Your daily workflow will
124-
look like this:
125-
126-
1. Pull the latest changes from git.
127-
128-
2. If something changed in the **common** folder, then you may need to update
129-
your NPM:
130-
131-
> C:\MyRepo> **rush install**
132-
>
133-
> C:\MyRepo> **rush link**
134-
>
135-
> C:\MyRepo> **rush rebuild -q**
136-
137-
3. Debug a project:
138-
139-
> C:\MyRepo> **cd my-project**
140-
>
141-
> C:\MyRepo\my-project> **gulp serve**
142-
143-
## Configuring a project to be built by Rush
144-
145-
Once a project has been added to the `rush.json` file, several commands must be defined in the
146-
project's `package.json` file, under the `scripts` section. Every project must define a `clean`
147-
script. Additionally, every project must define either a `test` or `build` command. By default,
148-
Rush will default to using the `test` command if both are defined, but will fall back to `build`
149-
if `test` is missing.
150-
151-
The defined commands should either reference something on the `PATH` or should be an absolute path.
152-
If the command is defined simply as `gulp`, the version of gulp from the common folder's `node_modules/.bin`
153-
folder will be used.
154-
155-
An example configuration is below:
156-
157-
```json
158-
{
159-
"name": "my-project",
160-
"version": "1.0.0",
161-
"scripts": {
162-
"clean": "gulp clean",
163-
"build": "gulp",
164-
"test": "/usr/bin/testcommand --compile --things"
165-
}
166-
}
34+
See Rush in action! From your shell, install the tool like this:
16735
```
168-
169-
## If you need to modify your package.json
170-
171-
If you need to add new dependencies to your package.json, you will need to
172-
regenerate the files in the common folder. Use these commands:
173-
174-
> C:\MyRepo> **rush generate**
175-
>
176-
> C:\MyRepo> **rush link**
177-
178-
This will change various generated files in common folder. You should include these
179-
changes in your Pull Request.
180-
181-
The "**rush generate**" command takes a long time. To speed up debugging, you can use
182-
"**rush generate --lazy**" instead; however you must run the full "**rush generate**"
183-
before submitting your PR.
184-
185-
## Publishing your NPM packages
186-
187-
To publish all NPM projects in your repository, run "**rush publish**". You
188-
can select a subset of projects using the "**--include**" option followed by
189-
a [glob](https://en.wikipedia.org/wiki/Glob_(programming)) pattern. You can
190-
use the "**--registry**" option to specify a custom NPM registry, e.g. if you
191-
are testing with [Verdaccio](https://github.com/verdaccio/verdaccio).
192-
193-
## Converting a repo to build with Rush
194-
195-
Currently you need to manually create an "rush.json" configuration file
196-
at the root of your repository, which specifies the list of projects
197-
to be built. You also need to set up your "common" folder, and add the
198-
appropriate files to Git. (We are working on an "rush init" command to
199-
simplify this.)
200-
201-
## Detecting when new NPM dependencies are introduced
202-
203-
Suppose that your Rush repo has 30 different projects, and you want to keep track of
204-
what NPM packages people are using. When someone finds a new package and tries to add
205-
it to their project, you want to ask questions like: "Is this a good quality package?"
206-
"Are we already using a different library that does the same thing?" "Is the license
207-
allowed?" "How many other dependencies will this pull into our node_modules folder?"
208-
Rush can alert you when this happens.
209-
210-
In your **rush.json** file, add these optional fields:
211-
212-
```json
213-
"reviewCategories": [ "published", "internal", "experiment" ],
214-
"packageReviewFile": "common/PackageDependencies.json",
36+
$ npm install -g @microsoft/rush
21537
```
21638

217-
In this example, we defined three kinds of projects that we care about:
218-
Projects that we publish externally, projects kept internal to our company,
219-
and throwaway experiments. For each project in the repo, we will assign one
220-
of these categories as the "reviewCategory" field.
221-
222-
The **PackageDependencies.json** file contains the list of approved packages.
223-
This file should be added to Git. It might look like this:
39+
For command-line help, do this:
40+
```
41+
$ rush -h
42+
```
22443

225-
```json
226-
{
227-
"browserPackages": [
228-
{
229-
"name": "lodash",
230-
"allowedCategories": [ "internal", "experiment" ]
231-
}
232-
],
233-
"nonBrowserPackages": [
234-
{
235-
"name": "gulp",
236-
"allowedCategories": [ "published", "internal", "experiment" ]
237-
},
238-
{
239-
"name": "some-tool",
240-
"allowedCategories": [ "experiment" ]
241-
}
242-
]
243-
}
44+
To see Rush build some real projects, try running these commands: :-)
45+
```
46+
$ git clone https://github.com/Microsoft/web-build-tools
47+
$ cd web-build-tools
48+
$ rush install --bypass-policy
49+
$ rush rebuild
24450
```
24551

246-
Above, we specified that only our internal projects and experiments are allowed
247-
to use "lodash", whereas "gulp" is allowed everywhere. The "some-tool" library
248-
is being used by an experimental prototype, but should never be used in real projects.
52+
<!-- -------------------------------------------------------------------------- -->
53+
<!-- Text above this line should stay in sync with Rush.md from the GitHub wiki -->
54+
<!-- -------------------------------------------------------------------------- -->
24955

250-
Note that Rush distinguishes "**browserPackages**" from "**nonBrowserPackages**",
251-
since the approval criteria is generally different for these environments.
56+
# Getting Started
25257

253-
Now, suppose someone changes their package.json to add "lodash" to a project that
254-
was designated as "published". When they run "rush generate", Rush will automatically
255-
rewrite the **PackageDependencies.json** file, appending "published" to the
256-
"allowedCategories" for "lodash". In other words, it automatically broadens the rules
257-
so that they describe reality. When the pull request is created, reviewers will spot this diff
258-
and can ask appropriate questions. Since our criteria is based on generalized categories,
259-
the reviewers aren't hassled about every little package.json change; a **PackageDependencies.json**
260-
diff only appears for genuinely interesting changes.
58+
The GitHub wiki has complete, up-to-date documentation: https://aka.ms/rush

0 commit comments

Comments
 (0)