217 lines
5.8 KiB
Markdown
217 lines
5.8 KiB
Markdown
# Getting Started with Package-Based Repos
|
|
|
|
## Create a New Workspace
|
|
|
|
Start by creating a new workspace. We can use the following command that will help us set it up.
|
|
|
|
```bash
|
|
npx create-nx-workspace@latest package-based --preset=npm
|
|
```
|
|
|
|
The file structure should look like this:
|
|
|
|
```treeview
|
|
myorg/
|
|
├── packages/
|
|
├── nx.json
|
|
└── package.json
|
|
```
|
|
|
|
## Create a Package
|
|
|
|
The `packages` folder is where we host our monorepo libraries. Create a new `is-even` folder with the following structure:
|
|
|
|
```treeview
|
|
packages/
|
|
└── is-even/
|
|
├── index.ts
|
|
└── package.json
|
|
```
|
|
|
|
Before proceeding, make sure you install TypeScript as we're going to use it to build our package. While we could install TypeScript at the package-level, it is more convenient to have it globally for the entire monorepo. Run the following command at the root of your workspace.
|
|
|
|
```bash
|
|
npm i typescript -D -W
|
|
```
|
|
|
|
Now update the content of the files to match the following:
|
|
|
|
{% tabs %}
|
|
{% tab label="index.ts" %}
|
|
|
|
```ts {% fileName="packages/is-even/index.ts" %}
|
|
export const isEven = (x: number) => x % 2 === 0;
|
|
```
|
|
|
|
{% /tab %}
|
|
{% tab label="package.json" %}
|
|
|
|
```json {% fileName="packages/is-even/package.json" %}
|
|
{
|
|
"name": "@package-based/is-even",
|
|
"version": "0.0.0",
|
|
"main": "dist/index.js",
|
|
"devDependencies": {},
|
|
"scripts": {
|
|
"build": "tsc index.ts --outDir dist"
|
|
}
|
|
}
|
|
```
|
|
|
|
{% /tab %}
|
|
{% /tabs %}
|
|
|
|
Update the `.gitignore` file to make sure you have a `dist` entry (without a leading slash) to ignore the `dist` folder inside the `is-even` package.
|
|
|
|
Note, the `build` uses TypeScript to compile the `index.ts` file into a project-level `./dist` folder. To run it use:
|
|
|
|
```bash
|
|
npx nx build is-even
|
|
```
|
|
|
|
## Local Linking of Packages
|
|
|
|
Linking packages locally in a package-based monorepo style is done with NPM/Yarn/PNPM workspaces. In this specific setup we use NPM workspaces (see `package.json` at the root of this monorepo).
|
|
|
|
To illustrate how packages can be linked locally, let's create another package `is-odd`. You can copy the existing `is-even` package:
|
|
|
|
```treeview
|
|
packages/
|
|
└── is-even/
|
|
├── ...
|
|
└── is-odd/
|
|
├── index.ts
|
|
└── package.json
|
|
```
|
|
|
|
Here's what the content of the files should look like:
|
|
|
|
{% tabs %}
|
|
{% tab label="index.ts" %}
|
|
|
|
```ts {% fileName="packages/is-odd/index.ts" %}
|
|
import { isEven } from '@package-based/is-even';
|
|
|
|
export const isOdd = (x: number) => !isEven(x);
|
|
```
|
|
|
|
{% /tab %}
|
|
{% tab label="package.json" %}
|
|
|
|
```json {% fileName="packages/is-odd/package.json" %}
|
|
{
|
|
"name": "@package-based/is-odd",
|
|
"version": "0.0.0",
|
|
"main": "dist/index.js",
|
|
"devDependencies": {},
|
|
"scripts": {
|
|
"build": "tsc index.ts --outDir dist"
|
|
},
|
|
"dependencies": {
|
|
"@package-based/is-even": "*"
|
|
}
|
|
}
|
|
```
|
|
|
|
{% /tab %}
|
|
{% /tabs %}
|
|
|
|
`is-odd` imports the `isEven` function from `@package-based/is-even`. Therefore its `package.json` file should list the `is-even` package in its `package.json` file as a dependency.
|
|
|
|
The `workspaces` property in the root-level `package.json` tells NPM (and it similar for Yarn or PNPM workspaces) to locally-link the two packages, without the need to publish them first to a NPM registry.
|
|
|
|
At the root of your workspace run
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
This allows the NPM workspace to properly link the new `is-odd` package.
|
|
|
|
## Task Dependencies
|
|
|
|
Most monorepos have dependencies not only among different packages, but also among their tasks.
|
|
|
|
For example, whenever we build `is-odd` we need to ensure that `is-even` is built beforehand. Nx can define such task dependencies by adding a `targetDefaults` property to `nx.json`.
|
|
|
|
```json {% fileName="nx.json" %}
|
|
{
|
|
...
|
|
"targetDefaults": {
|
|
"build": {
|
|
"dependsOn": ["^build"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
This tells Nx to run the `build` target of all the dependent projects first, before the `build` target of the package itself is being run.
|
|
|
|
Remove any existing `dist` folder and run:
|
|
|
|
```bash
|
|
npx nx build is-odd
|
|
```
|
|
|
|
It will automatically first run `npx nx build is-even` and then the build for `is-odd`. Note that if `is-even` has been built before, it would just be restored out of the cache.
|
|
|
|
## Cache Build Results
|
|
|
|
To build the `is-even` package run:
|
|
|
|
```bash
|
|
npx nx build is-even
|
|
```
|
|
|
|
Run the same command a second time and you'll see the build cache is being used:
|
|
|
|
```bash
|
|
> nx build is-even
|
|
|
|
> nx run is-even:build
|
|
|
|
> @package-based/is-even@0.0.0 build
|
|
> tsc index.ts --outDir dist
|
|
|
|
—————————————————————————————————————————————————————————————————
|
|
|
|
> NX Successfully ran target build for project is-even (1s)
|
|
```
|
|
|
|
## Running Multiple Tasks
|
|
|
|
To run the `build` target for all the packages in the workspace, use:
|
|
|
|
```bash
|
|
npx nx run-many --target=build
|
|
```
|
|
|
|
What you would get is the following:
|
|
|
|
```bash
|
|
> npx nx run-many --target=build
|
|
|
|
✔ nx run is-even:build [existing outputs match the cache, left as is]
|
|
✔ nx run is-odd:build (906ms)
|
|
|
|
—————————————————————————————————————————————————————————————————
|
|
|
|
> NX Successfully ran target build for 2 projects (914ms)
|
|
|
|
Nx read the output from the cache instead of running the command for 1 out of 2 tasks.
|
|
```
|
|
|
|
Note how on the `is-even:build` it didn't run the build but rather pulled it out of the cache because the build has ran before. If you re-run the `run-many` command all of the builds would be cached.
|
|
|
|
You can also only run tasks on packages that got changed by using
|
|
|
|
```bash
|
|
npx nx affected --target=build
|
|
```
|
|
|
|
## Learn More
|
|
|
|
- Read about the [core features of Nx](/core-features)
|
|
- Get a deeper understanding of the [mental model](/concepts/mental-model) behind Nx.
|
|
- [Adopt Nx](/recipes/adopting-nx) in your existing repo
|