docs(core): maintain ts monorepos feature (#30256)
Adds the Maintain TypeScript Monorepos feature page
This commit is contained in:
parent
8e6c00719b
commit
c698b1ef9c
@ -235,6 +235,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"disableCollapsible": false
|
"disableCollapsible": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"path": "/features/maintain-ts-monorepos",
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"isExternal": false,
|
||||||
|
"children": [],
|
||||||
|
"disableCollapsible": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Automate Updating Dependencies",
|
"name": "Automate Updating Dependencies",
|
||||||
"path": "/features/automate-updating-dependencies",
|
"path": "/features/automate-updating-dependencies",
|
||||||
@ -359,6 +367,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"disableCollapsible": false
|
"disableCollapsible": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"path": "/features/maintain-ts-monorepos",
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"isExternal": false,
|
||||||
|
"children": [],
|
||||||
|
"disableCollapsible": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Automate Updating Dependencies",
|
"name": "Automate Updating Dependencies",
|
||||||
"path": "/features/automate-updating-dependencies",
|
"path": "/features/automate-updating-dependencies",
|
||||||
|
|||||||
@ -317,6 +317,17 @@
|
|||||||
"path": "/features/generate-code",
|
"path": "/features/generate-code",
|
||||||
"tags": ["generate-code"]
|
"tags": ["generate-code"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"description": "",
|
||||||
|
"mediaImage": "",
|
||||||
|
"file": "shared/features/maintain-typescript-monorepos",
|
||||||
|
"itemList": [],
|
||||||
|
"isExternal": false,
|
||||||
|
"path": "/features/maintain-ts-monorepos",
|
||||||
|
"tags": ["inferred-tasks", "project-linking", "sync"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "automate-updating-dependencies",
|
"id": "automate-updating-dependencies",
|
||||||
"name": "Automate Updating Dependencies",
|
"name": "Automate Updating Dependencies",
|
||||||
@ -488,6 +499,17 @@
|
|||||||
"path": "/features/generate-code",
|
"path": "/features/generate-code",
|
||||||
"tags": ["generate-code"]
|
"tags": ["generate-code"]
|
||||||
},
|
},
|
||||||
|
"/features/maintain-ts-monorepos": {
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"description": "",
|
||||||
|
"mediaImage": "",
|
||||||
|
"file": "shared/features/maintain-typescript-monorepos",
|
||||||
|
"itemList": [],
|
||||||
|
"isExternal": false,
|
||||||
|
"path": "/features/maintain-ts-monorepos",
|
||||||
|
"tags": ["inferred-tasks", "project-linking", "sync"]
|
||||||
|
},
|
||||||
"/features/automate-updating-dependencies": {
|
"/features/automate-updating-dependencies": {
|
||||||
"id": "automate-updating-dependencies",
|
"id": "automate-updating-dependencies",
|
||||||
"name": "Automate Updating Dependencies",
|
"name": "Automate Updating Dependencies",
|
||||||
|
|||||||
@ -382,6 +382,110 @@
|
|||||||
"path": "/nx-api/nx/documents/generate"
|
"path": "/nx-api/nx/documents/generate"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"inferred-tasks": [
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/features/maintain-typescript-monorepos",
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"path": "/features/maintain-ts-monorepos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/concepts/mental-model",
|
||||||
|
"id": "mental-model",
|
||||||
|
"name": "Mental Model",
|
||||||
|
"path": "/concepts/mental-model"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/concepts/nx-plugins",
|
||||||
|
"id": "nx-plugins",
|
||||||
|
"name": "What Are Nx Plugins",
|
||||||
|
"path": "/concepts/nx-plugins"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/concepts/inferred-tasks",
|
||||||
|
"id": "inferred-tasks",
|
||||||
|
"name": "Inferred Tasks",
|
||||||
|
"path": "/concepts/inferred-tasks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/recipes/running-tasks/convert-to-inferred",
|
||||||
|
"id": "convert-to-inferred",
|
||||||
|
"name": "Migrate to Inferred Tasks (Project Crystal)",
|
||||||
|
"path": "/recipes/running-tasks/convert-to-inferred"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/recipes/plugins/project-graph-plugins",
|
||||||
|
"id": "project-graph-plugins",
|
||||||
|
"name": "Infer Tasks or Projects",
|
||||||
|
"path": "/extending-nx/recipes/project-graph-plugins"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"project-linking": [
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/features/maintain-typescript-monorepos",
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"path": "/features/maintain-ts-monorepos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/concepts/typescript-project-linking",
|
||||||
|
"id": "typescript-project-linking",
|
||||||
|
"name": "TypeScript Project Linking",
|
||||||
|
"path": "/concepts/typescript-project-linking"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/recipes/tips-n-tricks/switch-to-workspaces-project-references",
|
||||||
|
"id": "switch-to-workspaces-project-references",
|
||||||
|
"name": "Switch to Workspaces and TS Project References",
|
||||||
|
"path": "/recipes/tips-n-tricks/switch-to-workspaces-project-references"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sync": [
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/features/maintain-typescript-monorepos",
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"path": "/features/maintain-ts-monorepos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/concepts/sync-generators",
|
||||||
|
"id": "sync-generators",
|
||||||
|
"name": "Sync Generators",
|
||||||
|
"path": "/concepts/sync-generators"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "",
|
||||||
|
"file": "shared/recipes/generators/create-sync-generator",
|
||||||
|
"id": "create-sync-generator",
|
||||||
|
"name": "Create a Sync Generator",
|
||||||
|
"path": "/extending-nx/recipes/create-sync-generator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
||||||
|
"file": "generated/packages/nx/documents/sync",
|
||||||
|
"id": "sync",
|
||||||
|
"name": "sync",
|
||||||
|
"path": "/nx-api/nx/documents/sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
||||||
|
"file": "generated/packages/nx/documents/sync-check",
|
||||||
|
"id": "sync-check",
|
||||||
|
"name": "sync:check",
|
||||||
|
"path": "/nx-api/nx/documents/sync-check"
|
||||||
|
}
|
||||||
|
],
|
||||||
"automate-updating-dependencies": [
|
"automate-updating-dependencies": [
|
||||||
{
|
{
|
||||||
"description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.",
|
"description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.",
|
||||||
@ -621,43 +725,6 @@
|
|||||||
"path": "/concepts/mental-model"
|
"path": "/concepts/mental-model"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"inferred-tasks": [
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/concepts/mental-model",
|
|
||||||
"id": "mental-model",
|
|
||||||
"name": "Mental Model",
|
|
||||||
"path": "/concepts/mental-model"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/concepts/nx-plugins",
|
|
||||||
"id": "nx-plugins",
|
|
||||||
"name": "What Are Nx Plugins",
|
|
||||||
"path": "/concepts/nx-plugins"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/concepts/inferred-tasks",
|
|
||||||
"id": "inferred-tasks",
|
|
||||||
"name": "Inferred Tasks",
|
|
||||||
"path": "/concepts/inferred-tasks"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/recipes/running-tasks/convert-to-inferred",
|
|
||||||
"id": "convert-to-inferred",
|
|
||||||
"name": "Migrate to Inferred Tasks (Project Crystal)",
|
|
||||||
"path": "/recipes/running-tasks/convert-to-inferred"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/recipes/plugins/project-graph-plugins",
|
|
||||||
"id": "project-graph-plugins",
|
|
||||||
"name": "Infer Tasks or Projects",
|
|
||||||
"path": "/extending-nx/recipes/project-graph-plugins"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"add": [
|
"add": [
|
||||||
{
|
{
|
||||||
"description": "",
|
"description": "",
|
||||||
@ -748,52 +815,6 @@
|
|||||||
"path": "/nx-api/nx/documents/daemon"
|
"path": "/nx-api/nx/documents/daemon"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sync": [
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/concepts/sync-generators",
|
|
||||||
"id": "sync-generators",
|
|
||||||
"name": "Sync Generators",
|
|
||||||
"path": "/concepts/sync-generators"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/recipes/generators/create-sync-generator",
|
|
||||||
"id": "create-sync-generator",
|
|
||||||
"name": "Create a Sync Generator",
|
|
||||||
"path": "/extending-nx/recipes/create-sync-generator"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
|
||||||
"file": "generated/packages/nx/documents/sync",
|
|
||||||
"id": "sync",
|
|
||||||
"name": "sync",
|
|
||||||
"path": "/nx-api/nx/documents/sync"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
|
||||||
"file": "generated/packages/nx/documents/sync-check",
|
|
||||||
"id": "sync-check",
|
|
||||||
"name": "sync:check",
|
|
||||||
"path": "/nx-api/nx/documents/sync-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"project-linking": [
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/concepts/typescript-project-linking",
|
|
||||||
"id": "typescript-project-linking",
|
|
||||||
"name": "TypeScript Project Linking",
|
|
||||||
"path": "/concepts/typescript-project-linking"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"file": "shared/recipes/tips-n-tricks/switch-to-workspaces-project-references",
|
|
||||||
"id": "switch-to-workspaces-project-references",
|
|
||||||
"name": "Switch to Workspaces and TS Project References",
|
|
||||||
"path": "/recipes/tips-n-tricks/switch-to-workspaces-project-references"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"module-federation": [
|
"module-federation": [
|
||||||
{
|
{
|
||||||
"description": "",
|
"description": "",
|
||||||
|
|||||||
@ -101,6 +101,12 @@
|
|||||||
"tags": ["generate-code"],
|
"tags": ["generate-code"],
|
||||||
"file": "shared/features/generate-code"
|
"file": "shared/features/generate-code"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Maintain TypeScript Monorepos",
|
||||||
|
"id": "maintain-ts-monorepos",
|
||||||
|
"tags": ["inferred-tasks", "project-linking", "sync"],
|
||||||
|
"file": "shared/features/maintain-typescript-monorepos"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Automate Updating Dependencies",
|
"name": "Automate Updating Dependencies",
|
||||||
"description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.",
|
"description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.",
|
||||||
|
|||||||
284
docs/shared/features/maintain-typescript-monorepos.md
Normal file
284
docs/shared/features/maintain-typescript-monorepos.md
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
# Maintain TypeScript Monorepos
|
||||||
|
|
||||||
|
Keeping all the industry-standard tools involved in a large TypeScript monorepo correctly configured and working well together is a difficult task. And the more tools you add, the more opportunity there is for tools to conflict with each other in some way.
|
||||||
|
|
||||||
|
In addition to [generating default configuration files](/features/generate-code) and [automatically updating dependencies](/features/automate-updating-dependencies) to versions that we know work together, Nx makes managing all the tools in your monorepo easier in two ways:
|
||||||
|
|
||||||
|
- Rather than adding another tool that you have to configure, Nx configures itself to match the existing configuration of other tools.
|
||||||
|
- Nx also enhances certain tools to be more usable in a monorepo context.
|
||||||
|
|
||||||
|
## Auto-Configuration
|
||||||
|
|
||||||
|
Whenever possible, Nx will detect the existing configuration settings of other tools and update itself to match.
|
||||||
|
|
||||||
|
### Project Detection with Workspaces
|
||||||
|
|
||||||
|
If your repository is using package manager workspaces, Nx will use those settings to find all the [projects](/reference/project-configuration) in your repository. So you don't need to define a project for your package manager and separately identify the project for Nx. The `workspaces` configuration on the left allows Nx to detect the project graph on the right.
|
||||||
|
|
||||||
|
{% side-by-side align="top" %}
|
||||||
|
|
||||||
|
```json {% fileName="/package.json" %}
|
||||||
|
{
|
||||||
|
"workspaces": ["apps/*", "packages/*"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% graph height="200px" title="Project View" %}
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"composite": false,
|
||||||
|
"projects": [
|
||||||
|
{
|
||||||
|
"name": "product-state",
|
||||||
|
"type": "lib",
|
||||||
|
"data": {
|
||||||
|
"root": "packages/cart/product-state",
|
||||||
|
"tags": ["scope:cart", "type:state"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ui-buttons",
|
||||||
|
"type": "lib",
|
||||||
|
"data": {
|
||||||
|
"root": "packages/ui/buttons",
|
||||||
|
"tags": ["scope:shared", "type:ui"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cart",
|
||||||
|
"type": "app",
|
||||||
|
"data": {
|
||||||
|
"root": "apps/cart",
|
||||||
|
"tags": ["type:app", "scope:cart"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"product-state": [],
|
||||||
|
"ui-buttons": [],
|
||||||
|
"cart": [
|
||||||
|
{ "source": "cart", "target": "product-state", "type": "static" },
|
||||||
|
{ "source": "cart", "target": "ui-buttons", "type": "static" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"workspaceLayout": {
|
||||||
|
"appsDir": "apps",
|
||||||
|
"libsDir": "libs"
|
||||||
|
},
|
||||||
|
"affectedProjectIds": [],
|
||||||
|
"focus": null,
|
||||||
|
"groupByFolder": false,
|
||||||
|
"exclude": [],
|
||||||
|
"enableTooltips": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /graph %}
|
||||||
|
|
||||||
|
{% /side-by-side %}
|
||||||
|
|
||||||
|
### Inferred Tasks with Tooling Plugins
|
||||||
|
|
||||||
|
Nx provides [plugins](/concepts/nx-plugins) for tools that run tasks, like Vite, TypeScript, Playwright or Jest. These plugins can automatically [infer the Nx-specific task configuration](/concepts/inferred-tasks) based on the tooling configuration files that already exist.
|
||||||
|
|
||||||
|
In the example below, because the `/apps/cart/vite.config.ts` file exists, Nx knows that the `cart` project can run a `build` task using Vite. If you expand the `build` task on the right, you can also see that Nx configured the output directory for the [cache](/features/cache-task-results) to match the `build.outDir` provided in the Vite configuration file.
|
||||||
|
|
||||||
|
With inferred tasks, you can keep your tooling configuration file as the one source of truth for that tool's configuration, instead of adding an extra layer of configuration on top.
|
||||||
|
|
||||||
|
{% side-by-side align="top" %}
|
||||||
|
|
||||||
|
```ts {% fileName="/apps/cart/vite.config.ts" %}
|
||||||
|
/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/apps/cart',
|
||||||
|
plugins: [react()],
|
||||||
|
build: {
|
||||||
|
outDir: './dist',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
{% project-details %}
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"project": {
|
||||||
|
"name": "cart",
|
||||||
|
"type": "app",
|
||||||
|
"data": {
|
||||||
|
"root": "apps/cart",
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"options": {
|
||||||
|
"cwd": "apps/cart",
|
||||||
|
"command": "vite build"
|
||||||
|
},
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": ["^build"],
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": ["vite"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": ["{projectRoot}/dist"],
|
||||||
|
"executor": "nx:run-commands",
|
||||||
|
"configurations": {},
|
||||||
|
"metadata": {
|
||||||
|
"technologies": ["vite"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "cart",
|
||||||
|
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "apps/cart/src",
|
||||||
|
"projectType": "application",
|
||||||
|
"tags": [],
|
||||||
|
"implicitDependencies": [],
|
||||||
|
"metadata": {
|
||||||
|
"technologies": ["react"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceMap": {
|
||||||
|
"root": ["apps/cart/project.json", "nx/core/project-json"],
|
||||||
|
"targets": ["apps/cart/project.json", "nx/core/project-json"],
|
||||||
|
"targets.build": ["apps/cart/vite.config.ts", "@nx/vite/plugin"],
|
||||||
|
"targets.build.command": ["apps/cart/vite.config.ts", "@nx/vite/plugin"],
|
||||||
|
"targets.build.options": ["apps/cart/vite.config.ts", "@nx/vite/plugin"],
|
||||||
|
"targets.build.cache": ["apps/cart/vite.config.ts", "@nx/vite/plugin"],
|
||||||
|
"targets.build.dependsOn": ["apps/cart/vite.config.ts", "@nx/vite/plugin"],
|
||||||
|
"targets.build.inputs": ["apps/cart/vite.config.ts", "@nx/vite/plugin"],
|
||||||
|
"targets.build.outputs": ["apps/cart/vite.config.ts", "@nx/vite/plugin"],
|
||||||
|
"targets.build.options.cwd": [
|
||||||
|
"apps/cart/vite.config.ts",
|
||||||
|
"@nx/vite/plugin"
|
||||||
|
],
|
||||||
|
"name": ["apps/cart/project.json", "nx/core/project-json"],
|
||||||
|
"$schema": ["apps/cart/project.json", "nx/core/project-json"],
|
||||||
|
"sourceRoot": ["apps/cart/project.json", "nx/core/project-json"],
|
||||||
|
"projectType": ["apps/cart/project.json", "nx/core/project-json"],
|
||||||
|
"tags": ["apps/cart/project.json", "nx/core/project-json"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /project-details %}
|
||||||
|
|
||||||
|
{% /side-by-side %}
|
||||||
|
|
||||||
|
## Enhance Tools for Monorepos
|
||||||
|
|
||||||
|
Nx does not just reduce its own configuration burden, it also improves the functionality of your existing tools so that they work better in a monorepo context.
|
||||||
|
|
||||||
|
### Keep TypeScript Project References in Sync
|
||||||
|
|
||||||
|
TypeScript provides a feature called [Project References](https://www.typescriptlang.org/docs/handbook/project-references.html) that allows the TypeScript compiler to build and typecheck each project independently. When each project is typechecked, the TypeScript compiler will output an intermediate `*.tsbuildinfo` file that can be used by other projects instead of re-typechecking all dependencies. This feature can provide [significant performance improvements](/concepts/typescript-project-linking#typescript-project-references-performance-benefits), particularly in a large monorepo.
|
||||||
|
|
||||||
|
The main downside of this feature is that you have to manually define each project's references (dependencies) in the appropriate `tsconfig.*.json` file. This process is tedious to set up and very difficult to maintain as the repository changes over time. Nx can help by using a [sync generator](/concepts/sync-generators) to automatically update the references defined in the `tsconfig.json` files based on the project graph it already knows about.
|
||||||
|
|
||||||
|
{% side-by-side align="top" %}
|
||||||
|
|
||||||
|
{% graph height="200px" title="Project View" %}
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"composite": false,
|
||||||
|
"projects": [
|
||||||
|
{
|
||||||
|
"name": "product-state",
|
||||||
|
"type": "lib",
|
||||||
|
"data": {
|
||||||
|
"root": "packages/cart/product-state",
|
||||||
|
"tags": ["scope:cart", "type:state"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ui-buttons",
|
||||||
|
"type": "lib",
|
||||||
|
"data": {
|
||||||
|
"root": "packages/ui/buttons",
|
||||||
|
"tags": ["scope:shared", "type:ui"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cart",
|
||||||
|
"type": "app",
|
||||||
|
"data": {
|
||||||
|
"root": "apps/cart",
|
||||||
|
"tags": ["type:app", "scope:cart"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"product-state": [],
|
||||||
|
"ui-buttons": [],
|
||||||
|
"cart": [
|
||||||
|
{ "source": "cart", "target": "product-state", "type": "static" },
|
||||||
|
{ "source": "cart", "target": "ui-buttons", "type": "static" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"workspaceLayout": {
|
||||||
|
"appsDir": "apps",
|
||||||
|
"libsDir": "libs"
|
||||||
|
},
|
||||||
|
"affectedProjectIds": [],
|
||||||
|
"focus": null,
|
||||||
|
"groupByFolder": false,
|
||||||
|
"exclude": [],
|
||||||
|
"enableTooltips": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /graph %}
|
||||||
|
|
||||||
|
```jsonc {% fileName="apps/cart/tsconfig.json" %}
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"files": [], // intentionally empty
|
||||||
|
"references": [
|
||||||
|
// UPDATED BY NX SYNC
|
||||||
|
// All project dependencies
|
||||||
|
{
|
||||||
|
"path": "../../packages/product-state"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../../packages/ui/buttons"
|
||||||
|
},
|
||||||
|
// This project's other tsconfig.*.json files
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /side-by-side %}
|
||||||
|
|
||||||
|
Later, if someone adds another dependency to the `cart` app and then runs the `build` task, Nx will detect that the project references are out of sync and ask if the references should be updated.
|
||||||
|
|
||||||
|
```text {% command="nx build cart" path="~/myorg" %}
|
||||||
|
NX The workspace is out of sync
|
||||||
|
|
||||||
|
[@nx/js:typescript-sync]: Some TypeScript configuration files are missing project references to the projects they depend on or contain outdated project references.
|
||||||
|
|
||||||
|
This will result in an error in CI.
|
||||||
|
|
||||||
|
? Would you like to sync the identified changes to get your workspace up to date? …
|
||||||
|
❯ Yes, sync the changes and run the tasks
|
||||||
|
No, run the tasks without syncing the changes
|
||||||
|
```
|
||||||
@ -16,6 +16,7 @@
|
|||||||
- [Enhance Your LLM](/features/enhance-AI)
|
- [Enhance Your LLM](/features/enhance-AI)
|
||||||
- [Explore Your Workspace](/features/explore-graph)
|
- [Explore Your Workspace](/features/explore-graph)
|
||||||
- [Generate Code](/features/generate-code)
|
- [Generate Code](/features/generate-code)
|
||||||
|
- [Maintain TypeScript Monorepos](/features/maintain-ts-monorepos)
|
||||||
- [Automate Updating Dependencies](/features/automate-updating-dependencies)
|
- [Automate Updating Dependencies](/features/automate-updating-dependencies)
|
||||||
- [Enforce Module Boundaries](/features/enforce-module-boundaries)
|
- [Enforce Module Boundaries](/features/enforce-module-boundaries)
|
||||||
- [Manage Releases](/features/manage-releases)
|
- [Manage Releases](/features/manage-releases)
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export function Graph({
|
|||||||
if (!jsonFile && !parsedProps) {
|
if (!jsonFile && !parsedProps) {
|
||||||
if (!children || !children.hasOwnProperty('props')) {
|
if (!children || !children.hasOwnProperty('props')) {
|
||||||
return (
|
return (
|
||||||
<div className="no-prose my-6 block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
<div className="no-prose block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
||||||
<p className="mb-4">
|
<p className="mb-4">
|
||||||
No JSON provided for graph, use JSON code fence to embed data for
|
No JSON provided for graph, use JSON code fence to embed data for
|
||||||
the graph.
|
the graph.
|
||||||
@ -82,7 +82,7 @@ export function Graph({
|
|||||||
setParsedProps(JSON.parse(children?.props.children as any));
|
setParsedProps(JSON.parse(children?.props.children as any));
|
||||||
} catch {
|
} catch {
|
||||||
return (
|
return (
|
||||||
<div className="not-prose my-6 block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
<div className="not-prose block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
||||||
<p className="mb-4">Could not parse JSON for graph:</p>
|
<p className="mb-4">Could not parse JSON for graph:</p>
|
||||||
<pre className="p-4 text-sm">{children?.props.children as any}</pre>
|
<pre className="p-4 text-sm">{children?.props.children as any}</pre>
|
||||||
</div>
|
</div>
|
||||||
@ -94,7 +94,7 @@ export function Graph({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="my-6 w-full place-content-center overflow-hidden rounded-md ring-1 ring-slate-200 dark:ring-slate-700">
|
<div className="w-full place-content-center overflow-hidden rounded-md ring-1 ring-slate-200 dark:ring-slate-700">
|
||||||
<div className="relative flex justify-center border-b border-slate-200 bg-slate-100/50 p-2 font-bold dark:border-slate-700 dark:bg-slate-700/50">
|
<div className="relative flex justify-center border-b border-slate-200 bg-slate-100/50 p-2 font-bold dark:border-slate-700 dark:bg-slate-700/50">
|
||||||
{title}
|
{title}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,9 +1,21 @@
|
|||||||
|
import { cx } from '@nx/nx-dev/ui-primitives';
|
||||||
import { Children, ReactNode } from 'react';
|
import { Children, ReactNode } from 'react';
|
||||||
|
|
||||||
export function SideBySide({ children }: { children: ReactNode }) {
|
export function SideBySide({
|
||||||
|
align,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
align: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
const [first, ...rest] = Children.toArray(children);
|
const [first, ...rest] = Children.toArray(children);
|
||||||
return (
|
return (
|
||||||
<div className="not-prose grid items-center divide-x divide-solid divide-slate-50 md:grid-cols-2 dark:divide-slate-800">
|
<div
|
||||||
|
className={cx(
|
||||||
|
'not-prose grid divide-x divide-solid divide-slate-50 md:grid-cols-2 dark:divide-slate-800',
|
||||||
|
align === 'top' ? 'items-start' : 'items-center'
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div className="md:pr-6">{first}</div>
|
<div className="md:pr-6">{first}</div>
|
||||||
<div className="md:pl-6">{rest}</div>
|
<div className="md:pl-6">{rest}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,5 +2,9 @@ import { Schema } from '@markdoc/markdoc';
|
|||||||
|
|
||||||
export const sideBySide: Schema = {
|
export const sideBySide: Schema = {
|
||||||
render: 'SideBySide',
|
render: 'SideBySide',
|
||||||
attributes: {},
|
attributes: {
|
||||||
|
align: {
|
||||||
|
type: 'String',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user