docs(nxdev): new intro and package-based and integrated style tutorials

This commit is contained in:
Isaac Mann 2022-09-30 16:01:59 -04:00 committed by Juri Strumpflohner
parent a947e25149
commit 41e2c84c7d
13 changed files with 667 additions and 25 deletions

View File

@ -15,9 +15,14 @@
"file": "shared/getting-started/intro" "file": "shared/getting-started/intro"
}, },
{ {
"name": "Core Tutorial", "name": "Package-Based Repo Tutorial",
"id": "core-tutorial", "id": "package-based-repo-tutorial",
"file": "shared/core-tutorial/01-create-blog" "file": "shared/npm-tutorial/package-based"
},
{
"name": "Integrated Repo Tutorial",
"id": "integrated-repo-tutorial",
"file": "shared/npm-tutorial/integrated"
}, },
{ {
"name": "React Tutorial", "name": "React Tutorial",

View File

@ -8,7 +8,7 @@ width="100%" /%}
In this tutorial you use Nx to build a full-stack application out of common libraries using modern technologies like Cypress and Nest. In this tutorial you use Nx to build a full-stack application out of common libraries using modern technologies like Cypress and Nest.
{% callout type="check" title="Integrated Repo" %} {% callout type="check" title="Integrated Repo" %}
This tutorial sets up an [integrated repo](/concepts/integrated-vs-package-based). If you prefer a [package-based repo](/concepts/integrated-vs-package-based), check out the [Core Tutorial](/getting-started/core-tutorial). This tutorial sets up an [integrated repo](/concepts/integrated-vs-package-based). If you prefer a [package-based repo](/concepts/integrated-vs-package-based), check out the [Package-Based Repo Tutorial](/getting-started/package-based-repo-tutorial).
{% /callout %} {% /callout %}
## Contents ## Contents

View File

@ -2,6 +2,7 @@
- [Incremental Builds](/more-concepts/incremental-builds) - [Incremental Builds](/more-concepts/incremental-builds)
- [Nx and Turborepo](/more-concepts/turbo-and-nx) - [Nx and Turborepo](/more-concepts/turbo-and-nx)
- [Nx and the Angular CLI](/more-concepts/nx-and-angular)
- [Monorepos](/more-concepts/why-monorepos) - [Monorepos](/more-concepts/why-monorepos)
- [Using Nx at Enterprises](/more-concepts/monorepo-nx-enterprise) - [Using Nx at Enterprises](/more-concepts/monorepo-nx-enterprise)
- [Nx Daemon](/more-concepts/nx-daemon) - [Nx Daemon](/more-concepts/nx-daemon)

View File

@ -2,28 +2,57 @@
Nx is a smart, fast and extensible build system with first class monorepo support and powerful integrations. Nx is a smart, fast and extensible build system with first class monorepo support and powerful integrations.
## Philosophy {% personas %}
{% persona type="javascript" title="New Package-Based Repo" url="/getting-started/package-based-repo-tutorial" %}
Create a monorepo with Yarn, NPM or PNPM. Nx makes it fast, but lets you run things your way.
Nx has a similar design philosophy to Visual Studio Code. VSCode is a powerful text editor, and you can be very productive - [Get started with your package-based repo](/getting-started/package-based-repo-tutorial)
with it even if you don't install any extensions. The ecosystem of VSCode's extensions though is what can really level
up your productivity.
Nx is similar. The core of Nx is generic, simple, and unobtrusive. Nx plugins, although very useful for many projects, {% /persona %}
are completely optional.
Most examples on this site use Nx plugins (integrated repo style). It's just easier to demonstrate many features Nx offers when Nx generates all {% persona type="integrated" title="New Integrated Repo" url="/getting-started/integrated-repo-tutorial" %}
the boilerplate. However, the vast majority of the features will work the same way in a workspace with no plugins (package-based repo).
Here's a deep dive on [Integrated Repos vs. Package-Based Repos](/concepts/integrated-vs-package-based) Get a pre-configured setup. Nx configures your favorite frameworks and lets you focus on shipping features.
## Getting Started - [Get started with your integrated repo](/getting-started/integrated-repo-tutorial)
- [Nx core tutorial](/core-tutorial/01-create-blog) will help you understand the core of Nx. {% /persona %}
- [Adding Nx to an existing monorepo](/recipes/adopting-nx/adding-to-monorepo) shows several paths to adopting Nx in your organization.
- [Mental model](/concepts/mental-model) is a good starting point for those who like to understand things theoretically first.
If you want to use Nx plugins to really level up your productivity, pick one of the following tutorials: {% persona type="lerna" title="Add to an Existing Monorepo" url="/recipe/adding-to-monorepo" %}
- [Nx and Node](/node-tutorial/01-create-application) Incrementally add Nx to your repo and enjoy faster CI runs and local development. All without modifying your existing setup.
- [Nx and React](/react-tutorial/01-create-application)
- [Nx and Angular](/angular-tutorial/01-create-application) - [Add Nx to an Existing Monorepo](/recipe/adding-to-monorepo)
{% /persona %}
{% persona type="angular" title="Enter Modern Angular" url="/recipe/migration-angular" %}
Enhance your Angular development experience by leveraging its advanced generators and integrations with modern tooling.
- [Switch from the Angular CLI to Nx](/recipe/migration-angular)
{% /persona %}
{% /personas %}
If you know other tools in the monorepo space, here is how Nx compares:
- [Monorepo.tools](https://monorepo.tools)
- [Nx and Turborepo](/more-concepts/turbo-and-nx)
## Nx Has Two Goals
**Speed up your existing workflow with minimum effort.**
- Never rebuild the same code twice by [caching task results](/core-features/cache-task-results).
- Only [run tasks affected by the current PR](/core-features/run-tasks#run-tasks-affected-by-a-pr).
- [Distribute your task execution](/core-features/distribute-task-execution) across multiple agents in CI.
These features can be enabled without touching your existing workflows if you use Nx with a [package-based repo](/concepts/integrated-vs-package-based).
**Provide a first-rate developer experience no matter the size of the repo:**
- Encode common coding tasks in [code generators](/plugin-features/use-code-generators) to make them easily repeatable.
- Offload the maintenance burden of [updating dependencies and configuration files](/core-features/automate-updating-dependencies) to the Nrwl team.
- [Enforce project boundaries](/core-features/enforce-project-boundaries) based on your own organization structure.
These features and the [integrated repository](/concepts/integrated-vs-package-based) mindset allow large teams to collaborate in a single monorepo without getting in each other's way.

View File

@ -81,7 +81,7 @@ third_party # nx will ignore everything in the third-party dir
### Enabling JS Analysis ### Enabling JS Analysis
After running `add-nx-to-monorepo` Nx will only analyze `package.json` files like Lerna or Turborepo. After running `add-nx-to-monorepo` Nx will only analyze `package.json` files in the same way Lerna or Turborepo do.
```json ```json
{ {

View File

@ -18,7 +18,7 @@ For a discussion on #2, see [dependency management](#dependency-management) belo
## Speed up Lerna with Nx's powerful task scheduler ## Speed up Lerna with Nx's powerful task scheduler
Nx comes with a powerful task scheduler that intelligenty runs operations and makes sure they are quick. This happens in a variety of ways: Nx comes with a powerful task scheduler that intelligently runs operations and makes sure they are quick. This happens in a variety of ways:
- **Parallelization and task dependencies -** Nx automatically [knows how your projects relate to each other](/more-concepts/how-project-graph-is-built). As a result, if `project-a` depends on `project-b` and you run the build command for `project-a`, Nx first runs the builds for all of `project-a`'s dependencies and then the invoked project itself. Nx sorts these tasks to maximize parallelism. - **Parallelization and task dependencies -** Nx automatically [knows how your projects relate to each other](/more-concepts/how-project-graph-is-built). As a result, if `project-a` depends on `project-b` and you run the build command for `project-a`, Nx first runs the builds for all of `project-a`'s dependencies and then the invoked project itself. Nx sorts these tasks to maximize parallelism.
- **Only run what changed -** Using [Nx affected commands](/concepts/affected) you only really execute tasks on the projects that changed, compared to a given baseline (usually the main branch). - **Only run what changed -** Using [Nx affected commands](/concepts/affected) you only really execute tasks on the projects that changed, compared to a given baseline (usually the main branch).

View File

@ -8,7 +8,7 @@ width="100%" /%}
In this tutorial you use Nx to build a server application out of common libraries using modern technologies. In this tutorial you use Nx to build a server application out of common libraries using modern technologies.
{% callout type="check" title="Integrated Repo" %} {% callout type="check" title="Integrated Repo" %}
This tutorial sets up an [integrated repo](/concepts/integrated-vs-package-based). If you prefer a [package-based repo](/concepts/integrated-vs-package-based), check out the [Core Tutorial](/getting-started/core-tutorial). This tutorial sets up an [integrated repo](/concepts/integrated-vs-package-based). If you prefer a [package-based repo](/concepts/integrated-vs-package-based), check out the [Package-Based Repo Tutorial](/getting-started/package-based-repo-tutorial).
{% /callout %} {% /callout %}
## Contents ## Contents

View File

@ -0,0 +1,219 @@
# Getting Started with Integrated 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 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`:
```bash
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:
```bash
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:
```bash
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:
```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
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:
```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](/core-features) and [plugin features](/plugin-features) of Nx
- Get a deeper understanding of the [mental model](/concepts/mental-model) behind Nx.
- [Adopt Nx](/recipes/adopting-nx) in your existing repo

View File

@ -0,0 +1,216 @@
# 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

View File

@ -12,7 +12,7 @@ Nx has first-class Next.js support, if you are looking to use it for your projec
{% /callout %} {% /callout %}
{% callout type="check" title="Integrated Repo" %} {% callout type="check" title="Integrated Repo" %}
This tutorial sets up an [integrated](/concepts/integrated-vs-package-based) repo. If you prefer a [package-based repo](/concepts/integrated-vs-package-based), check out the [Core Tutorial](/getting-started/core-tutorial). This tutorial sets up an [integrated](/concepts/integrated-vs-package-based) repo. If you prefer a [package-based repo](/concepts/integrated-vs-package-based), check out the [Package-Based Repo Tutorial](/getting-started/package-based-repo-tutorial).
{% /callout %} {% /callout %}
## Contents ## Contents

View File

@ -20,6 +20,8 @@ import { NxCloudSection } from './lib/tags/nx-cloud-section.component';
import { nxCloudSection } from './lib/tags/nx-cloud-section.schema'; import { nxCloudSection } from './lib/tags/nx-cloud-section.schema';
import { InstallNxConsole } from './lib/tags/install-nx-console.component'; import { InstallNxConsole } from './lib/tags/install-nx-console.component';
import { installNxConsole } from './lib/tags/install-nx-console.schema'; import { installNxConsole } from './lib/tags/install-nx-console.schema';
import { Persona, Personas } from './lib/tags/personas.component';
import { persona, personas } from './lib/tags/personas.schema';
import { SideBySide } from './lib/tags/side-by-side.component'; import { SideBySide } from './lib/tags/side-by-side.component';
import { sideBySide } from './lib/tags/side-by-side.schema'; import { sideBySide } from './lib/tags/side-by-side.schema';
import { Tab, Tabs } from './lib/tags/tabs.component'; import { Tab, Tabs } from './lib/tags/tabs.component';
@ -45,6 +47,8 @@ export const getMarkdocCustomConfig = (
iframe, iframe,
'install-nx-console': installNxConsole, 'install-nx-console': installNxConsole,
'nx-cloud-section': nxCloudSection, 'nx-cloud-section': nxCloudSection,
persona,
personas,
'side-by-side': sideBySide, 'side-by-side': sideBySide,
tab, tab,
tabs, tabs,
@ -62,6 +66,8 @@ export const getMarkdocCustomConfig = (
Iframe, Iframe,
InstallNxConsole, InstallNxConsole,
NxCloudSection, NxCloudSection,
Persona,
Personas,
SideBySide, SideBySide,
Tab, Tab,
Tabs, Tabs,

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,32 @@
import { Schema } from '@markdoc/markdoc';
export const personas: Schema = {
render: 'Personas',
description: 'Display multiple persons in a grid 2x2',
};
export const persona: Schema = {
render: 'Persona',
description: 'Display the enclosed content in a persona box',
children: ['paragraph', 'tag', 'list'],
attributes: {
title: {
type: 'String',
description: 'The title displayed at the top of the persona callout.',
},
type: {
type: 'String',
default: 'zahra',
required: true,
matches: ['zahra', 'logan', 'harold'],
errorLevel: 'critical',
description:
'Controls the color and image of the persona. Can be: "zahra", "logan", "harold".',
},
url: {
type: 'String',
required: true,
errorLevel: 'critical',
description: 'Link to navigate to when the card is clicked.',
},
},
};