235 lines
7.3 KiB
Markdown
235 lines
7.3 KiB
Markdown
# Getting Started with Integrated Repos
|
|
|
|
{% youtube
|
|
src="https://www.youtube.com/embed/weZ7NAzB7PM"
|
|
title="Tutorial: Getting Started with Integrated Repos"
|
|
width="100%" /%}
|
|
|
|
{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/integrated" /%}
|
|
|
|
## Create a New Workspace
|
|
|
|
Start by creating a new workspace. We can use the following command that will help us set it up.
|
|
|
|
```shell
|
|
npx create-nx-workspace@latest myorg --preset=ts
|
|
```
|
|
|
|
The file structure should look like this:
|
|
|
|
```treeview
|
|
myorg/
|
|
├── packages/
|
|
├── tools/
|
|
├── nx.json
|
|
├── package.json
|
|
├── README.md
|
|
└── tsconfig.base.json
|
|
```
|
|
|
|
## Create a Package
|
|
|
|
Nx comes with generators that can help with scaffolding applications. Run this generator to make a new library named `is-even`:
|
|
|
|
```shell
|
|
npx nx generate @nrwl/js:library is-even --publishable --importPath @myorg/is-even
|
|
```
|
|
|
|
This command:
|
|
|
|
- Uses the `@nrwl/js` plugin's `library` generator to scaffold a new library named `is-even`.
|
|
- The `--publishable` flag makes sure we also get a `package.json` generated and a `publish` target we can invoke to publish to NPM.
|
|
- The `--importPath` allows us to define the name of the NPM package.
|
|
|
|
You should now have the following structure:
|
|
|
|
```treeview
|
|
packages/
|
|
└── is-even/
|
|
├── src/
|
|
| └── lib/
|
|
| | ├── is-even.spec.ts
|
|
| | ├── is-even.ts
|
|
| └── index.ts
|
|
├── project.json
|
|
├── package.json
|
|
├── ...
|
|
└── tsconfig.json
|
|
```
|
|
|
|
Update `is-even.ts` with this content:
|
|
|
|
```ts {% fileName="packages/is-even/src/lib/is-even.ts" %}
|
|
export function isEven(x: number): boolean {
|
|
return x % 2 === 0;
|
|
}
|
|
```
|
|
|
|
The Nx plugins use a project-level `project.json` to manage the metadata around the available targets that can be run for a given project. The generated `project.json` for `is-even` contains `build`, `publish`, `lint` and `test` targets:
|
|
|
|
```jsonc {% fileName="packages/is-even/project.json" %}
|
|
{
|
|
"name": "is-even",
|
|
"targets": {
|
|
"build": {
|
|
/* ... */
|
|
},
|
|
"publish": {
|
|
/* ... */
|
|
},
|
|
"lint": {
|
|
/* ... */
|
|
},
|
|
"test": {
|
|
/* ... */
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
You can dive into the various settings to fine-tune the options used for building, publishing, linting or testing the package. The low-level details are being taken care of by the plugin.
|
|
|
|
Running
|
|
|
|
- `npx nx build is-even` builds the src files and places a ready-to-be-published package in `dist/packages/is-even` at the root of your workspace
|
|
- `npx nx publish is-even` runs a publish script from `dist/packages/is-even` to push your package to NPM
|
|
- `npx nx test is-even` runs the pre-configured Jest tests for the package
|
|
- `npx nx lint is-even` runs the pre-configured ESLint checks for the package
|
|
|
|
## Local Linking of Packages
|
|
|
|
The local linking of packages in an integrated monorepo style is handled by Nx automatically by leveraging TypeScript path mappings in the `tsconfig.base.json` file.
|
|
|
|
To illustrate that, let's create another package `is-odd`. We can again run the generator for that:
|
|
|
|
```shell
|
|
npx nx generate @nrwl/js:library is-odd --publishable --importPath @myorg/is-odd
|
|
```
|
|
|
|
Note how the `tsconfig.base.json` now has two entries:
|
|
|
|
```json {% fileName="tsconfig.base.json" %}
|
|
{
|
|
"compileOnSave": false,
|
|
"compilerOptions": {
|
|
...
|
|
"paths": {
|
|
"@myorg/is-even": ["packages/is-even/src/index.ts"],
|
|
"@myorg/is-odd": ["packages/is-odd/src/index.ts"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Update the `is-odd.ts` implemention in the `is-odd` package to import `isEven` from the `@myorg/is-even` package:
|
|
|
|
```ts {% fileName="packages/is-odd/src/lib/is-odd.ts" %}
|
|
import { isEven } from '@myorg/is-even';
|
|
|
|
export function isOdd(x: number): boolean {
|
|
return !isEven(x);
|
|
}
|
|
```
|
|
|
|
This is all that needs to be done.
|
|
|
|
## Task Dependencies
|
|
|
|
In a monorepo there are not just dependencies among 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.
|
|
|
|
In an integrated monorepo style this is already being dealt with by the generators. The current `nx.json` file already comes with defaults that work out of the box:
|
|
|
|
```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 at the root of the workspace and run:
|
|
|
|
```shell
|
|
npx nx build is-odd
|
|
```
|
|
|
|
It will automatically first run `npx nx build is-even`, so you should end up with both packages in your dist folder. 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:
|
|
|
|
```shell
|
|
npx nx build is-even
|
|
```
|
|
|
|
Run the same command a second time and you'll see the build cache is being used:
|
|
|
|
```{% command="npx nx build is-even" %}
|
|
> nx run is-even:build
|
|
|
|
Compiling TypeScript files for project "is-even"...
|
|
Done compiling TypeScript files for project "is-even".
|
|
|
|
—————————————————————————————————————————————————————————————————————
|
|
|
|
> NX Successfully ran target build for project is-even (713ms)
|
|
```
|
|
|
|
## Running Multiple Tasks
|
|
|
|
To run the `build` target for all the packages in the workspace, use:
|
|
|
|
```shell
|
|
npx nx run-many --target=build
|
|
```
|
|
|
|
What you would get is the following:
|
|
|
|
```{% command="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
|
|
|
|
```shell
|
|
npx nx affected --target=build
|
|
```
|
|
|
|
## Learn More
|
|
|
|
{% cards %}
|
|
|
|
{% card title="Core Features" description="Read about the core features of Nx." url="/core-features" /%}
|
|
|
|
{% card title="Mental Model" description="Get a deeper understanding of the mental model." url="/concepts/mental-model" /%}
|
|
|
|
{% card title="Adopting Nx" description="Learn how to add Nx to your existing repo." url="/recipes/adopting-nx" /%}
|
|
|
|
{% card title="Integrated Repos vs Package-Based Repos" description="Learn about two styles of monorepos." url="/concepts/integrated-vs-package-based" /%}
|
|
|
|
{% card title="React Tutorial" description="A step-by-step tutorial showing how to build an integrated monorepo with React applications sharing code." url="/react-tutorial/1-code-generation" /%}
|
|
|
|
{% card title="Node.js Tutorial" description="A step-by-step tutorial showing how to build an integrated monorepo with Node.js applications sharing code." url="/getting-started/node-server-tutorial" /%}
|
|
|
|
{% /cards %}
|