docs(core): node and react tutorial rework (#12498)

* docs(react): update react tutorial text

* docs(react): fixes to computation cache lesson

* docs(react): reworking react tutorial

* docs(react): fixing broken links in tutorial

* docs(react): fixing broken more links in tutorial

* docs(react): fixing last broken link in tutorial

* docs(react): really fixing last broken link in tutorial

* fixing images in preview

* docs(react): cleaning up text and formatting issues

* docs(react): more fixes and cleanup

* docs(react): more fixes

* docs(react): fixing nx console broken links

* docs(react): adjusting ending summary cards

* docs(react): more typo fixes

* docs(react): incorporating victor and isaac's feedback

* docs(react): fixing broken link

* docs(react): a self-round of typo and formatting fixes

* docs(react): another round of formatting fixes

* docs(react): another small change

* docs(react): another typo fix

* docs(react): more typo fixed noticed working with node tutorial

* docs(react): making h1's consistent

* docs(react): fixing tab title for part 1

* docs(react): fixing the title

* docs(react): escaping colon in title

* docs(node): copying react tutorials as starting point

* docs(node): fixing map.json and links to other lessons

* docs(node): updating the copy-pasted react tutorial for the node example

* docs(node): more fixes after self-review

* docs(node): fixing another typo

* docs(node): Making h1's consistent

* docs(node): fixing tab title in step 1

* docs(node): fixing the title

* docs(node): escaping colon in title

* docs(core): nx graph => project graph

* docs(core): fixing titles

* docs(core): further shortening the text

* docs(core): formatting fixes

* docs(core): responding to victor comments

* docs(core): switching to new terminal code blocks

* docs(core): light and dark mode friendly images
This commit is contained in:
Zachary DeRose 2022-10-14 10:12:05 -07:00 committed by GitHub
parent 09283fb37d
commit 1298a0f6db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 1243 additions and 1833 deletions

View File

@ -11,7 +11,7 @@
"name": "Overview",
"path": "/packages/nest",
"file": "shared/nest-plugin",
"content": "Nest.js is a framework designed for building scalable server-side applications. In many ways, Nest is familiar to Angular developers:\n\n- It has excellent TypeScript support.\n- Its dependency injection system is similar to the one in Angular.\n- It emphasises testability.\n- Its configuration APIs are similar to Angular as well.\n\nMany conventions and best practices used in Angular applications can be also be used in Nest.\n\n## Setting Up Nest\n\nTo create a new workspace with Nest, run the following command:\n\n```shell\nnpx create-nx-workspace my-workspace --preset=nest\n```\n\nYarn users can use the following command instead:\n\n```shell\nyarn create nx-workspace my-workspace --preset=nest\n```\n\nTo add the Nest plugin to an existing workspace, run one the following commands:\n\n```shell\nnpm install -D @nrwl/nest\n```\n\n```shell\nyarn add -D @nrwl/nest\n```\n\n### Create Applications\n\nYou can add a new Nest application with the following command:\n\n```shell\nnx g @nrwl/nest:app my-nest-app\n```\n\n#### Application Proxies\n\nGenerating Nest applications has an option to configure other projects in the workspace to proxy API requests. This can be done by passing the `--frontendProject` with the project name you wish to enable proxy support for.\n\n```shell\nnx g @nrwl/nest:app my-nest-app --frontendProject my-angular-app\n```\n\n### Create Libraries\n\nYou can add a new Nest library with the following command:\n\n```shell\nnx g @nrwl/nest:lib my-nest-lib\n```\n\nTo make the library `buildable`, use the following command:\n\n```shell\nnx g @nrwl/nest:lib my-nest-lib --buildable\n```\n\nTo make the library `publishable`, use the following command:\n\n```shell\nnx g @nrwl/nest:lib my-nest-lib --publishable --importPath=@my-workspace/my-nest-lib\n```\n\n> Read more about [building and publishing libraries here](/more-concepts/buildable-and-publishable-libraries).\n\n### Nest Generators\n\nThe Nest plugin for Nx extends the generators provided by Nest. Any commands that can be used with the Nest CLI can also be used with the `nx` command. The `--project` flag should be used for all Nest generators.\n\n> `--project` is used to infer the root of the project where the generators will generate the files.\n\n## Using Nest\n\n### Build\n\nYou can build an application with the following command:\n\n```shell\nnx build my-nest-app\n```\n\nThis applies to `buildable` libraries as well\n\n```shell\nnx build my-nest-lib\n```\n\n#### Waiting for other builds\n\nSetting the `waitUntilTargets` option with an array of projects (with the following format: `\"project:architect\"`) will execute those commands before serving the Nest application.\n\n### Serve\n\nYou can serve an application with the following command:\n\n```shell\nnx serve my-nest-app\n```\n\nThe `serve` command runs the `build` target, and executes the application.\n\nBy default, the serve command will run in `watch` mode. This allows code to be changed, and the Nest application to be rebuilt automatically.\n\n#### Debugging\n\nNest applications also have the `inspect` flag set, so you can attach your debugger to the running instance.\n\nDebugging is set to use a random port that is available on the system. The port can be changed by setting the port option in the `serve` target in the `project.json`. Or by running the serve command with `--port <number>`.\n\nFor additional information on how to debug Node applications, see the [Node.js debugging getting started guide](https://nodejs.org/en/docs/guides/debugging-getting-started/#inspector-clients).\n\n### Lint\n\nYou can lint an application with the following command:\n\n```shell\nnx lint my-nest-app\n```\n\nYou can lint a library with the following command:\n\n```shell\nnx lint my-nest-lib\n```\n\n### Unit Test\n\nYou can run unit test for an application with the following command:\n\n```shell\nnx test my-nest-app\n```\n\nYou can run unit test for a library with the following command:\n\n```shell\nnx test my-nest-lib\n```\n\n## More Documentation\n\n- [Todo Tutorial](/node-tutorial/01-create-application)\n- [Using Jest](/packages/jest)\n"
"content": "Nest.js is a framework designed for building scalable server-side applications. In many ways, Nest is familiar to Angular developers:\n\n- It has excellent TypeScript support.\n- Its dependency injection system is similar to the one in Angular.\n- It emphasises testability.\n- Its configuration APIs are similar to Angular as well.\n\nMany conventions and best practices used in Angular applications can be also be used in Nest.\n\n## Setting Up Nest\n\nTo create a new workspace with Nest, run the following command:\n\n```shell\nnpx create-nx-workspace my-workspace --preset=nest\n```\n\nYarn users can use the following command instead:\n\n```shell\nyarn create nx-workspace my-workspace --preset=nest\n```\n\nTo add the Nest plugin to an existing workspace, run one the following commands:\n\n```shell\nnpm install -D @nrwl/nest\n```\n\n```shell\nyarn add -D @nrwl/nest\n```\n\n### Create Applications\n\nYou can add a new Nest application with the following command:\n\n```shell\nnx g @nrwl/nest:app my-nest-app\n```\n\n#### Application Proxies\n\nGenerating Nest applications has an option to configure other projects in the workspace to proxy API requests. This can be done by passing the `--frontendProject` with the project name you wish to enable proxy support for.\n\n```shell\nnx g @nrwl/nest:app my-nest-app --frontendProject my-angular-app\n```\n\n### Create Libraries\n\nYou can add a new Nest library with the following command:\n\n```shell\nnx g @nrwl/nest:lib my-nest-lib\n```\n\nTo make the library `buildable`, use the following command:\n\n```shell\nnx g @nrwl/nest:lib my-nest-lib --buildable\n```\n\nTo make the library `publishable`, use the following command:\n\n```shell\nnx g @nrwl/nest:lib my-nest-lib --publishable --importPath=@my-workspace/my-nest-lib\n```\n\n> Read more about [building and publishing libraries here](/more-concepts/buildable-and-publishable-libraries).\n\n### Nest Generators\n\nThe Nest plugin for Nx extends the generators provided by Nest. Any commands that can be used with the Nest CLI can also be used with the `nx` command. The `--project` flag should be used for all Nest generators.\n\n> `--project` is used to infer the root of the project where the generators will generate the files.\n\n## Using Nest\n\n### Build\n\nYou can build an application with the following command:\n\n```shell\nnx build my-nest-app\n```\n\nThis applies to `buildable` libraries as well\n\n```shell\nnx build my-nest-lib\n```\n\n#### Waiting for other builds\n\nSetting the `waitUntilTargets` option with an array of projects (with the following format: `\"project:architect\"`) will execute those commands before serving the Nest application.\n\n### Serve\n\nYou can serve an application with the following command:\n\n```shell\nnx serve my-nest-app\n```\n\nThe `serve` command runs the `build` target, and executes the application.\n\nBy default, the serve command will run in `watch` mode. This allows code to be changed, and the Nest application to be rebuilt automatically.\n\n#### Debugging\n\nNest applications also have the `inspect` flag set, so you can attach your debugger to the running instance.\n\nDebugging is set to use a random port that is available on the system. The port can be changed by setting the port option in the `serve` target in the `project.json`. Or by running the serve command with `--port <number>`.\n\nFor additional information on how to debug Node applications, see the [Node.js debugging getting started guide](https://nodejs.org/en/docs/guides/debugging-getting-started/#inspector-clients).\n\n### Lint\n\nYou can lint an application with the following command:\n\n```shell\nnx lint my-nest-app\n```\n\nYou can lint a library with the following command:\n\n```shell\nnx lint my-nest-lib\n```\n\n### Unit Test\n\nYou can run unit test for an application with the following command:\n\n```shell\nnx test my-nest-app\n```\n\nYou can run unit test for a library with the following command:\n\n```shell\nnx test my-nest-lib\n```\n\n## More Documentation\n\n- [Using Jest](/packages/jest)\n"
}
],
"generators": [

View File

@ -27,7 +27,7 @@
{
"name": "React Tutorial",
"id": "react-tutorial",
"file": "shared/react-tutorial/01-create-application"
"file": "shared/react-tutorial/1-code-generation"
},
{
"name": "Angular Tutorial",
@ -37,7 +37,7 @@
{
"name": "Node Tutorial",
"id": "node-tutorial",
"file": "shared/node-tutorial/01-create-application"
"file": "shared/node-tutorial/1-code-generation"
}
]
},
@ -81,67 +81,32 @@
{
"name": "React Tutorial",
"id": "react-tutorial",
"description": "Learn to use Nx with this React tutorial where you will learn about all its main feature with a real project.",
"description": "In this tutorial you'll create a frontend-focused workspace with Nx.",
"itemList": [
{
"name": "1 - Create Application",
"id": "01-create-application",
"file": "shared/react-tutorial/01-create-application"
"name": "1 - Code Generation",
"id": "1-code-generation",
"file": "shared/react-tutorial/1-code-generation"
},
{
"name": "2 - Add E2E Test",
"id": "02-add-e2e-test",
"file": "shared/react-tutorial/02-add-e2e-test"
"name": "2 - Project Graph",
"id": "2-project-graph",
"file": "shared/react-tutorial/2-project-graph"
},
{
"name": "3 - Display Todos",
"id": "03-display-todos",
"file": "shared/react-tutorial/03-display-todos"
"name": "3 - Task Running",
"id": "3-task-running",
"file": "shared/react-tutorial/3-task-running"
},
{
"name": "4 - Connect to API",
"id": "04-connect-to-api",
"file": "shared/react-tutorial/04-connect-to-api"
"name": "4 - Workspace Optimization",
"id": "4-workspace-optimization",
"file": "shared/react-tutorial/4-workspace-optimization"
},
{
"name": "5 - Add Node Application",
"id": "05-add-node-app",
"file": "shared/react-tutorial/05-add-node-app"
},
{
"name": "6 - Proxy Configuration",
"id": "06-proxy",
"file": "shared/react-tutorial/06-proxy"
},
{
"name": "7 - Share Code",
"id": "07-share-code",
"file": "shared/react-tutorial/07-share-code"
},
{
"name": "8 - Create Libraries",
"id": "08-create-libs",
"file": "shared/react-tutorial/08-create-libs"
},
{
"name": "9 - Project Graph",
"id": "09-dep-graph",
"file": "shared/react-tutorial/09-dep-graph"
},
{
"name": "10 - Use Computation Caching",
"id": "10-computation-caching",
"file": "shared/react-tutorial/10-computation-caching"
},
{
"name": "11 - Test Affected Projects",
"id": "11-test-affected-projects",
"file": "shared/react-tutorial/11-test-affected-projects"
},
{
"name": "12 - Summary",
"id": "12-summary",
"file": "shared/react-tutorial/12-summary"
"name": "5 - Summary",
"id": "5-summary",
"file": "shared/react-tutorial/5-summary"
}
]
},
@ -218,44 +183,29 @@
"description": "Learn to use Nx with this Node tutorial where you will learn about all its main feature with a real project.",
"itemList": [
{
"name": "1 - Create Application",
"id": "01-create-application",
"file": "shared/node-tutorial/01-create-application"
"name": "1 - Code Generation",
"id": "1-code-generation",
"file": "shared/node-tutorial/1-code-generation"
},
{
"name": "2 - Display Todos",
"id": "02-display-todos",
"file": "shared/node-tutorial/02-display-todos"
"name": "2 - Project Graph",
"id": "2-project-graph",
"file": "shared/node-tutorial/2-project-graph"
},
{
"name": "3 - Share Code",
"id": "03-share-code",
"file": "shared/node-tutorial/03-share-code"
"name": "3 - Task Running",
"id": "3-task-running",
"file": "shared/node-tutorial/3-task-running"
},
{
"name": "4 - Create Libraries",
"id": "04-create-libs",
"file": "shared/node-tutorial/04-create-libs"
"name": "4 - Workspace Optimization",
"id": "4-workspace-optimization",
"file": "shared/node-tutorial/4-workspace-optimization"
},
{
"name": "5 - Project Graph",
"id": "05-dep-graph",
"file": "shared/node-tutorial/05-dep-graph"
},
{
"name": "6 - Use Computation Caching",
"id": "06-computation-caching",
"file": "shared/node-tutorial/06-computation-caching"
},
{
"name": "7 - Test Affected Projects",
"id": "07-test-affected-projects",
"file": "shared/node-tutorial/07-test-affected-projects"
},
{
"name": "8 - Summary",
"id": "08-summary",
"file": "shared/node-tutorial/08-summary"
"name": "5 - Summary",
"id": "5-summary",
"file": "shared/node-tutorial/5-summary"
}
]
},

View File

@ -145,5 +145,4 @@ nx test my-nest-lib
## More Documentation
- [Todo Tutorial](/node-tutorial/01-create-application)
- [Using Jest](/packages/jest)

View File

@ -1,161 +0,0 @@
# Node Nx Tutorial - Step 1: Create Application
{% youtube
src="https://www.youtube.com/embed/UcBSBQYNlhE"
title="Nx.dev Tutorial | Node | Step 1: Create Application"
width="100%" /%}
In this tutorial you use Nx to build a server application out of common libraries using modern technologies.
{% 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 [Package-Based Repo Tutorial](/getting-started/package-based-repo-tutorial).
{% /callout %}
## Contents
- [1 - Create Application](/node-tutorial/01-create-application)
- [2 - Display Todos](/node-tutorial/02-display-todos)
- [3 - Share Code](/node-tutorial/03-share-code)
- [4 - Create Libraries](/node-tutorial/04-create-libs)
- [5 - Project Graph](/node-tutorial/05-dep-graph)
- [6 - Use Computation Caching](/node-tutorial/06-computation-caching)
- [7 - Test Affected Projects](/node-tutorial/07-test-affected-projects)
- [8 - Summary](/node-tutorial/08-summary)
## Create a New Workspace
**Start by creating a new workspace.**
```shell
npx create-nx-workspace@latest
```
You then receive the following prompts in your command line:
```shell
Workspace name (e.g., org name) myorg
What to create in the new workspace nest
Application name todos
```
> You can also choose to add [Nx Cloud](https://nx.app), but its not required for the tutorial.
```treeview
myorg/
├── README.md
├── apps/
│ └── todos/
│ ├── jest.config.ts
│ ├── src/
│ │ ├── app/
│ │ │ ├── app.controller.spec.ts
│ │ │ ├── app.controller.ts
│ │ │ ├── app.module.ts
│ │ │ ├── app.service.spec.ts
│ │ │ └── app.service.ts
│ │ ├── assets/
│ │ ├── environments/
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ └── main.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
├── libs/
├── tools/
├── .eslintrc.json
├── .prettierrc
├── jest.config.ts
├── jest.preset.js
├── nx.json
├── package.json
├── README.md
└── tsconfig.base.json
```
The generate command added one project to our workspace:
- A Nest application
## Note on the Nx CLI
Depending on how your dev env is set up, the command above might result in `Command 'nx' not found`.
To fix it, you can either install the `nx` cli globally by running:
{% tabs %}
{% tab label="yarn" %}
```shell
yarn global add nx
```
{% /tab %}
{% tab label="npm" %}
```shell
npm install -g nx
```
{% /tab %}
{% /tabs %}
Or you can prepend every command with `npm run`:
{% tabs %}
{% tab label="yarn" %}
```shell
yarn nx serve todos
```
{% /tab %}
{% tab label="npm" %}
```shell
npx nx serve todos
```
{% /tab %}
{% /tabs %}
## Project.json, Targets, Executors
You configure your projects in `project.json` files. These files contains the workspace projects with their command targets. For instance, `todos` has the `build`, `serve`, `lint`, and `test` targets. This means that you can run `nx build todos`, `nx serve todos`, etc..
Every target uses an executor which actually runs this target. So targets are analogous to typed npm scripts, and executors are analogous to typed shell scripts.
**Why not use shell scripts and npm scripts directly?**
There are a lot of advantages to providing additional metadata to the build tool. For instance, you can introspect targets. `nx serve todos --help` results in:
```shell
nx run todos:serve [options,...]
Options:
--buildTarget The target to run to build you the app
--waitUntilTargets The targets to run to before starting the node app (default: )
--host The host to inspect the process on (default: localhost)
--port The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes.
--watch Run build when files change (default: true)
--inspect Ensures the app is starting with debugging (default: inspect)
--runtimeArgs Extra args passed to the node process (default: )
--args Extra args when starting the app (default: )
--help Show available options for project target.
```
It helps with good editor integration (see [VSCode Support](/core-features/integrate-with-editors#nx-console-for-vscode)).
But, most importantly, it provides a holistic dev experience regardless of the tools used, and enables advanced build features like distributed computation caching and distributed builds).
## Serve the newly created application
Now that the application is set up, run it locally via:
```shell
nx serve todos
```
## What's Next
- Continue to [Step 2: Display todos](/node-tutorial/02-display-todos)

View File

@ -1,167 +0,0 @@
# Node Nx Tutorial - Step 2: Display todos
{% youtube
src="https://www.youtube.com/embed/I4-sO2LeVbU"
title="Nx.dev Tutorial | Node | Step 2: Display Todos"
width="100%" /%}
Great! you now have a server application set up to show some data when going to the `/api` route.
Next, you're going to add a new service, and set up some server side templates.
## Creating a todos service
With Nx, you have the ability to scaffold out new code for your application. Create a Todos service and populate some todos!
**Run `nx generate @nrwl/nest:service todo --project todos --directory app` to generate our new service**
```shell
$ nx generate @nrwl/nest:service todos --project todos --directory app
CREATE apps/todos/src/app/todos/todos.service.spec.ts (453 bytes)
CREATE apps/todos/src/app/todos/todos.service.ts (89 bytes)
UPDATE apps/todos/src/app/app.module.ts (318 bytes)
```
{% callout type="check" title="Get more info on plugins" %}
Services are not the only things that the `@nrwl/nest` plugin can create. Run `nx list @nrwl/nest` to see other capabilities that the plugin provides.
{% /callout %}
Open the newly created file in `apps/todos/src/app/todos/todos.service.ts` and paste the following code:
```typescript
import { Injectable } from '@nestjs/common';
export type Todo = {
message: string;
done: boolean;
};
const todos: Todo[] = [
{ message: 'Take out trash', done: false },
{ message: 'Continue using Nx', done: false },
];
@Injectable()
export class TodosService {
getTodos(): Todo[] {
return todos;
}
}
```
{% callout type="note" title="We keep things simple here" %}
Usually services should call some kind of data source (like a database or even a file) but for this tutorial, just populate todos manually.
{% /callout %}
You now have your Todos service ready!
## Install template engine
In order to render some views, you need to install a template engine:
{% tabs %}
{% tab label="yarn" %}
```shell
yarn add hbs
```
{% /tab %}
{% tab label="npm" %}
```shell
npm install --save hbs
```
{% /tab %}
{% /tabs %}
Once the installation process is complete, you need to configure the `main.ts` file with the following code:
```typescript
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app/app.module';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.setBaseViewsDir(join(__dirname, 'assets', 'views'));
app.setViewEngine('hbs');
const port = process.env.PORT || 3333;
await app.listen(port, () => {
Logger.log('Listening at http://localhost:' + port);
});
}
bootstrap();
```
You added configuration for setting up the view engine, and removed the `globalPrefix` option.
## Template rendering
Under the `assets` directory of the todo's project, you create a `views` directory with an `index.hbs` file inside with the following content:
```handlebars
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>App</title>
</head>
<body>
<ul class="todos">
{{#each todos}}
<li><input type="checkbox" {{#if done}}checked{{/if}} /> {{message}}</li>
{{/each}}
</ul>
</body>
</html>
```
Next, update the `app.controller.ts` file with the following:
```typescript
import { Controller, Get, Render } from '@nestjs/common';
import { AppService } from './app.service';
import { TodosService } from './todos/todos.service';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
private todosService: TodosService
) {}
@Get('api')
getData() {
return this.todosService.getTodos();
}
@Get()
@Render('index')
root() {
return {
todos: this.getData(),
};
}
}
```
You changed the `@Get` decorator for the `getData` function to point to the `api` route. You also changed this to call the `todosService.getTodos()` method. \
Then you added the `root` function which renders the `index` file from our `views` directory.
{% callout type="note" title="Serve is running" %}
The serve process should still be running. If it isn't, restart the process with `nx serve todos`
{% /callout %}
## What's Next
- Continue to [Step 3: Share code](/node-tutorial/03-share-code)

View File

@ -1,80 +0,0 @@
# Node Nx Tutorial - Step 3: Share Code
{% youtube
src="https://www.youtube.com/embed/MqqwOoKa-Ho"
title="Nx.dev Tutorial | Node | Step 3: Share Code"
width="100%" /%}
Awesome! The application is working as expected!
Next, work on refactoring a bit. The next work to do is move the `Todo` type to it's own library. This is important when you want to share the type between multiple applications, without having to duplicate the same type everywhere.
**Run the following generator to create a library:**
```shell
nx g @nrwl/workspace:lib data
```
The result should look like this:
```treeview
myorg/
├── apps/
│ └── todos/
├── libs/
│ └── data/
│ ├── src/
│ │ ├── lib/
│ │ │ └── data.ts
│ │ └── index.ts
│ ├── jest.config.js
│ ├── tsconfig.lib.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
├── tools/
├── nx.json
├── package.json
└── tsconfig.base.json
```
**Copy the type into `libs/data/src/lib/data.ts`.**
```typescript
export type Todo = {
message: string;
done: boolean;
};
```
### A note about VS Code :
If you're using [VS Code](https://code.visualstudio.com/) it may be necessary at this point to restart the TS server so that the new `@myorg/data` package is recognised. This needs to be done **every time a new workspace library is added**.
Use the command palette with a `*.ts` file open and choose `Restart TS Server`.
## Refactor the todos service
**Now update `apps/todos/src/app/todos/todos.service.ts` to import the type:**
```typescript
import { Injectable } from '@nestjs/common';
import { Todo } from '@myorg/data';
const todos: Todo[] = [
{ message: 'Take out trash', done: false },
{ message: 'Continue using Nx', done: false },
];
@Injectable()
export class TodosService {
getTodos(): Todo[] {
return todos;
}
}
```
Every time you add a new library, you have to restart `nx serve`. **So restart `nx serve todos` and you should see the application running.**
## What's Next
- Continue to [Step 4: Create libraries](/node-tutorial/04-create-libs)

View File

@ -1,97 +0,0 @@
# Node Nx Tutorial - Step 4: Create Libraries
{% youtube
src="https://www.youtube.com/embed/V29I_DHGlB8"
title="Nx.dev Tutorial | Node | Step 4: Create Libraries"
width="100%" /%}
Libraries are not just a way to share code in Nx. They are also useful for factoring out code into small units with a well-defined public API.
## Public API
Every library has an `index.ts` file, which defines its public API. Other applications and libraries should only access what the `index.ts` exports. Everything else in the library is private.
## Controller libraries
To illustrate how useful libraries can be, create a new Auth library with a controller.
Run
```shell
nx g @nrwl/nest:lib auth --controller
```
{% callout type="note" title="--controller" %}
We added the `--controller` flag here to generate a controller along with the library scaffolding.
{% /callout %}
You should see the following:
```treeview
myorg/
├── apps/
│ └── todos/
├── libs/
│ ├── auth/
│ │ ├── jest.config.ts
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── lib/
│ │ │ ├── auth.controller.spec.ts
│ │ │ ├── auth.controller.ts
│ │ │ └── auth.module.ts
│ │ ├── tsconfig.json
│ │ ├── tsconfig.lib.json
│ │ └── tsconfig.spec.json
│ └── data/
├── tools/
├── nx.json
├── package.json
└── tsconfig.base.json
```
Modify the `libs/auth/src/lib/auth.controller.ts` file like this:
```typescript
import { Controller, Get } from '@nestjs/common';
@Controller('auth')
export class AuthController {
@Get()
auth() {
return {
authenticated: true,
};
}
}
```
{% callout type="note" title="We keep things simple here" %}
In code destined for production, you would actually have a proper authentication check here.
{% /callout %}
## Use the new library
**Now import `AuthModule` into `apps/todos/src/app/app.module.ts`.**
```typescript
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TodosService } from './todos/todos.service';
import { AuthModule } from '@myorg/auth';
@Module({
imports: [AuthModule],
controllers: [AppController],
providers: [AppService, TodosService],
})
export class AppModule {}
```
Restart `nx serve todos` then go to http://localhost:3333/auth. You should see `{ authenticated: true }`.
## What's Next
- Continue to [Step 5: Dep graph](/node-tutorial/05-dep-graph)

View File

@ -1,16 +0,0 @@
# Node Nx Tutorial - Step 5: Project Graph
{% youtube
src="https://www.youtube.com/embed/l9MjZ9IPdu4"
title="Nx.dev Tutorial | Node | Step 5: Dep Graph"
width="100%" /%}
An Nx workspace can contain dozens or hundreds of applications and libraries. As a codebase grows, it becomes more difficult to understand how they depend on each other and the implications of making a particular change.
Previously, some senior architect would create an ad-hoc dependency diagram and upload it to a corporate wiki. The diagram is not correct even on Day 1 and gets more and more out of sync with every passing day.
With Nx, you can do better than that.
## What's Next
- Continue to [Step 6: Computation Caching](/node-tutorial/06-computation-caching)

View File

@ -1,41 +0,0 @@
# Node Nx Tutorial - Step 6: Computation Caching
{% youtube
src="https://www.youtube.com/embed/gXChzhI1Qpg"
title="Nx.dev Tutorial | Node | Step 6: Computation Caching"
width="100%" /%}
Nx has built-in computation caching, which drastically improves the performance of the commands.
**To see it in action, run `nx build todos`:**
```shell
> nx run todos:build
Starting type checking service...
Using 14 workers with 2048MB memory limit
Hash: 51f23143c450a9f931a7
Built at: 09/04/2020 4:03:20 PM
Entrypoint main = main.js main.js.map
chunk {main} main.js, main.js.map (main) 4.17 KiB [entry] [rendered]
```
**Now, run `nx build todos` again, and you will see the results appearing instantly:**
```shell
> nx run todos:build
> NX NOTE Cached Output:
Starting type checking service...
Using 14 workers with 2048MB memory limit
Hash: 51f23143c450a9f931a7
Built at: 09/04/2020 4:03:20 PM
Entrypoint main = main.js main.js.map
chunk {main} main.js, main.js.map (main) 4.17 KiB [entry] [rendered]
```
Based on the state of the source code and the environment, Nx was able to figure out that it had already run this exact command. Nx found the artifact in the local cache and replayed the output and restored the necessary files.
## What's Next
- Continue to [Step 7: Test affected projects](/node-tutorial/07-test-affected-projects)

View File

@ -1,80 +0,0 @@
# Node Nx Tutorial - Step 7: Test Affected Projects
{% youtube
src="https://www.youtube.com/embed/TRRVLyHfN60"
title="Nx.dev Tutorial | Node | Step 7: Test Affected Projects"
width="100%" /%}
In addition to supporting computation caching, Nx scales your development by doing code change analysis to see what apps or libraries are affected by a particular pull request.
**Commit all the changes in the repo**:
```shell
git add .
git commit -am 'init'
git checkout -b testbranch
```
**Open `libs/auth/src/lib/auth.controller.ts` and change the controller:**
```typescript
import { Body, Controller, Get, Post } from '@nestjs/common';
@Controller('auth')
export class AuthController {
@Get()
auth() {
return {
authenticated: true,
};
}
@Post()
authenticate(@Body() postData: { username: string; password: string }) {
const { username, password } = postData;
// check the database
console.log(username, password);
}
}
```
**Run `nx affected:apps`**, and you should see `todos` printed out. The `affected:apps` looks at what you have changed and uses the project graph to figure out which apps are affected by this change.
**Run `nx affected:libs`**, and you should see `auth` printed out. This command works similarly, but instead of printing the affected apps, it prints the affected libs.
## Test Affected Projects
Printing the affected projects can be handy, but usually you want to do something with them. For instance, you may want to test everything that has been affected.
**Run `nx affected:test` to retest only the projects affected by the change.**
As you can see, because the code was updated without updating the tests, the unit tests failed.
```shell
> NX Running target test for projects:
- auth
- todos
...
Failed projects:
- todos
```
Note that Nx only tried to retest `auth` and `todos`. It didn't retest `data` because there is no way that library could be affected by the changes in this branch.
## Affected:\*
You can run any target against the affected projects in the graph like this:
```shell
# The following are equivalent
nx affected --target=build
nx affected:build
```
## What's Next
- Continue to [Step 8: Summary](/node-tutorial/08-summary)

View File

@ -1,17 +0,0 @@
# Node Nx Tutorial - Step 8: Summary
In this tutorial you:
- Built a full Node application with an API and server side rendered pages
- Shared code
- Created a controller library
- Used Nx affected commands to only retest and rebuild what is affected
## Learn more
- [Free Nx Course on YouTube](https://www.youtube.com/playlist?list=PLakNactNC1dH38AfqmwabvOszDmKriGco)
**Dive Deep:**
- [Computation Caching](/concepts/how-caching-works)
- [Rebuilding What is Affected](/concepts/affected)

View File

@ -0,0 +1,99 @@
---
title: 'Node Tutorial - Part 1: Code Generation'
description: In this tutorial you'll create a backend-focused workspace with Nx.
---
{% callout type="check" title="Two Styles of Repo" %}
There are two styles of repos: integrated and package-based. This tutorial shows the integrated style.
You can find more information on the difference between the two in [our introduction](/getting-started/intro).
{% /callout %}
# Node Tutorial - Part 1: Code Generation
In this tutorial you'll create a backend-focused workspace with Nx.
## Contents
- [1 - Code Generation](/node-tutorial/1-code-generation)
- [2 - Project Graph](/node-tutorial/2-project-graph)
- [3 - Task Running](/node-tutorial/3-task-running)
- [4 - Workspace Optimization](/node-tutorial/4-workspace-optimization)
- [5 - Summary](/node-tutorial/5-summary)
## Your Objective
For this tutorial, you'll create an Express API application, a CLI (command-line interface) application, and a library for a data client that these two applications will use to interact with a data-source.
![Our Workspace Requirements](/shared/node-tutorial/requirements-diagram.png)
## Creating an Nx Workspace
Run the command `npx create-nx-workspace@latest` and when prompted, provide the following responses:
```{% command="npx create-nx-workspace@latest" path="~" %}
✔ Choose your style · integrated
✔ What to create in the new workspace · express
✔ Repository name · my-products
✔ Application name · products-api
✔ Enable distributed caching to make your CI faster · No
```
{% card title="Opting into Nx Cloud" description="You will also be prompted whether to add Nx Cloud to your workspace. We won't address this in this tutorial, but you can see the introduction to Nx Cloud for more details." url="/nx-cloud/intro/what-is-nx-cloud" /%}
Once the command complete, you can find your Express API application in `apps/products-api`.
## Adding Another Application to Your Workspace
Run this command to create your `products-cli` app:
```{% command="npx nx g @nrwl/node:app products-cli" path="~/my-products" %}
> NX Generating @nrwl/node:application
CREATE apps/products-cli/src/app/.gitkeep
CREATE apps/products-cli/src/assets/.gitkeep
CREATE apps/products-cli/src/environments/environment.prod.ts
CREATE apps/products-cli/src/environments/environment.ts
CREATE apps/products-cli/src/main.ts
CREATE apps/products-cli/tsconfig.app.json
CREATE apps/products-cli/tsconfig.json
CREATE apps/products-cli/project.json
CREATE apps/products-cli/.eslintrc.json
CREATE apps/products-cli/jest.config.ts
CREATE apps/products-cli/tsconfig.spec.json
```
![Nx Generator Syntax](/shared/node-tutorial/generator-syntax.png)
## Generating Libraries
To create the `products-data-client` library, use the `@nrwl/js:lib` generator:
```{% command="npx nx g @nrwl/js:lib products-data-client" path="~/my-products" %}
> NX Generating @nrwl/js:library
CREATE libs/products-data-client/README.md
CREATE libs/products-data-client/package.json
CREATE libs/products-data-client/src/index.ts
CREATE libs/products-data-client/src/lib/products-data-client.spec.ts
CREATE libs/products-data-client/src/lib/products-data-client.ts
CREATE libs/products-data-client/tsconfig.json
CREATE libs/products-data-client/tsconfig.lib.json
CREATE libs/products-data-client/project.json
UPDATE tsconfig.base.json
CREATE libs/products-data-client/.eslintrc.json
CREATE libs/products-data-client/jest.config.ts
CREATE libs/products-data-client/tsconfig.spec.json
```
You have now created all three projects from the design:
- `products-api` in `apps/products-api`
- `products-cli` in `apps/products-cli`
- `products-data-client` in `libs/products-data-client`
## What's Next
- Continue to [2: Project Graph](/node-tutorial/2-project-graph)

View File

@ -0,0 +1,127 @@
# Node Tutorial - Part 2: Project Graph
Run the command: `npx nx graph`. A browser should open up with the following contents:
![Initial Project Graph](/shared/node-tutorial/initial-project-graph.png)
This is still different from the design from the start of Part 1:
![Our Workspace Requirements](/shared/node-tutorial/requirements-diagram.png)
The Project Graph is derived from the source code of your workspace. Make the following adjustments to your existing projects, so that our Project Graph will match the design:
### `products-data-client`
Update the contents of the generated `products-data-client.ts` file:
```typescript {% fileName="libs/products-data-client/src/lib/products-data-client.ts" %}
export interface Product {
id: string;
name: string;
price: number;
}
export interface ProductsDataClient {
getProducts(): Promise<Product[]>;
getProductById(id: string): Promise<Product | undefined>;
}
export const exampleProducts: Record<string, Product> = {
'1': { id: '1', name: 'Product 1', price: 100 },
'2': { id: '2', name: 'Product 2', price: 200 },
};
export function createProductsDataClient(): ProductsDataClient {
return {
getProducts() {
return Promise.resolve(Object.values(exampleProducts));
},
getProductById(id) {
return Promise.resolve(exampleProducts[id]);
},
};
}
```
### `products-cli`
Update the generated `main.ts` file of this project to import the `createProductsDataClient()` function.
Use the data client to print the product matching the id provided at the command-line. If no id was provided, print all products as an array:
```typescript {% fileName="apps/products-cli/src/main.ts" %}
import { createProductsDataClient } from '@my-products/products-data-client';
main();
async function main() {
const productsDataClient = createProductsDataClient();
const id = getProvidedId();
if (id != null) {
const product = await productsDataClient.getProductById(id);
console.log(JSON.stringify(product, null, 2));
} else {
const products = await productsDataClient.getProducts();
console.log(JSON.stringify(products, null, 2));
}
}
function getProvidedId() {
return process.argv[2];
}
```
### `products-api`
Update the generated `main.ts` file of this project to also import the `createProductsDataClient()` function.
Use the data client and Express to create an Express app with 2 GET request handlers:
```javascript {% fileName="apps/products-api/src/main.ts" %}
/**
* This is not a production server yet!
* This is only a minimal backend to get started.
*/
import * as express from 'express';
import { createProductsDataClient } from '@my-products/products-data-client';
const app = express();
const productsDataClient = createProductsDataClient();
app.get('/products', async (_req, res) => {
const products = await productsDataClient.getProducts();
res.send(products);
});
app.get('/products/:id', async (req, res) => {
const id = req.params.id;
const product = await productsDataClient.getProductById(id);
if (product == null) {
res.status(404).send();
return;
}
res.send(product);
});
const port = process.env.port || 3333;
const server = app.listen(port, () => {
console.log(`Listening at http://localhost:${port}`);
});
server.on('error', console.error);
```
Now run `npx nx graph` again:
{% side-by-side %}
![Matching Graph](/shared/node-tutorial/matching-graph.png)
![Our Workspace Requirements](/shared/node-tutorial/requirements-diagram.png)
{% /side-by-side %}
Your graph now matches the original design.
The Project Graph is more than just a visualization - Nx provides tooling to optimize your task-running and even automate your CI based on this graph. This will be covered in more detail in: [4: Workspace Optimization](/node-tutorial/4-workspace-optimization).
## What's Next
- Continue to [3: Task Running](/node-tutorial/3-task-running)

View File

@ -0,0 +1,145 @@
# Node Tutorial - Part 3: Task-Running
Common tasks include:
- Building an application
- Serving an application locally for development purposes
- Running your unit tests
- Linting your code
When you ran your generators in Part 1, you already set up these more common tasks for each project.
## Defining Targets
Here's the `project.json` file for your `products-data-client` project:
```json {% fileName="libs/products-data-client/project.json" %}
{
"name": "products-data-client",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/products-data-client/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nrwl/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/products-data-client",
"main": "libs/products-data-client/src/index.ts",
"tsConfig": "libs/products-data-client/tsconfig.lib.json",
"assets": ["libs/products-data-client/*.md"]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/products-data-client/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/products-data-client"],
"options": {
"jestConfig": "libs/products-data-client/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": []
}
```
You can see that three targets are defined here: `build`, `lint` and `test`.
The properties inside each of these these targets is defined as follows:
- `executor` - which Nx executor to run. The syntax here is: `<plugin name>:<executor name>`
- `outputs` - this is an array of files that would be created by running this target. (This informs Nx on what to save for it's caching mechanisms you'll learn about in [4 - Workspace Optimizations](/node-tutorial/4-workspace-optimization)).
- `options` - this is an object defining which executor options to use for the given target. Every Nx executor allows for options as a way to parameterize it's functionality.
## Running Tasks
![Syntax for Running Tasks in Nx](/shared/node-tutorial/run-target-syntax.png)
Run the `build` target for your `products-data-client` project:
```{% command="npx nx build products-data-client" path="~/my-products" %}
> nx run products-data-client:build
Compiling TypeScript files for project "products-data-client"...
Done compiling TypeScript files for project "products-data-client".
———————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target build for project products-data-client (780ms)
```
You can now find your built `products-data-client` distributable in your `dist/libs/products-data-client` directory, as specified in the `outputPath` property of the `build` target options in your `project.json` file.
Next, run a lint check on `products-data-client`:
```{% command="npx nx lint products-data-client" path="~/my-products" %}
> nx run products-data-client:lint
Linting "products-data-client"...
All files pass linting.
———————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target lint for project products-data-client (777ms)
```
Next, add some tests to your data client in the `products-data-client.spec.ts` file:
```typescript {% fileName="libs/products-data-client/src/lib/products-data-client.spec.ts" %}
import {
createProductsDataClient,
exampleProducts,
} from './products-data-client';
describe('productsDataClient', () => {
it('should get all example products', async () => {
const productsDataClient = createProductsDataClient();
const products = await productsDataClient.getProducts();
expect(products).toEqual(Object.values(exampleProducts));
});
it('should get example product by id', async () => {
const productsDataClient = createProductsDataClient();
const product = await productsDataClient.getProductById('1');
expect(product).toEqual(exampleProducts['1']);
});
});
```
And then run your `test` target:
```{% command="npx nx test products-data-client" path="~/my-products" %}
> nx run products-data-client:test
PASS products-data-client libs/products-data-client/src/lib/products-data-client.spec.ts
productsDataClient
✓ should get all example products (1 ms)
✓ should get example product by id
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.843 s
Ran all test suites.
———————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target test for project products-data-client (2s)
```
## What's Next
- Continue to [4: Workspace Optimization](/node-tutorial/4-workspace-optimization)

View File

@ -0,0 +1,213 @@
# Node Tutorial - Part 4: Workspace Optimization
## Testing Affected Projects
`affected` is a mechanism that relies on your git metadata to determine the projects in your workspace that were affected by a given commit.
Run the command:
```{% command="git add . && git commit -m 'commiting to test affected'" path="~/my-products" %}
```
Then make a change to your example products in your `products-data-client` project:
```typescript {% fileName="libs/products-data-client/src/lib/products-data-client.ts" %}
export const exampleProducts: Record<string, Product> = {
'1': { id: '1', name: 'Product 1', price: 100 },
'2': { id: '2', name: 'Product 2', price: 400 }, // changed here
};
```
Run the following command to visualize how our workspace is affected by this change:
```{% command="npx nx affected:graph" path="~/my-products" %}
```
![Project Graph with All Affected](/shared/node-tutorial/project-graph-with-all-affected.png)
The change made to the `products-data-client` project is also affecting the `products-api` and `products-cli` projects, since both of those projects import from the `products-data-client` project.
Next, stash your changes since the commit:
```{% command="git stash" path="~/my-products" %}
```
And then make a minor adjustment to the `products-cli` project:
```typescript {% fileName="apps/products-clit/src/main.ts" %}
import { createProductsDataClient } from '@my-products/products-data-client';
main();
async function main() {
const productsDataClient = createProductsDataClient();
const id = getProvidedId();
if (id != null) {
const product = await productsDataClient.getProductById(id);
if (!product) {
throw new Error(`Product with id ${id} not found`);
}
console.log(JSON.stringify(product, null, 2));
} else {
const products = await productsDataClient.getProducts();
console.log(JSON.stringify(products, null, 2));
}
}
function getProvidedId() {
return process.argv[2];
}
```
Now run the command to visualize the affected graph again:
```{% command="npx nx affected:graph" path="~/my-products" %}
```
![Project Graph with One Affected](/shared/node-tutorial/project-graph-with-one-affected.png)
This can be leveraged to run tasks only on the projects that were affected by this commit.
To run the `test` targets only for affected projects, run the command:
```{% command="npx nx affected --target=test" path="~/my-products" %}
```
This can be particularly helpful in CI pipelines for larger repos, where most commits only affect a small subset of the entire workspace.
{% card title="Affected Documentation" description="Checkout Affected documentation for more details" url="/nx/affected" /%}
## Task Caching
`affected` allows you to "skip" tasks that couldn't possibly be affected by your changes. Task Caching allows you to "replay" tasks that have already been run.
Task Caching is informed by "inputs" and "outputs":
### Inputs
Inputs for your task caching includes by default any environment details and all the source code of the projects and dependencies affecting your project.
When running a task, Nx will determine all the inputs for your task and create a hash that will be used to index your cache. If you've already run this task with the same inputs, your cache will already be populated at this index, and Nx will replay the results stored in the cache.
If this index does not exist, Nx will run the command and if the command succeeds, it will store the result in the cache.
### Outputs
Outputs of the cache include the terminal output created by the task, as well as any files created by the task - for example: the artifact created by running a `build` task.
Outputs are defined for every target in your workspace:
```json {% fileName="libs/products-data-client/project.json" %}
{
"name": "products-data-client",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/products-data-client/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nrwl/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/products-data-client",
"main": "libs/products-data-client/src/index.ts",
"tsConfig": "libs/products-data-client/tsconfig.lib.json",
"assets": ["libs/products-data-client/*.md"]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/products-data-client/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/products-data-client"],
"options": {
"jestConfig": "libs/products-data-client/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": []
}
```
Outputs are stored in the cache so that terminal output can be replayed, and any created files can be pulled from your cache and placed where they were created the original time the task was run.
### Example
To see caching in action, first clear your `dist` directory:
```{% command="rm -rf dist/" path="~/my-products" %}
```
And run the command `npx nx build products-data-client`. (Recall that you had already run this target in [3- Task Running](/node-tutorial/3-task-running))
```{% command="npx nx build products-data-client" path="~/my-products" %}
> nx run products-data-client:build [local cache]
Compiling TypeScript files for project "products-data-client"...
Done compiling TypeScript files for project "products-data-client".
———————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target build for project products-data-client (32ms)
Nx read the output from the cache instead of running the command for 1 out of 1 tasks.
```
Notice that `[local cache]` is mentioned in the terminal output, and that this time the command only took 32ms to run.
Also notice that the result of your build has been added back to the `dist/libs/products-data-client` directory.
{% card title="More Task Caching Details" description="See the documentation for more information on caching." url="/core-features/cache-task-results" /%}
## Configuring Task Pipelines
Next, run the command `npx nx build products-cli`:
```{% command="npx nx build products-cli" path="~/my-products" %}
✔ 1/1 dependent project tasks succeeded [1 read from cache]
Hint: you can run the command with --verbose to see the full dependent project outputs
———————————————————————————————————————————————————————————————————————————————————————————————
> nx run products-cli:build
chunk (runtime: main) main.js (main) 1.71 KiB [entry] [rendered]
webpack compiled successfully (bafa37be9890ecb2)
———————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target build for project products-cli and 1 task(s) it depends on (2s)
Nx read the output from the cache instead of running the command for 1 out of 2 tasks.
```
Notice the line here:
```plain
✔ 1/1 dependent project tasks succeeded [1 read from cache]
```
This is because your `products-cli` project depends on your `products-data-client` project, which also has a `build` target. By default Nx is configured to run (or read from cache) the `build` target for any dependencies that have a `build` target, before running the `build` on the original project.
This feature allows the Nx graph to dynamically maintain task dependencies, rather than having to manually maintain those task dependencies as your workspace continues to grow.
{% card title="More On The Task Pipeline Configuration" description="See the Task Pipeline Configuration Guide for more details on how to configure your Task Graph." url="/concepts/task-pipeline-configuration" /%}
## What's Next
- Continue to [5: Summary](/node-tutorial/5-summary)

View File

@ -0,0 +1,26 @@
# Node Tutorial - Part 5: Summary
In this tutorial you:
- Learned how to use Nx's Generators to generate code for your workspace.
- Learned how Nx determines a graph of your workspace
- Learned how to configure and run tasks in your workspace
- Learned how Nx's built-in optimizations work, and how to apply those to your own workspace
## Learn More
{% cards %}
{% card title="Free Nx Course on YouTube" description="Follow up this tutorial with our free Nx Course." type="video" url="https://www.youtube.com/playlist?list=PLakNactNC1dH38AfqmwabvOszDmKriGco" /%}
{% card title="Nx React Tutorial" description="Follow up this tutorial the React tutorial to see how Nx can be used in the frontend space." url="/tutorials/react-tutorial" /%}
{% card title="Core Features" description="Learn more about the Core Features of Nx." url="/core-features" /%}
{% card title="The Nx Mental Model" description="Expand your Mental Model of Nx." url="/concepts/mental-model" /%}
{% card title="Distributed Task Execution" description="Learn how to use Nx Cloud for Distributed Task Execution to speed up your CI times even more." url="/concepts/dte" /%}
{% card title="Configure CI For Your Workspace" description="Learn how to create CI configuration for your workspace using our ci-workflow generator, or by creating your own workflow." url="/recipes/ci-setup" /%}
{% /cards %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1,165 +0,0 @@
# React Nx Tutorial - Step 1: Create Application
{% youtube
src="https://www.youtube.com/embed/HcQE5R6ucng"
title="Nx.dev Tutorial | React | Step 1: Create Application"
width="100%" /%}
In this tutorial you use Nx to build a full-stack application out of common libraries using modern technologies.
{% callout type="note" title="Nx has first-class Next.js support" %}
Nx has first-class Next.js support, if you are looking to use it for your project. Read more about it [here](/packages/next)
{% /callout %}
{% 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 [Package-Based Repo Tutorial](/getting-started/package-based-repo-tutorial).
{% /callout %}
## Contents
- [1 - Create Application](/react-tutorial/01-create-application)
- [2 - Add E2E Test](/react-tutorial/02-add-e2e-test)
- [3 - Display Todos](/react-tutorial/03-display-todos)
- [4 - Connect to API](/react-tutorial/04-connect-to-api)
- [5 - Add Node Application](/react-tutorial/05-add-node-app)
- [6 - Proxy Configuration](/react-tutorial/06-proxy)
- [7 - Share Code](/react-tutorial/07-share-code)
- [8 - Create Libraries](/react-tutorial/08-create-libs)
- [9 - Project Graph](/react-tutorial/09-dep-graph)
- [10 - Use Computation Caching](/react-tutorial/10-computation-caching)
- [11 - Test Affected Projects](/react-tutorial/11-test-affected-projects)
- [12 - Summary](/react-tutorial/12-summary)
## Create a new workspace
Start by creating a new workspace.
```shell
npx create-nx-workspace@latest
```
You then receive the following prompts in your command line:
```shell
Workspace name (e.g., org name) myorg
What to create in the new workspace react
Application name todos
Default stylesheet format CSS
```
Enter the indicated answers.
> You can also choose to add [Nx Cloud](https://nx.app), but its not required for the tutorial.
```treeview
myorg/
├── apps/
│ ├── todos/
│ │ ├── src/
│ │ │ ├── app/
│ │ │ ├── assets/
│ │ │ ├── environments/
│ │ │ ├── favicon.ico
│ │ │ ├── index.html
│ │ │ ├── main.tsx
│ │ │ ├── polyfills.ts
│ │ │ └── styles.css
│ │ ├── .babelrc
│ │ ├── .browserslistrc
│ │ ├── .eslintrc.json
│ │ ├── jest.config.ts
│ │ ├── project.json
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ └── tsconfig.spec.json
│ └── todos-e2e/
│ ├── src/
│ │ ├── fixtures/
│ │ │ └── example.json
│ │ ├── e2e/
│ │ │ └── app.cy.ts
│ │ └── support/
│ │ ├── app.po.ts
│ │ ├── commands.ts
│ │ └── e2e.ts
│ ├── .eslintrc.json
│ ├── cypress.config.ts
│ ├── project.json
│ └── tsconfig.json
├── libs/
├── tools/
├── .eslintrc.json
├── .prettierrc
├── babel.config.json
├── jest.config.ts
├── jest.preset.js
├── nx.json
├── package.json
├── README.md
└── tsconfig.base.json
```
Two projects were added to the workspace:
- A React application
- E2E tests for the React application
## Serve the newly created application
Now that the application is set up, run it locally via:
```shell
npx nx serve todos
```
## Note on the Nx CLI
If you prefer to run using a global installation of Nx, you can run:
```shell
nx serve todos
```
Depending on how your dev env is set up, the command above might result in `Command 'nx' not found`.
To fix it, you can either install the `nx` cli globally by running:
{% tabs %}
{% tab label="yarn" %}
```shell
yarn global add nx
```
{% /tab %}
{% tab label="npm" %}
```shell
npm install -g nx
```
{% /tab %}
{% /tabs %}
Alternatively, you can run the local installation of Nx by prepending every command with `npx`:
{% tabs %}
{% tab label="yarn" %}
```shell
yarn nx serve todos
```
{% /tab %}
{% tab label="npm" %}
```shell
npx nx serve todos
```
{% /tab %}
{% /tabs %}
## What's Next
- Continue to [Step 2: Add E2E Tests](/react-tutorial/02-add-e2e-test)

View File

@ -1,45 +0,0 @@
# React Nx Tutorial - Step 2: Add E2E Tests
{% youtube
src="https://www.youtube.com/embed/3HSzqt3WiVg"
title="Nx.dev Tutorial | React | Step 2: Add E2E Tests"
width="100%" /%}
By default, Nx uses [Cypress](https://cypress.io) to run E2E tests.
Open **`apps/todos-e2e/src/support/app.po.ts`.** It's a page object file that contains helpers for querying the page.
**Add the following two helpers:**
```typescript
export const getTodos = () => cy.get('li.todo');
export const getAddTodoButton = () => cy.get('button#add-todo');
```
**Next, update `apps/todos-e2e/src/e2e/app.cy.ts`.**
```typescript
import { getAddTodoButton, getTodos } from '../support/app.po';
describe('TodoApps', () => {
beforeEach(() => cy.visit('/'));
it('should display todos', () => {
getTodos().should((t) => expect(t.length).equal(2));
getAddTodoButton().click();
getTodos().should((t) => expect(t.length).equal(3));
});
});
```
This is a simple example of an E2E test, only to verify the todos are displayed correctly.
If you have not done so already, stop the `npx nx serve` command and run `npx nx e2e todos-e2e --watch`.
Once the Cypress UI opens, select any browser you want. You'll see the `app.cy.ts` file that you just updated. Click on the file and the test will run. Keep the E2E tests running.
As you progress through the tutorial, you work on making these E2E tests pass.
## What's Next
- Continue to [Step 3: Display Todos](/react-tutorial/03-display-todos)

View File

@ -1,96 +0,0 @@
# React Nx Tutorial - Step 3: Display Todos
{% youtube
src="https://www.youtube.com/embed/fNehP0WX__c"
title="Nx.dev Tutorial | React | Step 3: Display Todos"
width="100%" /%}
Great! You have a failing E2E test. Now you can make it pass!
The best way to work with Cypress is to keep the failing E2E test running while working on the app. This helps you see the progress you are making.
## Show todos
**Open `apps/todos`.**
To make the first assertion of the e2e test pass, update `apps/todos/src/app/app.tsx`:
```typescript
import { useState } from 'react';
interface Todo {
title: string;
}
export const App = () => {
const [todos, setTodos] = useState<Todo[]>([
{ title: 'Todo 1' },
{ title: 'Todo 2' },
]);
return (
<>
<h1>Todos</h1>
<ul>
{todos.map((t) => (
<li className={'todo'}>{t.title}</li>
))}
</ul>
</>
);
};
export default App;
```
**Rerun the specs by clicking the button in the top right corner of the left pane.** Now the test fails while trying to find the add todo button.
## Add todos
**Add the `add-todo` button with the corresponding click handler.**
```typescript
import { useState } from 'react';
interface Todo {
title: string;
}
export const App = () => {
const [todos, setTodos] = useState<Todo[]>([
{ title: 'Todo 1' },
{ title: 'Todo 2' },
]);
function addTodo() {
setTodos([
...todos,
{
title: `New todo ${Math.floor(Math.random() * 1000)}`,
},
]);
}
return (
<>
<h1>Todos</h1>
<ul>
{todos.map((t) => (
<li className={'todo'}>{t.title}</li>
))}
</ul>
<button id={'add-todo'} onClick={addTodo}>
Add Todo
</button>
</>
);
};
export default App;
```
The tests should pass now.
## What's Next
- Continue to [Step 4: Connect to an API](/react-tutorial/04-connect-to-api)

View File

@ -1,59 +0,0 @@
# React Nx Tutorial - Step 4: Connect to an API
{% youtube
src="https://www.youtube.com/embed/HexxYHpIfAo"
title="Nx.dev Tutorial | React | Step 4: Connect to an API"
width="100%" /%}
Real-world applications do not live in isolationthey need APIs to talk to. Setup your app to talk to an API.
**Let's change our application to fetch the data from the API.**
```typescript
import { useEffect, useState } from 'react';
interface Todo {
title: string;
}
const App = () => {
const [todos, setTodos] = useState<Todo[]>([]);
useEffect(() => {
fetch('/api/todos')
.then((_) => _.json())
.then(setTodos);
}, []);
function addTodo() {
fetch('/api/addTodo', {
method: 'POST',
body: '',
})
.then((_) => _.json())
.then((newTodo) => {
setTodos([...todos, newTodo]);
});
}
return (
<>
<h1>Todos</h1>
<ul>
{todos.map((t) => (
<li className={'todo'}>{t.title}</li>
))}
</ul>
<button id={'add-todo'} onClick={addTodo}>
Add Todo
</button>
</>
);
};
export default App;
```
## What's Next
- Continue to [Step 5: Add Node Application Implementing an API](/react-tutorial/05-add-node-app)

View File

@ -1,166 +0,0 @@
# React Nx Tutorial - Step 5: Add Node Application Implementing API
{% youtube
src="https://www.youtube.com/embed/XgfknOqgxQ0"
title="Nx.dev Tutorial | React | Step 5: Add Node Application Implementing API"
width="100%" /%}
The requests fail because the API has not been created yet. Using Nx you develop node applications next to your React applications. You can use same commands to run and test them. You share code between the backend and the frontend. Use this capability to implement the API service.
## Add Express plugin to your workspace
Nx is an open platform with plugins for many modern tools and frameworks. **To see some plugins, run `npx nx list`:**
```shell
> NX Installed plugins:
@nrwl/cypress (executors,generators)
@nrwl/jest (executors,generators)
@nrwl/linter (executors,generators)
@nrwl/nx-cloud (generators)
@nrwl/react (generators)
@nrwl/storybook (executors,generators)
@nrwl/web (executors,generators)
@nrwl/workspace (executors,generators)
> NX Also available:
@nrwl/angular (generators)
@nrwl/express (executors,generators)
@nrwl/nest (executors,generators)
@nrwl/next (executors,generators)
@nrwl/node (executors,generators)
@nrwl/nx-plugin (executors,generators)
> NX Community plugins:
nx-plugins - Nx plugin integrations with ESBuild / Vite / Snowpack / Prisma, with derived ESBuild / nowpack / ... plugins.
@codebrew/nx-aws-cdk - An Nx plugin for aws cdk develop.
...
```
**Add the dependency:**
{% tabs %}
{% tab label="yarn" %}
```shell
yarn add --dev @nrwl/express
```
{% /tab %}
{% tab label="npm" %}
```shell
npm install --save-dev @nrwl/express
```
{% /tab %}
{% /tabs %}
{% callout type="check" title="List plugins" %}
When installing `@nrwl/express`, it also automatically added `@nrwl/node` for you. Run `npx nx list @nrwl/express` and `npx nx list @nrwl/node` to see what those plugins provide.
{% /callout %}
## Generate an Express application
**Run the following to generate a new Express application:**
```shell
npx nx g @nrwl/express:app api --frontendProject=todos
```
After this is done, you should see something like this:
```treeview
myorg/
├── apps/
│ ├── api/
│ │ ├── src/
│ │ │ ├── app/
│ │ │ ├── assets/
│ │ │ ├── environments/
│ │ │ │ ├── environment.ts
│ │ │ │ └── environment.prod.ts
│ │ │ └── main.ts
│ │ ├── jest.config.ts
│ │ ├── project.json
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ └── tsconfig.spec.json
│ ├── todos/
│ │ ├── src/
│ │ ├── project.json
│ │ └── proxy.conf.json
│ └── todos-e2e/
├── libs/
├── tools/
├── nx.json
├── package.json
└── tsconfig.base.json
```
The `apps` directory is where Nx places anything you can run: frontend applications, backend applications, e2e test suites. That's why the `api` application appeared there.
You can run:
| Command | Description |
| ---------------- | --------------------- |
| npx nx serve api | serve the application |
| npx nx build api | build the application |
| npx nx test api | test the application |
**Add a file `apps/api/src/app/todos.ts`.**
```typescript
import { Express } from 'express';
interface Todo {
title: string;
}
const todos: Todo[] = [{ title: 'Todo 1' }, { title: 'Todo 2' }];
export function addTodoRoutes(app: Express) {
app.get('/api/todos', (req, resp) => resp.send(todos));
app.post('/api/addTodo', (req, resp) => {
const newTodo = {
title: `New todo ${Math.floor(Math.random() * 1000)}`,
};
todos.push(newTodo);
resp.send(newTodo);
});
}
```
Here, you are building an Express application with Nx. Nx also comes with Next support, and you can also use any other node library you want.
**Next update `apps/api/src/main.ts` to register the routes**
```typescript
import * as express from 'express';
import { addTodoRoutes } from './app/todos';
const app = express();
app.get('/api', (req, res) => {
res.send({ message: 'Welcome to api!' });
});
addTodoRoutes(app);
const port = process.env.port || 3333;
const server = app.listen(port, () => {
console.log(`Listening at http://localhost:${port}/api`);
});
server.on('error', console.error);
```
**Now run `npx nx serve api` to run the api server**
Refresh the application in the browser. The React app is now able to fetch and create todos by calling the API.
## What's Next
- Continue to [Step 6: Proxy](/react-tutorial/06-proxy)

View File

@ -1,85 +0,0 @@
# React Nx Tutorial - Step 6: Proxy Configuration
{% youtube
src="https://www.youtube.com/embed/xfvCz-yLeEw"
title="Nx.dev Tutorial | React | Step 6: Proxy"
width="100%" /%}
You passed `--frontendProject=todos` when creating the node application. What did that argument do?
It created a proxy configuration that allows the React application to talk to the API in development.
**To see how it works, open `apps/todos/project.json` and find the `serve` target.**
```json
{
"serve": {
"executor": "@nrwl/web:dev-server",
"options": {
"buildTarget": "todos:build",
"hmr": true,
"proxyConfig": "apps/todos/proxy.conf.json"
},
"configurations": {
"production": {
"buildTarget": "todos:build:production",
"hmr": false
}
}
}
}
```
Note the `proxyConfig` property which points to `apps/todos/proxy.conf.json`. Open this file.
```json
{
"/api": {
"target": "http://localhost:3333",
"secure": false
}
}
```
This configuration tells `npx nx serve` to forward all requests starting with `/api` to the process listening on port `3333`.
## Project.json, Targets, Executors
You configure your apps in `apps/[app-name]/project.json`. Open `apps/todos/project.json` to see an example. This file contains configuration for the todos app. For instance, you can see the `build`, `serve`, `lint`, and `test` targets. This means that you can run `npx nx build todos`, `npx nx serve todos`, etc..
Every target uses an executor which actually runs this target. So targets are analogous to typed npm scripts, and executors are analogous to typed shell scripts.
**Why not use shell scripts and npm scripts directly?**
There are a lot of advantages to providing additional metadata to the build tool. For instance, you can introspect targets. `npx nx serve todos --help` results in:
```shell
nx run todos:serve [options,...]
Options:
--buildTarget Target which builds the application
--port Port to listen on. (default: 4200)
--host Host to listen on. (default: localhost)
--ssl Serve using HTTPS.
--sslKey SSL key to use for serving HTTPS.
--sslCert SSL certificate to use for serving HTTPS.
--watch Watches for changes and rebuilds application (default: true)
--liveReload Whether to reload the page on change, using live-reload. (default: true)
--hmr Enable hot module replacement.
--publicHost Public URL where the application will be served
--open Open the application in the browser.
--allowedHosts This option allows you to whitelist services that are allowed to access the dev server.
--memoryLimit Memory limit for type checking service process in MB.
--maxWorkers Number of workers to use for type checking.
--baseHref Base url for the application being built.
--skip-nx-cache Skip the use of Nx cache.
--help Show available options for project target.
```
It helps with good editor integration (see [VSCode Support](/core-features/integrate-with-editors#nx-console-for-vscode)).
But, most importantly, it provides a holistic dev experience regardless of the tools used, and enables advanced build features like distributed [computation caching](/concepts/how-caching-works) and [distributed builds](/concepts/dte).
## What's Next
- Continue to [Step 7: Share Code](/react-tutorial/07-share-code)

View File

@ -1,96 +0,0 @@
# React Nx Tutorial - Step 7: Share Code
{% youtube
src="https://www.youtube.com/embed/-zzw4_oT_2I"
title="Nx.dev Tutorial | React | Step 7: Share Code"
width="100%" /%}
Awesome! The application is working end to end! However, there is a problem. Both the backend and the frontend define the `Todo` interface. The interface is in sync now, but in a real application, over time, it diverges, and, as a result, runtime errors creep in. You should share this interface between the backend and the frontend. In Nx, you do this by creating a library.
**Run the following generator to create a library:**
```shell
npx nx g @nrwl/workspace:lib data
```
The result should look like this:
```treeview
myorg/
├── apps/
│ ├── todos/
│ ├── todos-e2e/
│ └── api/
├── libs/
│ └── data/
│ ├── src/
│ │ ├── lib/
│ │ │ └── data.ts
│ │ └── index.ts
│ ├── jest.config.ts
│ ├── project.json
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── tools/
├── nx.json
├── package.json
└── tsconfig.base.json
```
**Copy the interface into `libs/data/src/lib/data.ts`.**
```typescript
export interface Todo {
title: string;
}
```
### A note about VS Code :
If you're using [VS Code](https://code.visualstudio.com/) it may be necessary at this point to restart the TS server so that the new `@myorg/data` package is recognised. This may need to be done **every time a new workspace library is added**. If you install the [Nx Console](/core-features/integrate-with-editors) extension you won't need to take this step.
## Refactor the API
**Now update `apps/api/src/app/todos.ts` to import the interface:**
```typescript
import { Express } from 'express';
import { Todo } from '@myorg/data';
const todos: Todo[] = [{ title: 'Todo 1' }, { title: 'Todo 2' }];
export function addTodoRoutes(app: Express) {
app.get('/api/todos', (req, resp) => resp.send(todos));
app.post('/api/addTodo', (req, resp) => {
const newTodo = {
title: `New todo ${Math.floor(Math.random() * 1000)}`,
};
todos.push(newTodo);
resp.send(newTodo);
});
}
```
## Update the React application
**Next import the interface in `apps/todos/src/app/app.tsx`:**
```typescript
import { useEffect, useState } from 'react';
import { Todo } from '@myorg/data';
export const App = () => {
...
};
export default App;
```
Every time you add a new library, you have to restart `npx nx serve`.
**So restart both `npx nx serve api` and `npx nx serve todos` and you should see the application running.**
## What's Next
- Continue to [Step 8: Create Libraries](/react-tutorial/08-create-libs)

View File

@ -1,187 +0,0 @@
# React Nx Tutorial - Step 8: Create Libs
{% youtube
src="https://www.youtube.com/embed/a1CAYlXizWM"
title="Nx.dev Tutorial | React | Step 8: Create Libs"
width="100%" /%}
Libraries are not just a way to share code in Nx. They are also useful for factoring out code into small units with a well-defined public API.
## Public API
Every library has an `index.ts` file, which defines its public API. Other applications and libraries should only access what the `index.ts` exports. Everything else in the library is private.
## UI libraries
To illustrate how useful libraries can be, create a library of React components.
Run
```shell
npx nx g @nrwl/react:lib ui
```
You should see the following:
```treeview
myorg/
├── apps/
│ ├── todos/
│ ├── todos-e2e/
│ └── api/
├── libs/
│ ├── data/
│ └── ui/
│ ├── src/
│ │ ├── lib/
│ │ │ ├── ui.module.css
│ │ │ ├── ui.spec.tsx
│ │ │ └── ui.tsx
│ │ └── index.ts
│ ├── jest.config.ts
│ ├── project.json
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── tools/
├── nx.json
├── package.json
└── tsconfig.base.json
```
The `libs/ui/src/lib/ui.tsx` file looks like this:
```typescript
import './ui.module.css';
/* eslint-disable-next-line */
export interface UiProps {}
export function Ui(props: UiProps) {
return (
<div>
<h1>Welcome to Ui!</h1>
</div>
);
}
export default Ui;
```
## Add a component
Here, you can either change the UI component or generate a new one.
**Add a component to the newly created ui library by running:**
```shell
npx nx g @nrwl/react:component todos --project=ui --export
```
```treeview
myorg/
├── apps/
│ ├── todos/
│ ├── todos-e2e/
│ └── api/
├── libs/
│ ├── data/
│ └── ui/
│ ├── src/
│ │ ├── lib/
│ │ │ └── todos/
│ │ │ │ ├── todos.module.css
│ │ │ │ ├── todos.spec.tsx
│ │ │ │ └── todos.tsx
│ │ │ ├── ui.css
│ │ │ ├── ui.spec.tsx
│ │ │ └── ui.tsx
│ │ └── index.ts
│ ├── jest.config.ts
│ ├── project.json
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── tools/
├── nx.json
├── package.json
└── tsconfig.base.json
```
**Implement the Todos component.**
`libs/ui/src/lib/todos/todos.tsx`
```typescript
import { Todo } from '@myorg/data';
import './todos.module.css';
export interface TodosProps {
todos: Todo[];
}
export function Todos(props: TodosProps) {
return (
<ul>
{props.todos.map((t) => (
<li className={'todo'}>{t.title}</li>
))}
</ul>
);
}
export default Todos;
```
## Use the UI library
**Now import `Todos` into `apps/todos/src/app/app.tsx`.**
```typescript
import { useEffect, useState } from 'react';
import { Todo } from '@myorg/data';
import { Todos } from '@myorg/ui';
const App = () => {
const [todos, setTodos] = useState<Todo[]>([]);
useEffect(() => {
fetch('/api/todos')
.then((_) => _.json())
.then(setTodos);
}, []);
function addTodo() {
fetch('/api/addTodo', {
method: 'POST',
body: '',
})
.then((_) => _.json())
.then((newTodo) => {
setTodos([...todos, newTodo]);
});
}
return (
<>
<h1>Todos</h1>
<Todos todos={todos} />
<button id={'add-todo'} onClick={addTodo}>
Add Todo
</button>
</>
);
};
export default App;
```
**Restart both `npx nx serve api` and `npx nx serve todos` and you should see the application running.**
{% callout type="note" title="Nx helps you" %}
Nx helps you explore code generation options. Run `npx nx g @nrwl/react:component --help` to see all options available. Pass `--dry-run` to the command to see what would be generated without actually changing anything, like this: `npx nx g @nrwl/react:component mycmp --project=ui --dry-run`.
{% /callout %}
## What's Next
- Continue to [Step 9: Using the Project Graph](/react-tutorial/09-dep-graph)

View File

@ -1,24 +0,0 @@
# React Nx Tutorial - Step 9: Project Graph
{% youtube
src="https://www.youtube.com/embed/Dr7jI9RYcmY"
title="Nx.dev Tutorial | React | Step 9: Dep Graph"
width="100%" /%}
An Nx workspace can contain dozens or hundreds of applications and libraries. As a codebase grows, it can be difficult to understand how they depend on each other and the implications of making a particular change.
Previously, some senior architect would create an ad-hoc dependency diagram and upload it to a corporate wiki. The diagram is not correct even on Day 1 and gets more and more out of sync with every passing day.
With Nx, you can do better than that.
Run
```shell
npx nx graph
```
The project graph page opens in a new browser window. Click on "Show all projects" to see all the apps and libraries in the workspace.
## What's Next
- Continue to [Step 10: Using Computation Caching](/react-tutorial/10-computation-caching)

View File

@ -0,0 +1,147 @@
---
title: 'React Tutorial - Part 1: Code Generation'
description: In this tutorial you'll create a frontend-focused workspace with Nx.
---
{% callout type="check" title="Two Styles of Repo" %}
There are two styles of repos: integrated and package-based. This tutorial shows the integrated style.
You can find more information on the difference between the two in [our introduction](/getting-started/intro).
{% /callout %}
# React Tutorial - Part 1: Code Generation
## Contents
- [1 - Code Generation](/react-tutorial/1-code-generation)
- [2 - Project Graph](/react-tutorial/2-project-graph)
- [3 - Task Running](/react-tutorial/3-task-running)
- [4 - Workspace Optimization](/react-tutorial/4-workspace-optimization)
- [5 - Summary](/react-tutorial/5-summary)
## Your Objective
For this tutorial, you'll create two React applications, a React lib for your common components, and a library for your business logic as follows:
![Our Workspace Requirements](/shared/react-tutorial/requirements-diagram.png)
## Creating an Nx Workspace
Run the command `npx create-nx-workspace@latest` and when prompted, provide the following responses:
```{% command="npx create-nx-workspace@latest" path="~" %}
✔ Choose your style · integrated
✔ What to create in the new workspace · react
✔ Repository name · myorg
✔ Application name · store
✔ Default stylesheet format · css
✔ Enable distributed caching to make your CI faster · No
```
{% card title="Opting into Nx Cloud" description="You will also be prompted whether to add Nx Cloud to your workspace. We won't address this in this tutorial, but you can see the introduction to Nx Cloud for more details." url="/nx-cloud/intro/what-is-nx-cloud" /%}
Once the command completes, notice two projects were added to the workspace:
- A React application located in `apps/store`.
- A Project for Cypress e2e tests for our `store` application in `apps/store-e2e`.
{% card title="Nx Cypress Support" description="While we see the Cypress project here, we won't go deeper on Cypress in this tutorial. You can find more materials on Nx Cypress support on the @nrwl/cypress package page." url="/packages/cypress" /%}
## Adding Another Application to Your Workspace
Run this command to create your `admin` app:
```{% command="npx nx g @nrwl/react:app admin" path="~/myorg" %}
> NX Generating @nrwl/react:application
CREATE apps/admin/.babelrc
CREATE apps/admin/.browserslistrc
CREATE apps/admin/src/app/app.spec.tsx
CREATE apps/admin/src/app/nx-welcome.tsx
CREATE apps/admin/src/assets/.gitkeep
CREATE apps/admin/src/environments/environment.prod.ts
CREATE apps/admin/src/environments/environment.ts
CREATE apps/admin/src/favicon.ico
CREATE apps/admin/src/index.html
CREATE apps/admin/src/main.tsx
CREATE apps/admin/src/polyfills.ts
CREATE apps/admin/tsconfig.app.json
CREATE apps/admin/tsconfig.json
CREATE apps/admin/src/app/app.module.css
CREATE apps/admin/src/app/app.tsx
CREATE apps/admin/src/styles.css
CREATE apps/admin/project.json
CREATE apps/admin/.eslintrc.json
CREATE apps/admin-e2e/cypress.config.ts
CREATE apps/admin-e2e/src/e2e/app.cy.ts
CREATE apps/admin-e2e/src/fixtures/example.json
CREATE apps/admin-e2e/src/support/app.po.ts
CREATE apps/admin-e2e/src/support/commands.ts
CREATE apps/admin-e2e/src/support/e2e.ts
CREATE apps/admin-e2e/tsconfig.json
CREATE apps/admin-e2e/project.json
CREATE apps/admin-e2e/.eslintrc.json
CREATE apps/admin/jest.config.ts
CREATE apps/admin/tsconfig.spec.json
```
![Nx Generator Syntax](/shared/react-tutorial/generator-syntax.png)
## Generating Libraries
To create the `common-ui` and `products` libraries, use the `@nrwl/react:lib` and `@nrwl/js:lib` generators respectively:
{% side-by-side %}
```{% command="npx nx g @nrwl/react:lib common-ui" path="~/myorg" %}
> NX Generating @nrwl/react:library
CREATE libs/common-ui/project.json
CREATE libs/common-ui/.eslintrc.json
CREATE libs/common-ui/.babelrc
CREATE libs/common-ui/README.md
CREATE libs/common-ui/src/index.ts
CREATE libs/common-ui/tsconfig.json
CREATE libs/common-ui/tsconfig.lib.json
UPDATE tsconfig.base.json
CREATE libs/common-ui/jest.config.ts
CREATE libs/common-ui/tsconfig.spec.json
CREATE libs/common-ui/src/lib/common-ui.module.css
CREATE libs/common-ui/src/lib/common-ui.spec.tsx
CREATE libs/common-ui/src/lib/common-ui.tsx
```
```{% command="npx nx g @nrwl/js:lib products" path="~/myorg" %}
> NX Generating @nrwl/js:library
CREATE libs/products/README.md
CREATE libs/products/package.json
CREATE libs/products/src/index.ts
CREATE libs/products/src/lib/products.spec.ts
CREATE libs/products/src/lib/products.ts
CREATE libs/products/tsconfig.json
CREATE libs/products/tsconfig.lib.json
CREATE libs/products/.babelrc
CREATE libs/products/project.json
UPDATE tsconfig.base.json
CREATE libs/products/.eslintrc.json
CREATE libs/products/jest.config.ts
CREATE libs/products/tsconfig.spec.json
```
{% /side-by-side %}
You should now be able to see all four projects of our design:
- `store` in `apps/store`
- `admin` in `apps/admin`
- `products` in `libs/products`
- `common-ui` in `libs/common-ui`
## What's Next
- Continue to [2: Project Graph](/react-tutorial/2-project-graph)

View File

@ -1,64 +0,0 @@
# React Nx Tutorial - Step 10: Computation Caching
{% youtube
src="https://www.youtube.com/embed/aNjvT3VX1Ts"
title="Nx.dev Tutorial | React | step 10: Computation Caching"
width="100%" /%}
Nx has built-in computation caching, which helps drastically improve the performance of the commands.
**To see it in action, run `npx nx build todos`:**
```shell
> npx nx run todos:build
Starting type checking service...
Using 14 workers with 2048MB memory limit
Hash: c38fbdb8b372af447180
Built at: 03/26/2020 11:03:57 AM
Entrypoint main = runtime.ff0534391bf88384547e.js main.b8dbcd3d3fd2900377f2.esm.js
Entrypoint polyfills = runtime.ff0534391bf88384547e.js polyfills.55535a35b1529d884ca3.esm.js
Entrypoint styles = runtime.ff0534391bf88384547e.js styles.3ff695c00d717f2d2a11.css
chunk {0} runtime.ff0534391bf88384547e.js (runtime) 0 bytes ={1}= ={2}= ={3}= [entry] [rendered]
chunk {1} main.b8dbcd3d3fd2900377f2.esm.js (main) 155 KiB ={0}= [initial] [rendered]
chunk {2} polyfills.55535a35b1529d884ca3.esm.js (polyfills) 239 KiB ={0}= [initial] [rendered]
chunk {3} styles.3ff695c00d717f2d2a11.css (styles) 147 bytes ={0}= [initial] [rendered]
```
**Now, run `npx nx build todos` again, and you see the results appearing instantly:**
```shell
> npx nx run todos:build
> NX NOTE Cached Output:
Starting type checking service...
Using 14 workers with 2048MB memory limit
Hash: c38fbdb8b372af447180
Built at: 03/26/2020 11:05:06 AM
Entrypoint main = runtime.ff0534391bf88384547e.js main.b8dbcd3d3fd2900377f2.esm.js
Entrypoint polyfills = runtime.ff0534391bf88384547e.js polyfills.55535a35b1529d884ca3.esm.js
Entrypoint styles = runtime.ff0534391bf88384547e.js styles.3ff695c00d717f2d2a11.css
chunk {0} runtime.ff0534391bf88384547e.js (runtime) 0 bytes ={1}= ={2}= ={3}= [entry] [rendered]
chunk {1} main.b8dbcd3d3fd2900377f2.esm.js (main) 155 KiB ={0}= [initial] [rendered]
chunk {2} polyfills.55535a35b1529d884ca3.esm.js (polyfills) 239 KiB ={0}= [initial] [rendered]
chunk {3} styles.3ff695c00d717f2d2a11.css (styles) 147 bytes ={0}= [initial] [rendered]
```
Based on the state of the source code and the environment, Nx figured out that it had already run this exact command. Nx found the artifact in the local cache and replayed the output and restored the necessary files.
## Building multiple projects
**Now, run `npx nx run-many --target=build --projects=todos,api` to rebuild the two applications:**
```shell
Nx read the output from the cache instead of running the command for 1 out of 2 projects.
```
Nx built `api` and retrieved `todos` from its computation cache. Read more about the cache [here](/concepts/how-caching-works).
> Add --parallel to any command, and Nx does most of the work in parallel.
## What's Next
- Continue to [Step 11: Test Affected Projects](/react-tutorial/11-test-affected-projects)

View File

@ -1,81 +0,0 @@
# React Nx Tutorial - Step 11: Test Affected Projects
{% youtube
src="https://www.youtube.com/embed/_mBBFRjs01g"
title="Nx.dev Tutorial | React | Step 11: Test Affected Projects"
width="100%" /%}
In addition to supporting computation caching, Nx scales your development by doing code change analysis to see what is affected by a particular pull request.
**Commit all the changes you have made so far**:
```shell
git add .
git commit -am 'init'
git checkout -b testbranch
```
**Open `libs/ui/src/lib/todos/todos.tsx` and change the component by updating the `<li>` content to `{t.title}!!`:**
```typescript
import { Todo } from '@myorg/data';
import './todos.module.css';
export interface TodosProps {
todos: Todo[];
}
export function Todos(props: TodosProps) {
return (
<ul>
{props.todos.map((t) => (
<li className={'todo'}>{t.title}!!</li>
))}
</ul>
);
}
export default Todos;
```
**Run `npx nx print-affected --type=app --select=projects`**, and you should see `todos` printed out. The `print-affected` looks at what you have changed and uses the project graph to figure out which apps can be affected by this change.
**Run `npx nx print-affected --type=lib --select=projects`**, and you should see `ui` printed out. This command works similarly, but instead of printing the affected apps, it prints the affected libs.
## Test Affected Projects
Printing the affected projects can be handy, but usually you want to do something with them. For instance, you may want to test everything that has been affected.
**Run `npx nx affected:test` to retest only the projects affected by the change.**
As you can see, since we updated the code, without updating the tests, the unit tests failed.
```shell
> NX Running target test for projects:
- ui
- todos
...
Failed projects:
- todos
- ui
```
Note that Nx only tried to retest `ui` and `todos`. It didn't retest `api` or `data` because there is no way that could be affected by the changes in this branch.
## Affected:\*
You can run any target against the affected projects in the graph like this:
```shell
# The following are equivalent
npx nx affected --target=build
npx nx affected:build
```
## What's Next
- Continue to [Step 12: Summary](/react-tutorial/12-summary)

View File

@ -1,17 +0,0 @@
# React Nx Tutorial - Step 12: Summary
In this tutorial you:
- Built a full stack application using React and Express
- Shared code between the frontend and the backend
- Created a UI library
- Used Nx affected commands to only retest and rebuild what is affected
## Learn more
- [Free Nx Course on YouTube](https://www.youtube.com/playlist?list=PLakNactNC1dH38AfqmwabvOszDmKriGco)
**Dive Deep:**
- [Computation Caching](/concepts/how-caching-works)
- [Rebuilding What is Affected](/concepts/affected)

View File

@ -0,0 +1,126 @@
# React Tutorial - Part 2: Project Graph
Run the command: `npx nx graph`. A browser should open up with the following contents:
![Initial Project Graph](/shared/react-tutorial/initial-project-graph.png)
This is still different than the design from the start of Part 1:
![Our Workspace Requirements](/shared/react-tutorial/requirements-diagram.png)
The Project Graph is derived from the source code of your workspace. Make the following adjustments to your existing projects, so that our Project Graph will match the design:
### `common-ui`
Run the `@nrwl/react:component` generator with the command:
```{% command="npx nx g @nrwl/react:component banner --project=common-ui --export" path="~/myorg" %}
> NX Generating @nrwl/react:component
CREATE libs/common-ui/src/lib/banner/banner.module.css
CREATE libs/common-ui/src/lib/banner/banner.spec.tsx
CREATE libs/common-ui/src/lib/banner/banner.tsx
UPDATE libs/common-ui/src/index.ts
```
Then create a simple `Banner` component in the generated file:
```javascript {% fileName="libs/common-ui/src/lib/banner/banner.tsx" %}
export interface BannerProps {
text: string;
}
export function Banner(props: BannerProps) {
return <header>{props.text}</header>;
}
export default Banner;
```
### `admin`
Add the `Banner` component to the admin app:
```javascript {% fileName="apps/admin/src/app/app.tsx" %}
import { Banner } from '@myorg/common-ui';
export function App() {
return (
<>
<Banner text="Welcome to our admin app." />
<div />
</>
);
}
export default App;
```
### `products`
Export a `Product` TS interface and some example products:
```javascript {% fileName="libs/products/src/lib/products.ts" %}
export interface Product {
id: string;
name: string;
price: number;
}
export const exampleProducts: Product[] = [
{
id: '1',
name: 'Product 1',
price: 100,
},
{
id: '2',
name: 'Product 2',
price: 200,
},
];
```
### `store`
Use both the `Banner` component from your `common-ui` lib, and the `exampleProducts` from your `products` lib:
```javascript {% fileName="apps/store/src/app/app.tsx" %}
import { Banner } from '@myorg/common-ui';
import { exampleProducts } from '@myorg/products';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function App() {
return (
<>
<Banner text="Welcome to the store!" />
<ul>
{exampleProducts.map((product) => (
<li key={product.id}>
<strong>{product.name}</strong> Price: {product.price}
</li>
))}
</ul>
</>
);
}
export default App;
```
Now run `npx nx graph` again:
{% side-by-side %}
![Matching Graph](/shared/react-tutorial/matching-graph.png)
![Our Workspace Requirements](/shared/react-tutorial/requirements-diagram.png)
{% /side-by-side %}
Your graph now matches the original design.
The Project Graph is more than just a visualization - Nx provides tooling to optimize your task-running and even automate your CI based on this graph. This will be covered in more detail in: [4: Workspace Optimization](/react-tutorial/4-workspace-optimization).
## What's Next
- Continue to [3: Task Running](/react-tutorial/3-task-running)

View File

@ -0,0 +1,95 @@
# React Tutorial - 3: Task-Running
Common tasks include:
- Building an application
- Serving a local web server with the built project
- Running your unit tests
- Linting your code
- Running e2e tests
When you ran your generators in Part 1, you already set up these more common tasks for each project.
## Defining Targets
Here's the `project.json` file for your `common-ui` project:
```json {% fileName="libs/common-ui/project.json" %}
{
"name": "common-ui",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/common-ui/src",
"projectType": "library",
"tags": [],
"targets": {
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/common-ui/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/common-ui"],
"options": {
"jestConfig": "libs/common-ui/jest.config.ts",
"passWithNoTests": true
}
}
}
}
```
You can see that two targets are defined here: `test` and `lint`.
The properties inside each of these these targets is defined as follows:
- `executor` - which Nx executor to run. The syntax here is: `<plugin name>:<executor name>`
- `outputs` - this is an array of files that would be created by running this target. (This informs Nx on what to save for it's caching mechanisms you'll learn about in [4 - Workspace Optimizations](/react-tutorial/4-workspace-optimization)).
- `options` - this is an object defining which executor options to use for the given target. Every Nx executor allows for options as a way to parameterize it's functionality.
## Running Tasks
![Syntax for Running Tasks in Nx](/shared/react-tutorial/run-target-syntax.png)
Run the `test` target for your `common-ui` project:
```{% command="npx nx test common-ui" path="~/myorg" %}
> nx run common-ui:test
PASS common-ui libs/common-ui/src/lib/common-ui.spec.tsx
PASS common-ui libs/common-ui/src/lib/banner/banner.spec.tsx
Test Suites: 2 passed, 2 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.84 s, estimated 1 s
Ran all test suites.
———————————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target test for project common-ui (2s)
```
Next, run a lint check on your `common-ui` project:
```{% command="npx nx lint common-ui" path="~/myorg" %}
> nx run common-ui:lint
Linting "common-ui"...
All files pass linting.
———————————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target lint for project common-ui (2s)
```
## What's Next
- Continue to [4: Workspace Optimization](/react-tutorial/4-workspace-optimization)

View File

@ -0,0 +1,201 @@
# React Tutorial - Part 4: Workspace Optimization
## Testing Affected Projects
`affected` is a mechanism that relies on your git metadata to determine the projects in your workspace that were affected by a given commit.
Run the command:
```{% command="git add . && git commit -m 'commiting to test affected'" path="~/myorg" %}
```
Then make a change to the styles of your `common-ui` project:
```css {% fileName="libs/common-ui/src/lib/common-ui.module.css" %}
.container {
color: 'blue;';
}
```
You can visualize how our workspace is affected by this change using the command:
```{% command="npx nx affected:graph" path="~/myorg" %}
```
![Project Graph with Affected](/shared/react-tutorial/project-graph-with-affected.png)
The change made to the `common-ui` project is also affecting the `admin` and `store` projects. This can be leveraged run tasks only on the projects that were affected by this commit.
To run the `test` targets only for affected projects, run the command:
```{% command="npx nx affected --target=test" path="~/myorg" %}
```
This can be particularly helpful in CI pipelines for larger repos, where most commits only affect a small subset of the entire workspace.
{% card title="Affected Documentation" description="Checkout Affected documentation for more details" url="/nx/affected" /%}
## Task Caching
`affected` allows you to "skip" tasks that couldn't possibly be affected by your changes. Task Caching allows you to "replay" tasks that have already been run.
Task Caching is informed by "inputs" and "outputs":
### Inputs
Inputs for your task caching includes by default any environment details and all the source code of the projects and dependencies affecting your project.
When running a task, Nx will determine all the inputs for your task and create a hash that will be used to index your cache. If you've already run this task with the same inputs, your cache will already be populated at this index, and Nx will replay the results stored in the cache.
If this index does not exist, Nx will run the command and if the command succeeds, it will store the result in the cache.
### Outputs
Outputs of the cache include the terminal output created by the task, as well as any files created by the task - for example: the artifact created by running a `build` task.
Outputs are defined for every target in your workspace:
```json {% fileName="libs/products/project.json" %}
{
"name": "products",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/products/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nrwl/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/products",
"main": "libs/products/src/index.ts",
"tsConfig": "libs/products/tsconfig.lib.json",
"assets": ["libs/products/*.md"]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/products/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/products"],
"options": {
"jestConfig": "libs/products/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": []
}
```
Outputs are stored in the cache so that terminal output can be replayed, and any created files can be pulled from your cache, and placed where they were created the original time the task was run.
### Example
To see caching in action, run the command:
```{% command="npx nx build admin" path="~/myorg" %}
> nx run admin:build:production
Entrypoint main 139 KiB = runtime.54e36ebee261465d.js 1.19 KiB main.623d91691bdb6754.css 42 bytes main.303fe7c1dcf5306b.js 137 KiB
Entrypoint polyfills 93.5 KiB = runtime.54e36ebee261465d.js 1.19 KiB polyfills.bd0d0abec287a28e.js 92.3 KiB
Entrypoint styles 1.19 KiB = runtime.54e36ebee261465d.js 1.19 KiB styles.ef46db3751d8e999.css 0 bytes
chunk (runtime: runtime) main.623d91691bdb6754.css, main.303fe7c1dcf5306b.js (main) 144 KiB (javascript) 50 bytes (css/mini-extract) [initial] [rendered]
chunk (runtime: runtime) polyfills.bd0d0abec287a28e.js (polyfills) 301 KiB [initial] [rendered]
chunk (runtime: runtime) styles.ef46db3751d8e999.css (styles) 50 bytes (javascript) 80 bytes (css/mini-extract) [initial] [rendered]
chunk (runtime: runtime) runtime.54e36ebee261465d.js (runtime) 3.23 KiB [entry] [rendered]
webpack compiled successfully (0c0df3e6c70c6b7b)
———————————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target build for project admin (4s)
```
Since you have not run the `build` target before for the `admin` project, Nx runs the `build`, and populates the results in `dist/apps/admin` as specified in the `admin` project's `project.json` file for the `build` target.
Next, remove your dist directory:
```{% command="rm -rf dist" path="~/myorg" %}
```
And run the command again:
```{% command="npx nx build admin" path="~/myorg" %}
> nx run admin:build:production [local cache]
Entrypoint main 139 KiB = runtime.54e36ebee261465d.js 1.19 KiB main.623d91691bdb6754.css 42 bytes main.303fe7c1dcf5306b.js 137 KiB
Entrypoint polyfills 93.5 KiB = runtime.54e36ebee261465d.js 1.19 KiB polyfills.bd0d0abec287a28e.js 92.3 KiB
Entrypoint styles 1.19 KiB = runtime.54e36ebee261465d.js 1.19 KiB styles.ef46db3751d8e999.css 0 bytes
chunk (runtime: runtime) main.623d91691bdb6754.css, main.303fe7c1dcf5306b.js (main) 144 KiB (javascript) 50 bytes (css/mini-extract) [initial] [rendered]
chunk (runtime: runtime) polyfills.bd0d0abec287a28e.js (polyfills) 301 KiB [initial] [rendered]
chunk (runtime: runtime) styles.ef46db3751d8e999.css (styles) 50 bytes (javascript) 80 bytes (css/mini-extract) [initial] [rendered]
chunk (runtime: runtime) runtime.54e36ebee261465d.js (runtime) 3.23 KiB [entry] [rendered]
webpack compiled successfully (0c0df3e6c70c6b7b)
———————————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target build for project admin (59ms)
Nx read the output from the cache instead of running the command for 1 out of 1 tasks.
```
Notice that `[local cache]` is mentioned in the terminal output, and that this time the command only took 59ms to run.
Also notice that the result of your build has been added back to the `dist/apps/admin` directory.
{% card title="More Task Caching Details" description="See the documentation for more information on caching." url="/core-features/cache-task-results" /%}
## Configuring Task Pipelines
Next, run the command `npx nx build store`:
```{% command="npx nx build store" path="~/myorg" %}
✔ 1/1 dependent project tasks succeeded [0 read from cache]
Hint: you can run the command with --verbose to see the full dependent project outputs
———————————————————————————————————————————————————————————————————————————————————————————————————
> nx run store:build:production
Entrypoint main 139 KiB = runtime.54e36ebee261465d.js 1.19 KiB main.623d91691bdb6754.css 42 bytes main.94f9a4a3cec4f056.js 138 KiB
Entrypoint polyfills 93.5 KiB = runtime.54e36ebee261465d.js 1.19 KiB polyfills.bd0d0abec287a28e.js 92.3 KiB
Entrypoint styles 1.19 KiB = runtime.54e36ebee261465d.js 1.19 KiB styles.ef46db3751d8e999.css 0 bytes
chunk (runtime: runtime) main.623d91691bdb6754.css, main.94f9a4a3cec4f056.js (main) 145 KiB (javascript) 50 bytes (css/mini-extract) [initial] [rendered]
chunk (runtime: runtime) polyfills.bd0d0abec287a28e.js (polyfills) 301 KiB [initial] [rendered]
chunk (runtime: runtime) styles.ef46db3751d8e999.css (styles) 50 bytes (javascript) 80 bytes (css/mini-extract) [initial] [rendered]
chunk (runtime: runtime) runtime.54e36ebee261465d.js (runtime) 3.23 KiB [entry] [rendered]
webpack compiled successfully (06e95dfdacea84c7)
———————————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target build for project store and 1 task(s) it depends on (5s)
```
Notice the line here:
```plain
✔ 1/1 dependent project tasks succeeded [0 read from cache]
```
This is because your `store` project depends on your `products` project, which also has a `build` target. By default Nx is configured to run the `build` target for any dependencies that have a `build` target, before running the `build` on the original project.
This feature allows the Nx graph to dynamically maintain task dependencies, rather than having to manually maintain those task dependencies as your workspace continues to grow.
{% card title="More On The Task Pipeline Configuration" description="See the Task Pipeline Configuration Guide for more details on how to configure your Task Graph." url="/concepts/task-pipeline-configuration" /%}
## What's Next
- Continue to [5: Summary](/react-tutorial/5-summary)

View File

@ -0,0 +1,26 @@
# React Tutorial - Part 5: Summary
In this tutorial you:
- Learned how to use Nx's Generators to generate code for your workspace.
- Learned how Nx determines a graph of your workspace
- Learned how to configure and run tasks in your workspace
- Learned how Nx's built-in optimizations work, and how to apply those to your own workspace
## Learn More
{% cards %}
{% card title="Free Nx Course on YouTube" description="Follow up this tutorial with our free Nx Course." type="video" url="https://www.youtube.com/playlist?list=PLakNactNC1dH38AfqmwabvOszDmKriGco" /%}
{% card title="Free Nx Course From Egghead" type="external" description="Follow up this tutorial with a free course on React development with Nx we made in collaboration with Egghead." url="https://egghead.io/courses/scale-react-development-with-nx-4038" /%}
{% card title="Core Features" description="Learn more about the Core Features of Nx." url="/core-features" /%}
{% card title="The Nx Mental Model" description="Expand your Mental Model of Nx." url="/concepts/mental-model" /%}
{% card title="Distributed Task Execution" description="Learn how to use Nx Cloud for Distributed Task Execution to speed up your CI times even more." url="/concepts/dte" /%}
{% card title="Configure CI For Your Workspace" description="Learn how to create CI configuration for your workspace using our ci-workflow generator, or by creating your own workflow." url="/recipes/ci-setup" /%}
{% /cards %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -54,8 +54,8 @@ module.exports = withNx({
permanent: true,
});
rules.push({
source: '/(l|latest)/(n|node)/tutorial/01-create-application',
destination: '/node-tutorial/01-create-application',
source: '/(l|latest)/(n|node)/tutorial/1-code-generation',
destination: '/node-tutorial/1-code-generation',
permanent: true,
});

View File

@ -1046,11 +1046,11 @@ function pointToTutorialAndCourse(preset: Preset) {
bodyLines: [`https://nx.dev/angular-tutorial/01-create-application`],
});
break;
case Preset.Nest:
case Preset.Express:
output.addVerticalSeparator();
output.note({
title,
bodyLines: [`https://nx.dev/node-tutorial/01-create-application`],
bodyLines: [`https://nx.dev/node-tutorial/1-code-generation`],
});
break;
}