docs(core): decisions section (#23038)

Create an "Organizational Decisions" section under Concepts for
recommendations and discussions about how to set up Nx that aren't firm
requirements.
This commit is contained in:
Isaac Mann 2024-05-10 15:42:46 -04:00 committed by GitHub
parent 88ac601798
commit 186a420a74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 675 additions and 670 deletions

View File

@ -18,6 +18,7 @@ In the last couple of months we have quadrupled the team and have done some amaz
- [Enterprise Support](#enterprise-support) - [Enterprise Support](#enterprise-support)
- [New, Simplified Plans and Pricing Model](#new-simplified-plans-and-pricing-model) - [New, Simplified Plans and Pricing Model](#new-simplified-plans-and-pricing-model)
- [Coming Next](#coming-next) - [Coming Next](#coming-next)
- [Learn more](#learn-more)
**Prefer a Video? Weve got you Covered!** **Prefer a Video? Weve got you Covered!**
@ -39,7 +40,7 @@ More UI-related updates and improvements are already underway.
![](/blog/images/2023-04-19/bodyimg3.webp) ![](/blog/images/2023-04-19/bodyimg3.webp)
At Nx, we are performance addicts! Especially when it comes to local development, every millisecond counts! In the latest update of the Nx CLI, we added the ability to **offload some of the remote cache management to the [Nx Daemon](/concepts/more-concepts/nx-daemon)**. As a result you no longer have to wait for the cache to upload. This saves valuable time, allowing the command to complete instantly and immediately providing you with the necessary link. At Nx, we are performance addicts! Especially when it comes to local development, every millisecond counts! In the latest update of the Nx CLI, we added the ability to **offload some of the remote cache management to the [Nx Daemon](/concepts/nx-daemon)**. As a result you no longer have to wait for the cache to upload. This saves valuable time, allowing the command to complete instantly and immediately providing you with the necessary link.
We also **prefetch cache results in the background** to have them ready when needed. We also **prefetch cache results in the background** to have them ready when needed.
Both optimizations can save seconds. Both optimizations can save seconds.

View File

@ -638,6 +638,30 @@
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{
"name": "Nx Daemon",
"path": "/concepts/nx-daemon",
"id": "nx-daemon",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Nx and Turborepo",
"path": "/concepts/turbo-and-nx",
"id": "turbo-and-nx",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Buildable and Publishable Libraries",
"path": "/concepts/buildable-and-publishable-libraries",
"id": "buildable-and-publishable-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{ {
"name": "Module Federation", "name": "Module Federation",
"path": "/concepts/module-federation", "path": "/concepts/module-federation",
@ -680,14 +704,22 @@
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "More Concepts", "name": "Organizational Decisions",
"path": "/concepts/more-concepts", "path": "/concepts/decisions",
"id": "more-concepts", "id": "decisions",
"isExternal": false, "isExternal": false,
"children": [ "children": [
{
"name": "Overview",
"path": "/concepts/decisions/overview",
"id": "overview",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{ {
"name": "Monorepos", "name": "Monorepos",
"path": "/concepts/more-concepts/why-monorepos", "path": "/concepts/decisions/why-monorepos",
"id": "why-monorepos", "id": "why-monorepos",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
@ -695,72 +727,40 @@
}, },
{ {
"name": "Dependency Management", "name": "Dependency Management",
"path": "/concepts/more-concepts/dependency-management", "path": "/concepts/decisions/dependency-management",
"id": "dependency-management", "id": "dependency-management",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Code Sharing", "name": "Code Ownership",
"path": "/concepts/more-concepts/code-sharing", "path": "/concepts/decisions/code-ownership",
"id": "code-sharing", "id": "code-ownership",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Nx Daemon", "name": "Project Size",
"path": "/concepts/more-concepts/nx-daemon", "path": "/concepts/decisions/project-size",
"id": "nx-daemon", "id": "project-size",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Nx and Turborepo", "name": "Project Dependency Rules",
"path": "/concepts/more-concepts/turbo-and-nx", "path": "/concepts/decisions/project-dependency-rules",
"id": "turbo-and-nx", "id": "project-dependency-rules",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Applications and Libraries", "name": "Folder Structure",
"path": "/concepts/more-concepts/applications-and-libraries", "path": "/concepts/decisions/folder-structure",
"id": "applications-and-libraries", "id": "folder-structure",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "When to Create a New Library",
"path": "/concepts/more-concepts/creating-libraries",
"id": "creating-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Library Types",
"path": "/concepts/more-concepts/library-types",
"id": "library-types",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Grouping Libraries",
"path": "/concepts/more-concepts/grouping-libraries",
"id": "grouping-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Buildable and Publishable Libraries",
"path": "/concepts/more-concepts/buildable-and-publishable-libraries",
"id": "buildable-and-publishable-libraries",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
@ -835,6 +835,30 @@
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{
"name": "Nx Daemon",
"path": "/concepts/nx-daemon",
"id": "nx-daemon",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Nx and Turborepo",
"path": "/concepts/turbo-and-nx",
"id": "turbo-and-nx",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Buildable and Publishable Libraries",
"path": "/concepts/buildable-and-publishable-libraries",
"id": "buildable-and-publishable-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{ {
"name": "Module Federation", "name": "Module Federation",
"path": "/concepts/module-federation", "path": "/concepts/module-federation",
@ -909,14 +933,22 @@
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "More Concepts", "name": "Organizational Decisions",
"path": "/concepts/more-concepts", "path": "/concepts/decisions",
"id": "more-concepts", "id": "decisions",
"isExternal": false, "isExternal": false,
"children": [ "children": [
{
"name": "Overview",
"path": "/concepts/decisions/overview",
"id": "overview",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{ {
"name": "Monorepos", "name": "Monorepos",
"path": "/concepts/more-concepts/why-monorepos", "path": "/concepts/decisions/why-monorepos",
"id": "why-monorepos", "id": "why-monorepos",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
@ -924,72 +956,40 @@
}, },
{ {
"name": "Dependency Management", "name": "Dependency Management",
"path": "/concepts/more-concepts/dependency-management", "path": "/concepts/decisions/dependency-management",
"id": "dependency-management", "id": "dependency-management",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Code Sharing", "name": "Code Ownership",
"path": "/concepts/more-concepts/code-sharing", "path": "/concepts/decisions/code-ownership",
"id": "code-sharing", "id": "code-ownership",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Nx Daemon", "name": "Project Size",
"path": "/concepts/more-concepts/nx-daemon", "path": "/concepts/decisions/project-size",
"id": "nx-daemon", "id": "project-size",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Nx and Turborepo", "name": "Project Dependency Rules",
"path": "/concepts/more-concepts/turbo-and-nx", "path": "/concepts/decisions/project-dependency-rules",
"id": "turbo-and-nx", "id": "project-dependency-rules",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Applications and Libraries", "name": "Folder Structure",
"path": "/concepts/more-concepts/applications-and-libraries", "path": "/concepts/decisions/folder-structure",
"id": "applications-and-libraries", "id": "folder-structure",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "When to Create a New Library",
"path": "/concepts/more-concepts/creating-libraries",
"id": "creating-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Library Types",
"path": "/concepts/more-concepts/library-types",
"id": "library-types",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Grouping Libraries",
"path": "/concepts/more-concepts/grouping-libraries",
"id": "grouping-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Buildable and Publishable Libraries",
"path": "/concepts/more-concepts/buildable-and-publishable-libraries",
"id": "buildable-and-publishable-libraries",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
@ -997,9 +997,17 @@
], ],
"disableCollapsible": false "disableCollapsible": false
}, },
{
"name": "Overview",
"path": "/concepts/decisions/overview",
"id": "overview",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{ {
"name": "Monorepos", "name": "Monorepos",
"path": "/concepts/more-concepts/why-monorepos", "path": "/concepts/decisions/why-monorepos",
"id": "why-monorepos", "id": "why-monorepos",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
@ -1007,72 +1015,40 @@
}, },
{ {
"name": "Dependency Management", "name": "Dependency Management",
"path": "/concepts/more-concepts/dependency-management", "path": "/concepts/decisions/dependency-management",
"id": "dependency-management", "id": "dependency-management",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Code Sharing", "name": "Code Ownership",
"path": "/concepts/more-concepts/code-sharing", "path": "/concepts/decisions/code-ownership",
"id": "code-sharing", "id": "code-ownership",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Nx Daemon", "name": "Project Size",
"path": "/concepts/more-concepts/nx-daemon", "path": "/concepts/decisions/project-size",
"id": "nx-daemon", "id": "project-size",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Nx and Turborepo", "name": "Project Dependency Rules",
"path": "/concepts/more-concepts/turbo-and-nx", "path": "/concepts/decisions/project-dependency-rules",
"id": "turbo-and-nx", "id": "project-dependency-rules",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{ {
"name": "Applications and Libraries", "name": "Folder Structure",
"path": "/concepts/more-concepts/applications-and-libraries", "path": "/concepts/decisions/folder-structure",
"id": "applications-and-libraries", "id": "folder-structure",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "When to Create a New Library",
"path": "/concepts/more-concepts/creating-libraries",
"id": "creating-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Library Types",
"path": "/concepts/more-concepts/library-types",
"id": "library-types",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Grouping Libraries",
"path": "/concepts/more-concepts/grouping-libraries",
"id": "grouping-libraries",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Buildable and Publishable Libraries",
"path": "/concepts/more-concepts/buildable-and-publishable-libraries",
"id": "buildable-and-publishable-libraries",
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false

View File

@ -787,7 +787,7 @@
"name": "Mental Model", "name": "Mental Model",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/mental-model", "file": "shared/concepts/mental-model",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/mental-model", "path": "/concepts/mental-model",
@ -853,7 +853,7 @@
"name": "Executors and Configurations", "name": "Executors and Configurations",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/recipes/running-tasks/executors-and-configurations", "file": "shared/concepts/executors-and-configurations",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/executors-and-configurations", "path": "/concepts/executors-and-configurations",
@ -870,6 +870,39 @@
"path": "/concepts/integrated-vs-package-based", "path": "/concepts/integrated-vs-package-based",
"tags": ["intro", "repository-types"] "tags": ["intro", "repository-types"]
}, },
{
"id": "nx-daemon",
"name": "Nx Daemon",
"description": "",
"mediaImage": "",
"file": "shared/concepts/daemon",
"itemList": [],
"isExternal": false,
"path": "/concepts/nx-daemon",
"tags": []
},
{
"id": "turbo-and-nx",
"name": "Nx and Turborepo",
"description": "",
"mediaImage": "./shared/concepts/nx-media-monorepo.jpg",
"file": "shared/concepts/turbo-and-nx",
"itemList": [],
"isExternal": false,
"path": "/concepts/turbo-and-nx",
"tags": []
},
{
"id": "buildable-and-publishable-libraries",
"name": "Buildable and Publishable Libraries",
"description": "",
"mediaImage": "",
"file": "shared/concepts/buildable-and-publishable-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/buildable-and-publishable-libraries",
"tags": []
},
{ {
"id": "module-federation", "id": "module-federation",
"name": "Module Federation", "name": "Module Federation",
@ -882,7 +915,7 @@
"name": "Module Federation and Nx", "name": "Module Federation and Nx",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/module-federation-and-nx", "file": "shared/concepts/module-federation/module-federation-and-nx",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/module-federation-and-nx", "path": "/concepts/module-federation/module-federation-and-nx",
@ -893,7 +926,7 @@
"name": "Faster Builds with Module Federation", "name": "Faster Builds with Module Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/faster-builds", "file": "shared/concepts/module-federation/faster-builds",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/faster-builds-with-module-federation", "path": "/concepts/module-federation/faster-builds-with-module-federation",
@ -904,7 +937,7 @@
"name": "Micro Frontend Architecture", "name": "Micro Frontend Architecture",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/micro-frontend-architecture", "file": "shared/concepts/module-federation/micro-frontend-architecture",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/micro-frontend-architecture", "path": "/concepts/module-federation/micro-frontend-architecture",
@ -915,7 +948,7 @@
"name": "Manage Library Versions with Module Federation", "name": "Manage Library Versions with Module Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/manage-library-versions-with-module-federation", "file": "shared/concepts/module-federation/manage-library-versions-with-module-federation",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/manage-library-versions-with-module-federation", "path": "/concepts/module-federation/manage-library-versions-with-module-federation",
@ -927,21 +960,32 @@
"tags": [] "tags": []
}, },
{ {
"id": "more-concepts", "id": "decisions",
"name": "More Concepts", "name": "Organizational Decisions",
"description": "Get deeper into how Nx works and its different aspects.", "description": "Topics that need to be considered when structuring your repository",
"mediaImage": "", "mediaImage": "",
"file": "", "file": "",
"itemList": [ "itemList": [
{
"id": "overview",
"name": "Overview",
"description": "",
"mediaImage": "",
"file": "shared/concepts/decisions/monorepo-polyrepo",
"itemList": [],
"isExternal": false,
"path": "/concepts/decisions/overview",
"tags": []
},
{ {
"id": "why-monorepos", "id": "why-monorepos",
"name": "Monorepos", "name": "Monorepos",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/why-monorepos", "file": "shared/concepts/decisions/monorepos",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/why-monorepos", "path": "/concepts/decisions/why-monorepos",
"tags": [] "tags": []
}, },
{ {
@ -949,103 +993,59 @@
"name": "Dependency Management", "name": "Dependency Management",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/concepts/dependency-management", "file": "shared/concepts/decisions/dependency-management",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/dependency-management", "path": "/concepts/decisions/dependency-management",
"tags": [] "tags": []
}, },
{ {
"id": "code-sharing", "id": "code-ownership",
"name": "Code Sharing", "name": "Code Ownership",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/concepts/code-sharing", "file": "shared/concepts/decisions/code-ownership",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/code-sharing", "path": "/concepts/decisions/code-ownership",
"tags": [] "tags": []
}, },
{ {
"id": "nx-daemon", "id": "project-size",
"name": "Nx Daemon", "name": "Project Size",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/daemon", "file": "shared/concepts/decisions/project-size",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/nx-daemon", "path": "/concepts/decisions/project-size",
"tags": []
},
{
"id": "turbo-and-nx",
"name": "Nx and Turborepo",
"description": "",
"mediaImage": "./shared/guides/nx-media-monorepo.jpg",
"file": "shared/guides/turbo-and-nx",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/turbo-and-nx",
"tags": []
},
{
"id": "applications-and-libraries",
"name": "Applications and Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/applications-and-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/applications-and-libraries",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
}, },
{ {
"id": "creating-libraries", "id": "project-dependency-rules",
"name": "When to Create a New Library", "name": "Project Dependency Rules",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/workspace/creating-libraries", "file": "shared/concepts/decisions/project-dependency-rules",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/creating-libraries", "path": "/concepts/decisions/project-dependency-rules",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
}, },
{ {
"id": "library-types", "id": "folder-structure",
"name": "Library Types", "name": "Folder Structure",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/workspace/library-types", "file": "shared/concepts/decisions/folder-structure",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/library-types", "path": "/concepts/decisions/folder-structure",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
},
{
"id": "grouping-libraries",
"name": "Grouping Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/grouping-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/grouping-libraries",
"tags": ["enforce-module-boundaries"]
},
{
"id": "buildable-and-publishable-libraries",
"name": "Buildable and Publishable Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/buildable-and-publishable-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/buildable-and-publishable-libraries",
"tags": []
} }
], ],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts", "path": "/concepts/decisions",
"tags": [] "tags": []
} }
], ],
@ -1058,7 +1058,7 @@
"name": "Mental Model", "name": "Mental Model",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/mental-model", "file": "shared/concepts/mental-model",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/mental-model", "path": "/concepts/mental-model",
@ -1124,7 +1124,7 @@
"name": "Executors and Configurations", "name": "Executors and Configurations",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/recipes/running-tasks/executors-and-configurations", "file": "shared/concepts/executors-and-configurations",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/executors-and-configurations", "path": "/concepts/executors-and-configurations",
@ -1141,6 +1141,39 @@
"path": "/concepts/integrated-vs-package-based", "path": "/concepts/integrated-vs-package-based",
"tags": ["intro", "repository-types"] "tags": ["intro", "repository-types"]
}, },
"/concepts/nx-daemon": {
"id": "nx-daemon",
"name": "Nx Daemon",
"description": "",
"mediaImage": "",
"file": "shared/concepts/daemon",
"itemList": [],
"isExternal": false,
"path": "/concepts/nx-daemon",
"tags": []
},
"/concepts/turbo-and-nx": {
"id": "turbo-and-nx",
"name": "Nx and Turborepo",
"description": "",
"mediaImage": "./shared/concepts/nx-media-monorepo.jpg",
"file": "shared/concepts/turbo-and-nx",
"itemList": [],
"isExternal": false,
"path": "/concepts/turbo-and-nx",
"tags": []
},
"/concepts/buildable-and-publishable-libraries": {
"id": "buildable-and-publishable-libraries",
"name": "Buildable and Publishable Libraries",
"description": "",
"mediaImage": "",
"file": "shared/concepts/buildable-and-publishable-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/buildable-and-publishable-libraries",
"tags": []
},
"/concepts/module-federation": { "/concepts/module-federation": {
"id": "module-federation", "id": "module-federation",
"name": "Module Federation", "name": "Module Federation",
@ -1153,7 +1186,7 @@
"name": "Module Federation and Nx", "name": "Module Federation and Nx",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/module-federation-and-nx", "file": "shared/concepts/module-federation/module-federation-and-nx",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/module-federation-and-nx", "path": "/concepts/module-federation/module-federation-and-nx",
@ -1164,7 +1197,7 @@
"name": "Faster Builds with Module Federation", "name": "Faster Builds with Module Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/faster-builds", "file": "shared/concepts/module-federation/faster-builds",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/faster-builds-with-module-federation", "path": "/concepts/module-federation/faster-builds-with-module-federation",
@ -1175,7 +1208,7 @@
"name": "Micro Frontend Architecture", "name": "Micro Frontend Architecture",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/micro-frontend-architecture", "file": "shared/concepts/module-federation/micro-frontend-architecture",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/micro-frontend-architecture", "path": "/concepts/module-federation/micro-frontend-architecture",
@ -1186,7 +1219,7 @@
"name": "Manage Library Versions with Module Federation", "name": "Manage Library Versions with Module Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/manage-library-versions-with-module-federation", "file": "shared/concepts/module-federation/manage-library-versions-with-module-federation",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/manage-library-versions-with-module-federation", "path": "/concepts/module-federation/manage-library-versions-with-module-federation",
@ -1202,7 +1235,7 @@
"name": "Module Federation and Nx", "name": "Module Federation and Nx",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/module-federation-and-nx", "file": "shared/concepts/module-federation/module-federation-and-nx",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/module-federation-and-nx", "path": "/concepts/module-federation/module-federation-and-nx",
@ -1213,7 +1246,7 @@
"name": "Faster Builds with Module Federation", "name": "Faster Builds with Module Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/faster-builds", "file": "shared/concepts/module-federation/faster-builds",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/faster-builds-with-module-federation", "path": "/concepts/module-federation/faster-builds-with-module-federation",
@ -1224,7 +1257,7 @@
"name": "Micro Frontend Architecture", "name": "Micro Frontend Architecture",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/micro-frontend-architecture", "file": "shared/concepts/module-federation/micro-frontend-architecture",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/micro-frontend-architecture", "path": "/concepts/module-federation/micro-frontend-architecture",
@ -1235,28 +1268,39 @@
"name": "Manage Library Versions with Module Federation", "name": "Manage Library Versions with Module Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/manage-library-versions-with-module-federation", "file": "shared/concepts/module-federation/manage-library-versions-with-module-federation",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/module-federation/manage-library-versions-with-module-federation", "path": "/concepts/module-federation/manage-library-versions-with-module-federation",
"tags": [] "tags": []
}, },
"/concepts/more-concepts": { "/concepts/decisions": {
"id": "more-concepts", "id": "decisions",
"name": "More Concepts", "name": "Organizational Decisions",
"description": "Get deeper into how Nx works and its different aspects.", "description": "Topics that need to be considered when structuring your repository",
"mediaImage": "", "mediaImage": "",
"file": "", "file": "",
"itemList": [ "itemList": [
{
"id": "overview",
"name": "Overview",
"description": "",
"mediaImage": "",
"file": "shared/concepts/decisions/monorepo-polyrepo",
"itemList": [],
"isExternal": false,
"path": "/concepts/decisions/overview",
"tags": []
},
{ {
"id": "why-monorepos", "id": "why-monorepos",
"name": "Monorepos", "name": "Monorepos",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/why-monorepos", "file": "shared/concepts/decisions/monorepos",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/why-monorepos", "path": "/concepts/decisions/why-monorepos",
"tags": [] "tags": []
}, },
{ {
@ -1264,215 +1308,138 @@
"name": "Dependency Management", "name": "Dependency Management",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/concepts/dependency-management", "file": "shared/concepts/decisions/dependency-management",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/dependency-management", "path": "/concepts/decisions/dependency-management",
"tags": [] "tags": []
}, },
{ {
"id": "code-sharing", "id": "code-ownership",
"name": "Code Sharing", "name": "Code Ownership",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/concepts/code-sharing", "file": "shared/concepts/decisions/code-ownership",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/code-sharing", "path": "/concepts/decisions/code-ownership",
"tags": [] "tags": []
}, },
{ {
"id": "nx-daemon", "id": "project-size",
"name": "Nx Daemon", "name": "Project Size",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/daemon", "file": "shared/concepts/decisions/project-size",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/nx-daemon", "path": "/concepts/decisions/project-size",
"tags": []
},
{
"id": "turbo-and-nx",
"name": "Nx and Turborepo",
"description": "",
"mediaImage": "./shared/guides/nx-media-monorepo.jpg",
"file": "shared/guides/turbo-and-nx",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/turbo-and-nx",
"tags": []
},
{
"id": "applications-and-libraries",
"name": "Applications and Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/applications-and-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/applications-and-libraries",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
}, },
{ {
"id": "creating-libraries", "id": "project-dependency-rules",
"name": "When to Create a New Library", "name": "Project Dependency Rules",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/workspace/creating-libraries", "file": "shared/concepts/decisions/project-dependency-rules",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/creating-libraries", "path": "/concepts/decisions/project-dependency-rules",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
}, },
{ {
"id": "library-types", "id": "folder-structure",
"name": "Library Types", "name": "Folder Structure",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/workspace/library-types", "file": "shared/concepts/decisions/folder-structure",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/library-types", "path": "/concepts/decisions/folder-structure",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
},
{
"id": "grouping-libraries",
"name": "Grouping Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/grouping-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/grouping-libraries",
"tags": ["enforce-module-boundaries"]
},
{
"id": "buildable-and-publishable-libraries",
"name": "Buildable and Publishable Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/buildable-and-publishable-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/buildable-and-publishable-libraries",
"tags": []
} }
], ],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts", "path": "/concepts/decisions",
"tags": [] "tags": []
}, },
"/concepts/more-concepts/why-monorepos": { "/concepts/decisions/overview": {
"id": "overview",
"name": "Overview",
"description": "",
"mediaImage": "",
"file": "shared/concepts/decisions/monorepo-polyrepo",
"itemList": [],
"isExternal": false,
"path": "/concepts/decisions/overview",
"tags": []
},
"/concepts/decisions/why-monorepos": {
"id": "why-monorepos", "id": "why-monorepos",
"name": "Monorepos", "name": "Monorepos",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/why-monorepos", "file": "shared/concepts/decisions/monorepos",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/why-monorepos", "path": "/concepts/decisions/why-monorepos",
"tags": [] "tags": []
}, },
"/concepts/more-concepts/dependency-management": { "/concepts/decisions/dependency-management": {
"id": "dependency-management", "id": "dependency-management",
"name": "Dependency Management", "name": "Dependency Management",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/concepts/dependency-management", "file": "shared/concepts/decisions/dependency-management",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/dependency-management", "path": "/concepts/decisions/dependency-management",
"tags": [] "tags": []
}, },
"/concepts/more-concepts/code-sharing": { "/concepts/decisions/code-ownership": {
"id": "code-sharing", "id": "code-ownership",
"name": "Code Sharing", "name": "Code Ownership",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/concepts/code-sharing", "file": "shared/concepts/decisions/code-ownership",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/code-sharing", "path": "/concepts/decisions/code-ownership",
"tags": [] "tags": []
}, },
"/concepts/more-concepts/nx-daemon": { "/concepts/decisions/project-size": {
"id": "nx-daemon", "id": "project-size",
"name": "Nx Daemon", "name": "Project Size",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/daemon", "file": "shared/concepts/decisions/project-size",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/nx-daemon", "path": "/concepts/decisions/project-size",
"tags": []
},
"/concepts/more-concepts/turbo-and-nx": {
"id": "turbo-and-nx",
"name": "Nx and Turborepo",
"description": "",
"mediaImage": "./shared/guides/nx-media-monorepo.jpg",
"file": "shared/guides/turbo-and-nx",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/turbo-and-nx",
"tags": []
},
"/concepts/more-concepts/applications-and-libraries": {
"id": "applications-and-libraries",
"name": "Applications and Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/applications-and-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/applications-and-libraries",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
}, },
"/concepts/more-concepts/creating-libraries": { "/concepts/decisions/project-dependency-rules": {
"id": "creating-libraries", "id": "project-dependency-rules",
"name": "When to Create a New Library", "name": "Project Dependency Rules",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/workspace/creating-libraries", "file": "shared/concepts/decisions/project-dependency-rules",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/creating-libraries", "path": "/concepts/decisions/project-dependency-rules",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
}, },
"/concepts/more-concepts/library-types": { "/concepts/decisions/folder-structure": {
"id": "library-types", "id": "folder-structure",
"name": "Library Types", "name": "Folder Structure",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/workspace/library-types", "file": "shared/concepts/decisions/folder-structure",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/concepts/more-concepts/library-types", "path": "/concepts/decisions/folder-structure",
"tags": ["enforce-module-boundaries"] "tags": ["enforce-module-boundaries"]
}, },
"/concepts/more-concepts/grouping-libraries": {
"id": "grouping-libraries",
"name": "Grouping Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/grouping-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/grouping-libraries",
"tags": ["enforce-module-boundaries"]
},
"/concepts/more-concepts/buildable-and-publishable-libraries": {
"id": "buildable-and-publishable-libraries",
"name": "Buildable and Publishable Libraries",
"description": "",
"mediaImage": "",
"file": "shared/workspace/buildable-and-publishable-libraries",
"itemList": [],
"isExternal": false,
"path": "/concepts/more-concepts/buildable-and-publishable-libraries",
"tags": []
},
"/recipes": { "/recipes": {
"id": "recipes", "id": "recipes",
"name": "Recipes", "name": "Recipes",
@ -1871,7 +1838,7 @@
"name": "Advanced Micro Frontends with Angular using Dynamic Federation", "name": "Advanced Micro Frontends with Angular using Dynamic Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/dynamic-mfe-angular", "file": "shared/recipes/module-federation/dynamic-mfe-angular",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/recipes/angular/dynamic-module-federation-with-angular", "path": "/recipes/angular/dynamic-module-federation-with-angular",
@ -3435,7 +3402,7 @@
"name": "Advanced Micro Frontends with Angular using Dynamic Federation", "name": "Advanced Micro Frontends with Angular using Dynamic Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/dynamic-mfe-angular", "file": "shared/recipes/module-federation/dynamic-mfe-angular",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/recipes/angular/dynamic-module-federation-with-angular", "path": "/recipes/angular/dynamic-module-federation-with-angular",
@ -3551,7 +3518,7 @@
"name": "Advanced Micro Frontends with Angular using Dynamic Federation", "name": "Advanced Micro Frontends with Angular using Dynamic Federation",
"description": "", "description": "",
"mediaImage": "", "mediaImage": "",
"file": "shared/guides/module-federation/dynamic-mfe-angular", "file": "shared/recipes/module-federation/dynamic-mfe-angular",
"itemList": [], "itemList": [],
"isExternal": false, "isExternal": false,
"path": "/recipes/angular/dynamic-module-federation-with-angular", "path": "/recipes/angular/dynamic-module-federation-with-angular",

View File

@ -60,7 +60,7 @@
}, },
{ {
"description": "", "description": "",
"file": "shared/recipes/running-tasks/executors-and-configurations", "file": "shared/concepts/executors-and-configurations",
"id": "executors-and-configurations", "id": "executors-and-configurations",
"name": "Executors and Configurations", "name": "Executors and Configurations",
"path": "/concepts/executors-and-configurations" "path": "/concepts/executors-and-configurations"
@ -392,31 +392,24 @@
}, },
{ {
"description": "", "description": "",
"file": "shared/workspace/applications-and-libraries", "file": "shared/concepts/decisions/project-size",
"id": "applications-and-libraries", "id": "project-size",
"name": "Applications and Libraries", "name": "Project Size",
"path": "/concepts/more-concepts/applications-and-libraries" "path": "/concepts/decisions/project-size"
}, },
{ {
"description": "", "description": "",
"file": "shared/workspace/creating-libraries", "file": "shared/concepts/decisions/project-dependency-rules",
"id": "creating-libraries", "id": "project-dependency-rules",
"name": "When to Create a New Library", "name": "Project Dependency Rules",
"path": "/concepts/more-concepts/creating-libraries" "path": "/concepts/decisions/project-dependency-rules"
}, },
{ {
"description": "", "description": "",
"file": "shared/workspace/library-types", "file": "shared/concepts/decisions/folder-structure",
"id": "library-types", "id": "folder-structure",
"name": "Library Types", "name": "Folder Structure",
"path": "/concepts/more-concepts/library-types" "path": "/concepts/decisions/folder-structure"
},
{
"description": "",
"file": "shared/workspace/grouping-libraries",
"id": "grouping-libraries",
"name": "Grouping Libraries",
"path": "/concepts/more-concepts/grouping-libraries"
}, },
{ {
"description": "", "description": "",
@ -550,7 +543,7 @@
"intro": [ "intro": [
{ {
"description": "", "description": "",
"file": "shared/mental-model", "file": "shared/concepts/mental-model",
"id": "mental-model", "id": "mental-model",
"name": "Mental Model", "name": "Mental Model",
"path": "/concepts/mental-model" "path": "/concepts/mental-model"
@ -566,7 +559,7 @@
"inferred-tasks": [ "inferred-tasks": [
{ {
"description": "", "description": "",
"file": "shared/mental-model", "file": "shared/concepts/mental-model",
"id": "mental-model", "id": "mental-model",
"name": "Mental Model", "name": "Mental Model",
"path": "/concepts/mental-model" "path": "/concepts/mental-model"
@ -670,14 +663,14 @@
"module-federation": [ "module-federation": [
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/module-federation-and-nx", "file": "shared/concepts/module-federation/module-federation-and-nx",
"id": "module-federation-and-nx", "id": "module-federation-and-nx",
"name": "Module Federation and Nx", "name": "Module Federation and Nx",
"path": "/concepts/module-federation/module-federation-and-nx" "path": "/concepts/module-federation/module-federation-and-nx"
}, },
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/faster-builds", "file": "shared/concepts/module-federation/faster-builds",
"id": "faster-builds-with-module-federation", "id": "faster-builds-with-module-federation",
"name": "Faster Builds with Module Federation", "name": "Faster Builds with Module Federation",
"path": "/concepts/module-federation/faster-builds-with-module-federation" "path": "/concepts/module-federation/faster-builds-with-module-federation"
@ -698,7 +691,7 @@
}, },
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/dynamic-mfe-angular", "file": "shared/recipes/module-federation/dynamic-mfe-angular",
"id": "dynamic-module-federation-with-angular", "id": "dynamic-module-federation-with-angular",
"name": "Advanced Micro Frontends with Angular using Dynamic Federation", "name": "Advanced Micro Frontends with Angular using Dynamic Federation",
"path": "/recipes/angular/dynamic-module-federation-with-angular" "path": "/recipes/angular/dynamic-module-federation-with-angular"
@ -707,14 +700,14 @@
"angular": [ "angular": [
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/module-federation-and-nx", "file": "shared/concepts/module-federation/module-federation-and-nx",
"id": "module-federation-and-nx", "id": "module-federation-and-nx",
"name": "Module Federation and Nx", "name": "Module Federation and Nx",
"path": "/concepts/module-federation/module-federation-and-nx" "path": "/concepts/module-federation/module-federation-and-nx"
}, },
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/faster-builds", "file": "shared/concepts/module-federation/faster-builds",
"id": "faster-builds-with-module-federation", "id": "faster-builds-with-module-federation",
"name": "Faster Builds with Module Federation", "name": "Faster Builds with Module Federation",
"path": "/concepts/module-federation/faster-builds-with-module-federation" "path": "/concepts/module-federation/faster-builds-with-module-federation"
@ -728,7 +721,7 @@
}, },
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/dynamic-mfe-angular", "file": "shared/recipes/module-federation/dynamic-mfe-angular",
"id": "dynamic-module-federation-with-angular", "id": "dynamic-module-federation-with-angular",
"name": "Advanced Micro Frontends with Angular using Dynamic Federation", "name": "Advanced Micro Frontends with Angular using Dynamic Federation",
"path": "/recipes/angular/dynamic-module-federation-with-angular" "path": "/recipes/angular/dynamic-module-federation-with-angular"
@ -737,14 +730,14 @@
"react": [ "react": [
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/module-federation-and-nx", "file": "shared/concepts/module-federation/module-federation-and-nx",
"id": "module-federation-and-nx", "id": "module-federation-and-nx",
"name": "Module Federation and Nx", "name": "Module Federation and Nx",
"path": "/concepts/module-federation/module-federation-and-nx" "path": "/concepts/module-federation/module-federation-and-nx"
}, },
{ {
"description": "", "description": "",
"file": "shared/guides/module-federation/faster-builds", "file": "shared/concepts/module-federation/faster-builds",
"id": "faster-builds-with-module-federation", "id": "faster-builds-with-module-federation",
"name": "Faster Builds with Module Federation", "name": "Faster Builds with Module Federation",
"path": "/concepts/module-federation/faster-builds-with-module-federation" "path": "/concepts/module-federation/faster-builds-with-module-federation"

View File

@ -111,9 +111,9 @@ nx lint libName
Read more about: Read more about:
- [Creating Libraries](/concepts/more-concepts/creating-libraries) - [Creating Libraries](/concepts/decisions/project-size)
- [Library Types](/concepts/more-concepts/library-types) - [Library Types](/concepts/decisions/project-dependency-rules)
- [Buildable and Publishable Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) - [Buildable and Publishable Libraries](/concepts/buildable-and-publishable-libraries)
### Fallback to `@schematics/angular` ### Fallback to `@schematics/angular`

View File

@ -88,7 +88,7 @@ To make the library `publishable`, use the following command:
nx g @nx/nest:lib my-nest-lib --publishable --importPath=@my-workspace/my-nest-lib nx g @nx/nest:lib my-nest-lib --publishable --importPath=@my-workspace/my-nest-lib
``` ```
> Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). > Read more about [building and publishing libraries here](/concepts/buildable-and-publishable-libraries).
### Nest Generators ### Nest Generators

View File

@ -108,9 +108,6 @@ Nx allows you to create libraries with just one command. Some reasons you might
- Publish a package to be used outside the monorepo - Publish a package to be used outside the monorepo
- Better visualize the architecture using `nx graph` - Better visualize the architecture using `nx graph`
For more information on Nx libraries, see our documentation on [Creating Libraries](/concepts/more-concepts/creating-libraries)
and [Library Types](/concepts/more-concepts/library-types).
To generate a new library run: To generate a new library run:
```shell ```shell

View File

@ -70,7 +70,7 @@ nx g @nx/react:lib my-new-lib \
--importPath=@myorg/my-new-lib --importPath=@myorg/my-new-lib
``` ```
Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). Read more about [building and publishing libraries here](/concepts/buildable-and-publishable-libraries).
### Creating Components ### Creating Components

View File

@ -87,7 +87,7 @@ In the following section, we are going to see how to set up Storybook in these c
### Philosophy ### Philosophy
Setting up Storybook on Nx reflects - and takes advantage of - the [mental model](/concepts/mental-model) of Nx, and especially the architecture of [Applications and Libraries](/concepts/more-concepts/applications-and-libraries). What that means, in essence, is that you still maintain the individual Storybook instances (per project) which you use for testing and local development, but you also keep one extra “container” for publishing, that serves as a single entry point. Lets see this in more detail. Setting up Storybook on Nx reflects - and takes advantage of - the [mental model](/concepts/mental-model) of Nx. What that means, in essence, is that you still maintain the individual Storybook instances (per project) which you use for testing and local development, but you also keep one extra “container” for publishing, that serves as a single entry point. Lets see this in more detail.
#### Local development and testing #### Local development and testing
@ -119,7 +119,7 @@ Since each Storybook, in this case, is attached to a project, so is the serving
#### Publishing #### Publishing
When you are publishing your Storybook, you can follow the same principles described in the [Applications and Libraries Mental Model](/concepts/more-concepts/applications-and-libraries#mental-model) documentation page. The general idea is to have one central Storybook container, into which you are going to gather your stories from multiple libraries. When you are publishing your Storybook, you can follow the same principles described in the [Applications and Libraries Mental Model](/concepts/decisions/project-size#mental-model) documentation page. The general idea is to have one central Storybook container, into which you are going to gather your stories from multiple libraries.
You can think of the central Storybook container as a grouping of similar-concept or same-scope UI parts of your workspace. In the same way you are scoping libraries, you can group your stories as well. You can think of the central Storybook container as a grouping of similar-concept or same-scope UI parts of your workspace. In the same way you are scoping libraries, you can group your stories as well.
@ -129,7 +129,7 @@ Then, according to your use-case, you can have one central Storybook for your wh
In order to achieve some things mentioned above, you may use [Storybook Composition](/recipes/storybook/storybook-composition-setup). However, in this case, you would still need to build each projects Storybook individually, and also deploy it individually. So in the cases where you have multiple projects, Storybook Composition would not be very efficient. In order to achieve some things mentioned above, you may use [Storybook Composition](/recipes/storybook/storybook-composition-setup). However, in this case, you would still need to build each projects Storybook individually, and also deploy it individually. So in the cases where you have multiple projects, Storybook Composition would not be very efficient.
{% /callout %} {% /callout %}
Before moving on to the examples section, it could be useful to read the [Library Types](/concepts/more-concepts/library-types) documentation page and the [Grouping libraries](/concepts/more-concepts/grouping-libraries) documentation page. These could help you decide which way fits your use case better. Before moving on to the examples section, it could be useful to read the [Library Types](/concepts/decisions/project-dependency-rules) documentation page and the [Grouping libraries](/concepts/decisions/folder-structure) documentation page. These could help you decide which way fits your use case better.
## Examples / Use cases ## Examples / Use cases

View File

@ -201,7 +201,7 @@
"name": "Mental Model", "name": "Mental Model",
"tags": ["intro", "inferred-tasks"], "tags": ["intro", "inferred-tasks"],
"id": "mental-model", "id": "mental-model",
"file": "shared/mental-model" "file": "shared/concepts/mental-model"
}, },
{ {
"name": "How Caching Works", "name": "How Caching Works",
@ -241,7 +241,7 @@
"name": "Executors and Configurations", "name": "Executors and Configurations",
"id": "executors-and-configurations", "id": "executors-and-configurations",
"tags": ["run-tasks"], "tags": ["run-tasks"],
"file": "shared/recipes/running-tasks/executors-and-configurations" "file": "shared/concepts/executors-and-configurations"
}, },
{ {
"name": "Integrated Repos vs. Package-Based Repos vs. Standalone Apps", "name": "Integrated Repos vs. Package-Based Repos vs. Standalone Apps",
@ -249,6 +249,22 @@
"id": "integrated-vs-package-based", "id": "integrated-vs-package-based",
"file": "shared/concepts/integrated-vs-package-based" "file": "shared/concepts/integrated-vs-package-based"
}, },
{
"name": "Nx Daemon",
"id": "nx-daemon",
"file": "shared/concepts/daemon"
},
{
"name": "Nx and Turborepo",
"id": "turbo-and-nx",
"mediaImage": "./shared/concepts/nx-media-monorepo.jpg",
"file": "shared/concepts/turbo-and-nx"
},
{
"name": "Buildable and Publishable Libraries",
"id": "buildable-and-publishable-libraries",
"file": "shared/concepts/buildable-and-publishable-libraries"
},
{ {
"name": "Module Federation", "name": "Module Federation",
"id": "module-federation", "id": "module-federation",
@ -258,85 +274,68 @@
"name": "Module Federation and Nx", "name": "Module Federation and Nx",
"id": "module-federation-and-nx", "id": "module-federation-and-nx",
"tags": ["module-federation", "angular", "react"], "tags": ["module-federation", "angular", "react"],
"file": "shared/guides/module-federation/module-federation-and-nx" "file": "shared/concepts/module-federation/module-federation-and-nx"
}, },
{ {
"name": "Faster Builds with Module Federation", "name": "Faster Builds with Module Federation",
"id": "faster-builds-with-module-federation", "id": "faster-builds-with-module-federation",
"tags": ["module-federation", "angular", "react"], "tags": ["module-federation", "angular", "react"],
"file": "shared/guides/module-federation/faster-builds" "file": "shared/concepts/module-federation/faster-builds"
}, },
{ {
"name": "Micro Frontend Architecture", "name": "Micro Frontend Architecture",
"id": "micro-frontend-architecture", "id": "micro-frontend-architecture",
"file": "shared/guides/module-federation/micro-frontend-architecture" "file": "shared/concepts/module-federation/micro-frontend-architecture"
}, },
{ {
"name": "Manage Library Versions with Module Federation", "name": "Manage Library Versions with Module Federation",
"id": "manage-library-versions-with-module-federation", "id": "manage-library-versions-with-module-federation",
"file": "shared/guides/module-federation/manage-library-versions-with-module-federation" "file": "shared/concepts/module-federation/manage-library-versions-with-module-federation"
} }
] ]
}, },
{ {
"name": "More Concepts", "name": "Organizational Decisions",
"id": "more-concepts", "id": "decisions",
"description": "Get deeper into how Nx works and its different aspects.", "description": "Topics that need to be considered when structuring your repository",
"itemList": [ "itemList": [
{
"name": "Overview",
"id": "overview",
"file": "shared/concepts/decisions/monorepo-polyrepo"
},
{ {
"name": "Monorepos", "name": "Monorepos",
"id": "why-monorepos", "id": "why-monorepos",
"file": "shared/guides/why-monorepos" "file": "shared/concepts/decisions/monorepos"
}, },
{ {
"name": "Dependency Management", "name": "Dependency Management",
"id": "dependency-management", "id": "dependency-management",
"file": "shared/concepts/dependency-management" "file": "shared/concepts/decisions/dependency-management"
}, },
{ {
"name": "Code Sharing", "name": "Code Ownership",
"id": "code-sharing", "id": "code-ownership",
"file": "shared/concepts/code-sharing" "file": "shared/concepts/decisions/code-ownership"
}, },
{ {
"name": "Nx Daemon", "name": "Project Size",
"id": "nx-daemon", "id": "project-size",
"file": "shared/daemon"
},
{
"name": "Nx and Turborepo",
"id": "turbo-and-nx",
"mediaImage": "./shared/guides/nx-media-monorepo.jpg",
"file": "shared/guides/turbo-and-nx"
},
{
"name": "Applications and Libraries",
"id": "applications-and-libraries",
"tags": ["enforce-module-boundaries"], "tags": ["enforce-module-boundaries"],
"file": "shared/workspace/applications-and-libraries" "file": "shared/concepts/decisions/project-size"
}, },
{ {
"name": "When to Create a New Library", "name": "Project Dependency Rules",
"id": "creating-libraries", "id": "project-dependency-rules",
"tags": ["enforce-module-boundaries"], "tags": ["enforce-module-boundaries"],
"file": "shared/workspace/creating-libraries" "file": "shared/concepts/decisions/project-dependency-rules"
}, },
{ {
"name": "Library Types", "name": "Folder Structure",
"id": "library-types", "id": "folder-structure",
"tags": ["enforce-module-boundaries"], "tags": ["enforce-module-boundaries"],
"file": "shared/workspace/library-types" "file": "shared/concepts/decisions/folder-structure"
},
{
"name": "Grouping Libraries",
"id": "grouping-libraries",
"tags": ["enforce-module-boundaries"],
"file": "shared/workspace/grouping-libraries"
},
{
"name": "Buildable and Publishable Libraries",
"id": "buildable-and-publishable-libraries",
"file": "shared/workspace/buildable-and-publishable-libraries"
} }
] ]
} }
@ -550,7 +549,7 @@
"name": "Advanced Micro Frontends with Angular using Dynamic Federation", "name": "Advanced Micro Frontends with Angular using Dynamic Federation",
"id": "dynamic-module-federation-with-angular", "id": "dynamic-module-federation-with-angular",
"tags": ["module-federation", "angular"], "tags": ["module-federation", "angular"],
"file": "shared/guides/module-federation/dynamic-mfe-angular" "file": "shared/recipes/module-federation/dynamic-mfe-angular"
}, },
{ {
"name": "Setup incremental builds for Angular applications", "name": "Setup incremental builds for Angular applications",

View File

@ -1,4 +1,4 @@
# Code Sharing # Code Ownership
One of the most obvious benefits of having a monorepo is that you can easily share code across projects. This enables you to apply the Don't Repeat Yourself principle across the whole codebase. Code sharing could mean using a function or a component in multiple projects. Or code sharing could mean using a typescript interface to define the network API interface for both the front end and back end applications. One of the most obvious benefits of having a monorepo is that you can easily share code across projects. This enables you to apply the Don't Repeat Yourself principle across the whole codebase. Code sharing could mean using a function or a component in multiple projects. Or code sharing could mean using a typescript interface to define the network API interface for both the front end and back end applications.
@ -19,3 +19,21 @@ Another team can use a piece of code that is intended to be internal to your pro
### Projects Depending on the Wrong Libraries ### Projects Depending on the Wrong Libraries
Libraries with presentational components can accidentally use code from a library that holds a data store. Projects with Angular code can accidentally use code from a React project. Projects from team A could accidentally use code in projects that are intended to be only for team B. These kinds of rules will vary based on the organisation, but they can all be enforced automatically using tags and the `enforce-module-boundaries` lint rule. Libraries with presentational components can accidentally use code from a library that holds a data store. Projects with Angular code can accidentally use code from a React project. Projects from team A could accidentally use code in projects that are intended to be only for team B. These kinds of rules will vary based on the organisation, but they can all be enforced automatically using tags and the `enforce-module-boundaries` lint rule.
## Defining Code Ownership
As more teams are contributing to the same repository, it becomes crucial to establish clear code ownership.
Since Nx allows us to place projects in any directory structure, those directories can become code-ownership boundaries. That's
why the structure of an Nx workspace often reflects the structure of an organization. GitHub users can use
the `CODEOWNERS` file for that.
```plaintext
/libs/happynrwlapp julie-happynrwlapp-lead
/apps/happynrwlapp julie-happynrwlapp-lead
/libs/shared/ui hank-the-ui-guy
/libs/shared/utils-testing julie,hank
```
If you want to know more about code ownership on GitHub, please
check [the documentation on the `CODEOWNERS` file](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners).

View File

@ -0,0 +1,67 @@
# Folder Structure
Nx can work with any folder structure you choose, but it is good to have a plan in place for the folder structure of your monorepo.
Projects are often grouped by _scope_. A project's scope is either the application to which it belongs or (for larger applications) a section within that application.
## Move Generator
Don't be too anxious about choosing the exact right folder structure from the beginning. Projects can be moved or renamed using the [`@nx/workspace:move` generator](/nx-api/workspace/generators/move).
For instance, if a project under the `booking` folder is now being shared by multiple apps, you can move it to the shared folder like this:
```shell
nx g move --project booking-some-project shared/some-project
```
## Remove Generator
Similarly, if you no longer need a project, you can remove it with the [`@nx/workspace:remove` generator](/nx-api/workspace/generators/remove).
```shell
nx g remove booking-some-project
```
## Example Workspace
Let's use Nrwl Airlines as an example organization. This organization has two apps, `booking` and `check-in`. In the Nx workspace, projects related to `booking` are grouped under a `libs/booking` folder, projects related to `check-in` are grouped under a `libs/check-in` folder and projects used in both applications are placed in `libs/shared`. You can also have nested grouping folders, (i.e. `libs/shared/seatmap`).
The purpose of these folders is to help with organizing by scope. We recommend grouping projects together which are (usually) updated together. It helps minimize the amount of time a developer spends navigating the folder tree to find the right file.
```text
apps/
booking/
check-in/
libs/
booking/ <---- grouping folder
feature-shell/ <---- project
check-in/
feature-shell/
shared/ <---- grouping folder
data-access/ <---- project
seatmap/ <---- grouping folder
data-access/ <---- project
feature-seatmap/ <---- project
```
## Sharing Projects
One of the main advantages of using a monorepo is that there is more visibility into code that can be reused across many different applications. Shared projects are a great way to save developers time and effort by reusing a solution to a common problem.
Lets consider our reference monorepo. The `shared-data-access` project contains the code needed to communicate with the back-end (for example, the URL prefix). We know that this would be the same for all libs; therefore, we should place this in the shared lib and properly document it so that all projects can use it instead of writing their own versions.
```text
libs/
booking/
data-access/ <---- app-specific project
shared/
data-access/ <---- shared project
seatmap/
data-access/ <---- shared project
feature-seatmap/ <---- shared project
```

View File

@ -0,0 +1,38 @@
# Monorepo or Polyrepo
Monorepos have a lot of benefits, but there are also some costs involved. We feel strongly that the [technical challenges](/concepts/decisions/why-monorepos) involved in maintaining large monorepos are fully addressed through the efficient use of Nx and Nx Cloud. Rather, the limiting factors in how large your monorepo grows are interpersonal.
In order for teams to work together in a monorepo, they need to agree on how that repository is going to be managed. These questions can be answered in many different ways, but if the developers in the repository can't agree on the answers, then they'll need to work in separate repositories.
**Organizational Decisions:**
- [Dependency Management](/concepts/decisions/dependency-management) - Should there be an enforced single version policy or should each project maintain their own dependency versions independently?
- [Code Ownership](/concepts/decisions/code-ownership) - What is the code review process? Who is responsible for reviewing changes to each portion of the repository?
- [Project Dependency Rules](/concepts/decisions/project-dependency-rules) - What are the restrictions on dependencies between projects? Which projects can depend on which other projects?
- [Folder Structure](/concepts/decisions/folder-structure) - What is the folder structure and naming convention for projects in the repository?
- [Project Size](/concepts/decisions/project-size) - What size should projects be before they need to be split into separate projects?
- Git Workflow - What Git workflow should be used? Will you use trunk-based development or long running feature branches?
- CI Pipeline - How is the CI pipeline managed? Who is responsible for maintaining it?
- Deployment - How are deployments managed? Does each project deploy independently or do they all deploy at once?
## How Many Repositories?
Once you have a good understanding of where people stand on these questions, you'll need to choose between one of the following setups:
### One Monorepo to Rule Them All
If everyone can agree on how to run the repository, having [a single monorepo will provide a lot of benefits](/concepts/decisions/why-monorepos). Every project can share code and maintenance tasks can be performed in one PR for the entire organization. Any task that involves coordination becomes much easier.
Once the repository scales to hundreds of developers, you need to take proactive steps to ensure that your decisions about [code review](/concepts/decisions/code-ownership) and [project dependency restrictions](/features/enforce-module-boundaries) do not inhibit the velocity of your teams. Also, any shared code and tooling (like the CI pipeline or a shared component library) need to be maintained by a dedicated team to help everyone in the monorepo.
### Polyrepos - A Repository for Each Project
If every project is placed in its own repository, each team can make their own organizational decisions without the need to consult with other teams. Unfortunately, this also means that each team has to make their own organizational decisions instead of focusing on feature work that provides business value. Sharing code is difficult with this set up and every maintenance task needs to be repeated across all the repositories in the organization.
Nx can still be useful with this organizational structure. Tooling and maintenance tasks can be centralized through shared [Nx plugins](/concepts/nx-plugins) that each repository can opt-in to using. Since creating repositories is a frequent occurrence in this scenario, Nx [generators](/features/generate-code) can be used to quickly scaffold out the repository with reasonable tooling defaults.
### Multiple Monorepos
Somewhere between the single monorepo and the full polyrepo solutions exists the multiple monorepo setup. Typically when there are disagreements about organizational decisions, there are two or three factions that form. These factions can naturally be allocated to separate monorepos that have been configured in a way that best suits the teams that will be working in them.
Compared to the single monorepo setup, this setup requires some extra overhead cost - maintaining multiple CI pipelines and performing the same tooling maintenance tasks on multiple repositories, but this cost could be offset by the extra productivity boost provided by the fact that each team can work in a repository that is optimized for the way that they work.

View File

@ -4,13 +4,13 @@ A monorepo is a single git repository that holds the source code for multiple ap
## What are the benefits of a monorepo? ## What are the benefits of a monorepo?
- **Shared code and visibility** - [Keeps your code DRY across your entire organization.](/concepts/more-concepts/code-sharing) Reuse validation code, UI components, and types across the codebase. Reuse code between the backend, the frontend, and utility libraries. - **Shared code and visibility** - [Keeps your code DRY across your entire organization.](/concepts/decisions/code-ownership) Reuse validation code, UI components, and types across the codebase. Reuse code between the backend, the frontend, and utility libraries.
- **Atomic changes** - Change a server API and modify the downstream applications that consume that API in the same commit. You can change a button component in a shared library and the applications that use that component in the same commit. A monorepo saves the pain of trying to coordinate commits across multiple repositories. - **Atomic changes** - Change a server API and modify the downstream applications that consume that API in the same commit. You can change a button component in a shared library and the applications that use that component in the same commit. A monorepo saves the pain of trying to coordinate commits across multiple repositories.
- **Developer mobility** - Get a consistent way of building and testing applications written using different tools and technologies. Developers can confidently contribute to other teams applications and verify that their changes are safe. - **Developer mobility** - Get a consistent way of building and testing applications written using different tools and technologies. Developers can confidently contribute to other teams applications and verify that their changes are safe.
- **Single set of dependencies** - [Use a single version of all third-party dependencies](/concepts/more-concepts/dependency-management), reducing inconsistencies between applications. Less actively developed applications are still kept up-to-date with the latest version of a framework, library, or build tool. - **Single set of dependencies** - [Use a single version of all third-party dependencies](/concepts/decisions/dependency-management), reducing inconsistencies between applications. Less actively developed applications are still kept up-to-date with the latest version of a framework, library, or build tool.
## Why not just code collocation? ## Why not just code collocation?

View File

@ -1,6 +1,8 @@
# Library Types # Project Dependency Rules
There are many types of libraries in a workspace. In order to maintain a certain sense of order, we recommend having a small number of types, such as the below four (4) types of libraries. There are many types of libraries in a workspace. You can identify the type of a library through a naming convention and/or by using the project tagging system. With explicitly defined types, you can also use Nx to enforce project dependency rules based on the types of each project. This article explains one possible way to organize your repository projects by type. Every repository is different and yours may need a different set of types.
In order to maintain a certain sense of order, we recommend having a small number of types, such as the below four (4) types of libraries.
**Feature libraries:** **Feature libraries:**
@ -102,6 +104,49 @@ export { formatDate, formatTime } from './src/format-date-fns';
export { formatCurrency } from './src/format-currency'; export { formatCurrency } from './src/format-currency';
``` ```
## Enforce Project Dependency Rules
In order to enforce the dependency constraints that were listed for each type, you can add the following rule in the root `.eslintrc.json` file:
```json {% fileName="/.eslintrc.json" %}
{
"root": true,
"ignorePatterns": ["**/*"],
"plugins": ["@nx"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {
"@nx/enforce-module-boundaries": [
"error",
{
"allow": [],
"depConstraints": [
{
"sourceTag": "type:feature",
"onlyDependOnLibsWithTags": [
"type:feature",
"type:ui",
"type:util"
]
},
{
"sourceTag": "type:ui",
"onlyDependOnLibsWithTags": ["type:ui", "type:util"]
},
{
"sourceTag": "type:util",
"onlyDependOnLibsWithTags": ["type:util"]
}
]
}
]
}
}
]
}
```
## Other Types ## Other Types
You will probably come up with other library types that make sense for your organization. That's fine. Just keep a few things in mind: You will probably come up with other library types that make sense for your organization. That's fine. Just keep a few things in mind:

View File

@ -0,0 +1,43 @@
# Project Size
Like a lot of decisions in programming, deciding to make a new Nx project or not is all about trade-offs. Each organization will decide on their own conventions, but here are some trade-offs to bear in mind as you have the conversation.
## What is a Project For?
> Developers new to Nx can be initially hesitant to move their logic into separate projects, because they assume it implies that those projects need to be general purpose and shareable across applications.
**This is a common misconception, moving code into projects can be done from a pure code organization perspective.**
Ease of re-use might emerge as a positive side effect of refactoring code into projects by applying an _"API thinking"_ approach. It is not the main driver though.
In fact when organizing projects you should think about your business domains.
## Should I Make a New Project?
There are three main benefits to breaking your code up into more projects.
### 1. Faster Commands
The more granular your projects are, the more effective `nx affected` and Nx's computation cache will be. For example, if `projectA` contains 10 tests, but only 5 of them were affected by a particular code change, all 10 tests will be run by `nx affected -t test`. If you can predict which 5 tests are usually run together, you can split all the related code into a separate project to allow the two groups of 5 tests to be executed independently.
### 2. Visualizing Architecture
The `nx graph` command generates a graph of how apps and projects depend on each other. If most of your code lives in a few giant projects, this visualization doesn't provide much value. Adding the `--watch` flag to the command will update the visualization in-browser as you make changes.
### 3. Enforcing Constraints
You can enforce constraints on how different types of projects depend on each other [using tags](/features/enforce-module-boundaries). Following pre-determined conventions on what kind of code can go in different types of projects allows your tagging system to enforce good architectural patterns.
Also, each project defines its own API, which allows for encapsulating logic that other parts of codebase can not access. You can even use a [CODEOWNERS file](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) to assign ownership of a certain project to a user or team.
## Should I Add to an Existing Project?
Limiting the number of projects by keeping code in an existing project also has benefits.
### 1. Consolidating Code
Related code should be close together. If a developer can accomplish a task without moving between multiple different folders, it helps them work faster and make less mistakes. Every new project adds some folders and configuration files that are not directly contributing to business value. Nx helps reduce the cost of adding a new project, but it isn't zero.
### 2. Removing Constraints
Especially for rapidly evolving code, the standard architectural constraints may just get in the way of experimentation and exploration. It may be worthwhile to develop for a while in a single project in order to allow a real architecture to emerge and then refactoring into multiple projects once the pace of change has slowed down.

View File

@ -16,9 +16,9 @@ Nx's features can be enabled in each of these types of repositories. Just as eac
## Package-Based Repos ## Package-Based Repos
A package-based repo is a collection of packages that depend on each other via `package.json` files and nested `node_modules`. With this setup, you typically have [different dependencies for each project](/concepts/more-concepts/dependency-management). Build tools like Jest and Webpack work as usual, since everything is resolved as if each package was in a separate repo and all of its dependencies were published to npm. Moving an existing package into a package-based repo is very easy since you generally leave that package's existing build tooling untouched. Creating a new package inside the repo is just as difficult as spinning up a new repo since you have to create all the build tooling from scratch. A package-based repo is a collection of packages that depend on each other via `package.json` files and nested `node_modules`. With this setup, you typically have [different dependencies for each project](/concepts/decisions/dependency-management). Build tools like Jest and Webpack work as usual, since everything is resolved as if each package was in a separate repo and all of its dependencies were published to npm. Moving an existing package into a package-based repo is very easy since you generally leave that package's existing build tooling untouched. Creating a new package inside the repo is just as difficult as spinning up a new repo since you have to create all the build tooling from scratch.
Lerna, Yarn, Lage, [Turborepo](/concepts/more-concepts/turbo-and-nx) and Nx support this style. Lerna, Yarn, Lage, [Turborepo](/concepts/turbo-and-nx) and Nx support this style.
Someone who appreciates the flexibility of a package-based repository will be most interested in the following features of Nx: Someone who appreciates the flexibility of a package-based repository will be most interested in the following features of Nx:
@ -32,7 +32,7 @@ Someone who appreciates the flexibility of a package-based repository will be mo
## Integrated Repos ## Integrated Repos
An integrated repo contains projects that depend on each other through standard import statements. There is typically a [single version of every dependency](/concepts/more-concepts/dependency-management) defined at the root. Sometimes build tools like Jest and Webpack need to be wrapped to work correctly. It's harder to add an existing package to this repo style because the build tooling for that package may need to be modified. It's straightforward to add a brand-new project to the repo because all the tooling decisions have already been made. An integrated repo contains projects that depend on each other through standard import statements. There is typically a [single version of every dependency](/concepts/decisions/dependency-management) defined at the root. Sometimes build tools like Jest and Webpack need to be wrapped to work correctly. It's harder to add an existing package to this repo style because the build tooling for that package may need to be modified. It's straightforward to add a brand-new project to the repo because all the tooling decisions have already been made.
Bazel and Nx support this style. Bazel and Nx support this style.

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -48,7 +48,7 @@ In the next section, we will see an example with a host app (`host`) and three r
Although all the applications are independently built, thus have no dependency between them, conceptually you can think Although all the applications are independently built, thus have no dependency between them, conceptually you can think
of them in the following hierarchy. of them in the following hierarchy.
![Host with implicit dependencies to remotes](/shared/guides/module-federation/dep-graph-2.png) ![Host with implicit dependencies to remotes](/shared/concepts/module-federation/dep-graph-2.png)
## Creating an example workspace ## Creating an example workspace
@ -72,7 +72,7 @@ that are simple to set up. You can see what the CI does by viewing the sample pu
the [Nx Cloud](https://nx.app) integration, which gives you insight into each pipeline. We'll touch on the [Nx Cloud](https://nx.app) integration, which gives you insight into each pipeline. We'll touch on
this [later in this guide](#remote-computation-caching-with-nx-cloud). this [later in this guide](#remote-computation-caching-with-nx-cloud).
![Nx Cloud integration for GitHub](/shared/guides/module-federation/pull-request.png) ![Nx Cloud integration for GitHub](/shared/concepts/module-federation/pull-request.png)
Now, let's continue by creating an empty Nx workspace. Now, let's continue by creating an empty Nx workspace.
@ -350,7 +350,7 @@ In addition to computation caching, Nx Cloud also comes with:
- GitHub integration, so you can easily access important information without digging through a bunch of CI/CD logs. - GitHub integration, so you can easily access important information without digging through a bunch of CI/CD logs.
- Actionable insights, which improve caching and task distribution. - Actionable insights, which improve caching and task distribution.
![Nx Cloud run details](/shared/guides/module-federation/nx-cloud.png) ![Nx Cloud run details](/shared/concepts/module-federation/nx-cloud.png)
## Production build and deployment with Nx Cloud ## Production build and deployment with Nx Cloud

View File

@ -13,10 +13,10 @@ To mitigate these issues, Module Federation has a shared API. Its primary functi
The Shared API maintains a registry of all the downloaded dependencies. When a federated module requests a dependency, the Shared API checks the registry. If the dependency already exists, the module is directed to use the existing copy. If not, the dependency is downloaded and added to the registry. The Shared API maintains a registry of all the downloaded dependencies. When a federated module requests a dependency, the Shared API checks the registry. If the dependency already exists, the module is directed to use the existing copy. If not, the dependency is downloaded and added to the registry.
![How Shared API works](/shared/guides/module-federation/shared-api.png) ![How Shared API works](/shared/concepts/module-federation/shared-api.png)
{% callout type="info" title="Lost?" %} {% callout type="info" title="Lost?" %}
If you are not familiar with the concepts of federated modules, remotes, and hosts, please read the [Faster builds with module federation](https://nx.dev/concepts/more-concepts/faster-builds-with-module-federation) for an introduction. If you are not familiar with the concepts of federated modules, remotes, and hosts, please read the [Faster builds with module federation](/concepts/module-federation/faster-builds-with-module-federation) for an introduction.
{% /callout %} {% /callout %}
## Our Approach ## Our Approach
@ -60,7 +60,7 @@ A common use-case for this is if you want to enable tree-shaking for a library l
**Nx** determines the version of a library by looking at a `package.json`. If the library is an npm package, the version is determined by the version declared in the workspace `package.json`. If the library is a workspace library, the version is determined by the version in the `package.json` of the project that consumes the shared library. RemoteA consumes Counter, which is a workspace library exposed and shared by RemoteB. The version of Counter is determined by the version in RemoteB's `package.json`. If the `package.json` does not exist or the library is not declared, Nx will use the version in the `package.json` of the workspace library. **Nx** determines the version of a library by looking at a `package.json`. If the library is an npm package, the version is determined by the version declared in the workspace `package.json`. If the library is a workspace library, the version is determined by the version in the `package.json` of the project that consumes the shared library. RemoteA consumes Counter, which is a workspace library exposed and shared by RemoteB. The version of Counter is determined by the version in RemoteB's `package.json`. If the `package.json` does not exist or the library is not declared, Nx will use the version in the `package.json` of the workspace library.
![How Nx determines library versions](/shared/guides/module-federation/nx-library-version.png) ![How Nx determines library versions](/shared/concepts/module-federation/nx-library-version.png)
There are twos ways to manage library versions with **Nx**: There are twos ways to manage library versions with **Nx**:

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -40,7 +40,7 @@ to exist between host and remotes.
For example, if you have a `shell` host application, with three remotes -- `about`, `cart`, `shop` -- and a shared For example, if you have a `shell` host application, with three remotes -- `about`, `cart`, `shop` -- and a shared
`ui-button` library, then your project graph might look something like this. `ui-button` library, then your project graph might look something like this.
![MFE setup with independent projects](/shared/guides/module-federation/mfe-dep-graph.png) ![MFE setup with independent projects](/shared/concepts/module-federation/mfe-dep-graph.png)
Keeping the applications independent allows them to be deployed on different cadences, which is the whole point of MFEs. Keeping the applications independent allows them to be deployed on different cadences, which is the whole point of MFEs.

View File

Before

Width:  |  Height:  |  Size: 207 KiB

After

Width:  |  Height:  |  Size: 207 KiB

View File

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 174 KiB

View File

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 208 KiB

View File

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 142 KiB

View File

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -111,7 +111,7 @@ Getting started quickly is very easy. Check out some of the examples below:
Nx core make things faster but doesn't change how your commands run or how the terminal output looks. Compare Nx's and Turbo's terminal outputs: Nx core make things faster but doesn't change how your commands run or how the terminal output looks. Compare Nx's and Turbo's terminal outputs:
![nx and turbo terminal output](/shared/turbo-nx-terminal.gif) ![nx and turbo terminal output](/shared/concepts/turbo-nx-terminal.gif)
Nx doesn't change your terminal output. Spinners, animations, colors are the same whether you use Nx or not (we instrument Node.js to get this result). What is also important is that when you restore things from cache, Nx will replay the terminal output identical to the one you would have had you run the command. Examine Turbo's output: no spinners, no animations, no colors. Pretty much anything you run with Turbo looks different (and in our opinion worse) from running the same command without Turbo. Nx doesn't change your terminal output. Spinners, animations, colors are the same whether you use Nx or not (we instrument Node.js to get this result). What is also important is that when you restore things from cache, Nx will replay the terminal output identical to the one you would have had you run the command. Examine Turbo's output: no spinners, no animations, no colors. Pretty much anything you run with Turbo looks different (and in our opinion worse) from running the same command without Turbo.
@ -146,7 +146,7 @@ Turborepo is mostly written in Golang and Rust. Nx is mostly written in TypeScri
Benchmarking is hard because a lot depends on what you are trying to run, in what environment, etc. This is one benchmark we use when measuring Nx perf: [Nx and Turbo benchmark](https://github.com/vsavkin/large-monorepo/). It is a repo with 5 Next.js apps. We are measuring how quickly Nx and Turbo can figure out what needs to be restored from cache, and how quickly they can do it. Benchmarking is hard because a lot depends on what you are trying to run, in what environment, etc. This is one benchmark we use when measuring Nx perf: [Nx and Turbo benchmark](https://github.com/vsavkin/large-monorepo/). It is a repo with 5 Next.js apps. We are measuring how quickly Nx and Turbo can figure out what needs to be restored from cache, and how quickly they can do it.
This is the result: This is the result:
![nx and turbo benchmark](/shared/turbo-nx-perf.gif) ![nx and turbo benchmark](/shared/concepts/turbo-nx-perf.gif)
Nx is 9.4 times faster on the latest MBP. We have made several changes to [the benchmark](https://github.com/vsavkin/large-monorepo/) since it was released (removed the usage `npx` and addressed other concerns folks had), but the result remained roughly the same. Please check out the benchmark. Nx is 9.4 times faster on the latest MBP. We have made several changes to [the benchmark](https://github.com/vsavkin/large-monorepo/) since it was released (removed the usage `npx` and addressed other concerns folks had), but the result remained roughly the same. Please check out the benchmark.

View File

Before

Width:  |  Height:  |  Size: 566 KiB

After

Width:  |  Height:  |  Size: 566 KiB

View File

Before

Width:  |  Height:  |  Size: 864 KiB

After

Width:  |  Height:  |  Size: 864 KiB

View File

@ -182,9 +182,6 @@ Nx allows you to create libraries with just one command. Some reasons you might
- Publish a package to be used outside the monorepo - Publish a package to be used outside the monorepo
- Better visualize the architecture using `npx nx graph` - Better visualize the architecture using `npx nx graph`
For more information on Nx libraries, see our documentation on [Creating Libraries](/concepts/more-concepts/creating-libraries)
and [Library Types](/concepts/more-concepts/library-types).
To generate a new library run: To generate a new library run:
```shell ```shell

View File

@ -321,7 +321,7 @@ documentation" url="/concepts/task-pipeline-configuration" /%}
url="/reference/nxignore" /%} url="/reference/nxignore" /%}
{% card title="Nx and Turbo" description="Read about how Nx compares to Turborepo" url=" {% card title="Nx and Turbo" description="Read about how Nx compares to Turborepo" url="
/concepts/more-concepts/turbo-and-nx" /%} /concepts/turbo-and-nx" /%}
{% card title="Integrated Repos vs Package-Based Repos" description="Learn about two styles of monorepos." url=" {% card title="Integrated Repos vs Package-Based Repos" description="Learn about two styles of monorepos." url="
/concepts/integrated-vs-package-based" /%} /concepts/integrated-vs-package-based" /%}

View File

@ -2,7 +2,7 @@
If you have an existing monorepo that uses Turborepo, switching to use Nx is a straight-forward process. After switching, you'll have cleaner CLI output, a better graph view and IDE support with the option to incorporate Nx plugins and take advantage of the features of an integrated repository. All this without increasing the complexity of your configuration files. If you have an existing monorepo that uses Turborepo, switching to use Nx is a straight-forward process. After switching, you'll have cleaner CLI output, a better graph view and IDE support with the option to incorporate Nx plugins and take advantage of the features of an integrated repository. All this without increasing the complexity of your configuration files.
For more details, read our [comparison of Nx and Turborepo](/concepts/more-concepts/turbo-and-nx) For more details, read our [comparison of Nx and Turborepo](/concepts/turbo-and-nx)
## Initialize Nx ## Initialize Nx
@ -139,7 +139,7 @@ For each `turbo.json` configuration property, the equivalent Nx property is list
| `--ignore` | Use an [`.nxignore` file](/reference/nxignore) (or `.gitignore`) | | `--ignore` | Use an [`.nxignore` file](/reference/nxignore) (or `.gitignore`) |
| `--log-order` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) | | `--log-order` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) |
| `--no-cache` | Use [`--skip-nx-cache`](/nx-api/nx/documents/run-many#skip-nx-cache) | | `--no-cache` | Use [`--skip-nx-cache`](/nx-api/nx/documents/run-many#skip-nx-cache) |
| `--no-daemon` | Use [`NX_DAEMON=false` or set `useDaemonProcess: false`](/concepts/more-concepts/nx-daemon#turning-it-off) in `nx.json` | | `--no-daemon` | Use [`NX_DAEMON=false` or set `useDaemonProcess: false`](/concepts/nx-daemon#turning-it-off) in `nx.json` |
| `--output-logs` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) | | `--output-logs` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) |
| `--only` | N/A | | `--only` | N/A |
| `--parallel` | N/A | | `--parallel` | N/A |

View File

@ -111,9 +111,9 @@ nx lint libName
Read more about: Read more about:
- [Creating Libraries](/concepts/more-concepts/creating-libraries) - [Creating Libraries](/concepts/decisions/project-size)
- [Library Types](/concepts/more-concepts/library-types) - [Library Types](/concepts/decisions/project-dependency-rules)
- [Buildable and Publishable Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) - [Buildable and Publishable Libraries](/concepts/buildable-and-publishable-libraries)
### Fallback to `@schematics/angular` ### Fallback to `@schematics/angular`

View File

@ -88,7 +88,7 @@ To make the library `publishable`, use the following command:
nx g @nx/nest:lib my-nest-lib --publishable --importPath=@my-workspace/my-nest-lib nx g @nx/nest:lib my-nest-lib --publishable --importPath=@my-workspace/my-nest-lib
``` ```
> Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). > Read more about [building and publishing libraries here](/concepts/buildable-and-publishable-libraries).
### Nest Generators ### Nest Generators

View File

@ -108,9 +108,6 @@ Nx allows you to create libraries with just one command. Some reasons you might
- Publish a package to be used outside the monorepo - Publish a package to be used outside the monorepo
- Better visualize the architecture using `nx graph` - Better visualize the architecture using `nx graph`
For more information on Nx libraries, see our documentation on [Creating Libraries](/concepts/more-concepts/creating-libraries)
and [Library Types](/concepts/more-concepts/library-types).
To generate a new library run: To generate a new library run:
```shell ```shell

View File

@ -70,7 +70,7 @@ nx g @nx/react:lib my-new-lib \
--importPath=@myorg/my-new-lib --importPath=@myorg/my-new-lib
``` ```
Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). Read more about [building and publishing libraries here](/concepts/buildable-and-publishable-libraries).
### Creating Components ### Creating Components

View File

@ -87,7 +87,7 @@ In the following section, we are going to see how to set up Storybook in these c
### Philosophy ### Philosophy
Setting up Storybook on Nx reflects - and takes advantage of - the [mental model](/concepts/mental-model) of Nx, and especially the architecture of [Applications and Libraries](/concepts/more-concepts/applications-and-libraries). What that means, in essence, is that you still maintain the individual Storybook instances (per project) which you use for testing and local development, but you also keep one extra “container” for publishing, that serves as a single entry point. Lets see this in more detail. Setting up Storybook on Nx reflects - and takes advantage of - the [mental model](/concepts/mental-model) of Nx. What that means, in essence, is that you still maintain the individual Storybook instances (per project) which you use for testing and local development, but you also keep one extra “container” for publishing, that serves as a single entry point. Lets see this in more detail.
#### Local development and testing #### Local development and testing
@ -119,7 +119,7 @@ Since each Storybook, in this case, is attached to a project, so is the serving
#### Publishing #### Publishing
When you are publishing your Storybook, you can follow the same principles described in the [Applications and Libraries Mental Model](/concepts/more-concepts/applications-and-libraries#mental-model) documentation page. The general idea is to have one central Storybook container, into which you are going to gather your stories from multiple libraries. When you are publishing your Storybook, you can follow the same principles described in the [Applications and Libraries Mental Model](/concepts/decisions/project-size#mental-model) documentation page. The general idea is to have one central Storybook container, into which you are going to gather your stories from multiple libraries.
You can think of the central Storybook container as a grouping of similar-concept or same-scope UI parts of your workspace. In the same way you are scoping libraries, you can group your stories as well. You can think of the central Storybook container as a grouping of similar-concept or same-scope UI parts of your workspace. In the same way you are scoping libraries, you can group your stories as well.
@ -129,7 +129,7 @@ Then, according to your use-case, you can have one central Storybook for your wh
In order to achieve some things mentioned above, you may use [Storybook Composition](/recipes/storybook/storybook-composition-setup). However, in this case, you would still need to build each projects Storybook individually, and also deploy it individually. So in the cases where you have multiple projects, Storybook Composition would not be very efficient. In order to achieve some things mentioned above, you may use [Storybook Composition](/recipes/storybook/storybook-composition-setup). However, in this case, you would still need to build each projects Storybook individually, and also deploy it individually. So in the cases where you have multiple projects, Storybook Composition would not be very efficient.
{% /callout %} {% /callout %}
Before moving on to the examples section, it could be useful to read the [Library Types](/concepts/more-concepts/library-types) documentation page and the [Grouping libraries](/concepts/more-concepts/grouping-libraries) documentation page. These could help you decide which way fits your use case better. Before moving on to the examples section, it could be useful to read the [Library Types](/concepts/decisions/project-dependency-rules) documentation page and the [Grouping libraries](/concepts/decisions/folder-structure) documentation page. These could help you decide which way fits your use case better.
## Examples / Use cases ## Examples / Use cases

View File

@ -11,7 +11,7 @@ The integrated project is now ready to use. Next, we'll discuss some of the chan
## package.json dependencies ## package.json dependencies
All the dependencies that are required for an integrated project are maintained in the root `package.json` file. In order to use the plugin's [Automate Updating Framework Dependencies](/features/automate-updating-dependencies) feature, we recommend using a [Single Version Policy](/concepts/more-concepts/dependency-management#single-version-policy) for integrated projects. All the dependencies that are required for an integrated project are maintained in the root `package.json` file. In order to use the plugin's [Automate Updating Framework Dependencies](/features/automate-updating-dependencies) feature, we recommend using a [Single Version Policy](/concepts/decisions/dependency-management#single-version-policy) for integrated projects.
## tsconfig.base.json ## tsconfig.base.json

View File

@ -27,7 +27,7 @@ With [npm](https://docs.npmjs.com/cli/v7/using-npm/workspaces)/[yarn](https://cl
When you manage dependencies this way, you can still hoist dependencies to the root-level `package.json` file, but you have to make the explicit decision for each dependency. When you manage dependencies this way, you can still hoist dependencies to the root-level `package.json` file, but you have to make the explicit decision for each dependency.
There are difficulties with code sharing when you maintain separate dependencies. See the [Dependency Management Strategies](/concepts/more-concepts/dependency-management) guide for more information. There are difficulties with code sharing when you maintain separate dependencies. See the [Dependency Management Strategies](/concepts/decisions/dependency-management) guide for more information.
## Run Tasks Without the Use of an Nx Plugin ## Run Tasks Without the Use of an Nx Plugin

View File

@ -8,7 +8,7 @@ description: Learn how to set up individual Storybook instances for each scope w
This guide extends the This guide extends the
[Using Storybook in a Nx workspace - Best practices](/nx-api/storybook/documents/best-practices) guide. In that guide, we discussed the best practices of using Storybook in a Nx workspace. We explained the main concepts and the mental model of how to best set up Storybook. In this guide, we are going to see how to put that into practice, by looking at a real-world example. We are going to see how you can publish one Storybook per scope (eg. theme, app, framework) for your workspace. [Using Storybook in a Nx workspace - Best practices](/nx-api/storybook/documents/best-practices) guide. In that guide, we discussed the best practices of using Storybook in a Nx workspace. We explained the main concepts and the mental model of how to best set up Storybook. In this guide, we are going to see how to put that into practice, by looking at a real-world example. We are going to see how you can publish one Storybook per scope (eg. theme, app, framework) for your workspace.
Sometimes, you have multiple apps and libraries, and each of these is associated with a specific scope. You can read more about grouping libraries and scoping them in the [Library Types](/concepts/more-concepts/library-types) documentation page. Sometimes, you have multiple apps and libraries, and each of these is associated with a specific scope. You can read more about grouping libraries and scoping them in the [Library Types](/concepts/decisions/project-dependency-rules) documentation page.
In this case, you can have one Storybook instance per scope. If you follow the folder organization convention described above, it is easy to configure Storybook to import all the stories under a specific folder, for example, which are associated with a specific app or scope. In this case, you can have one Storybook instance per scope. If you follow the folder organization convention described above, it is easy to configure Storybook to import all the stories under a specific folder, for example, which are associated with a specific app or scope.

View File

@ -8,8 +8,6 @@ This is a short list of Nx-specific terms that will help you understand the rest
A [project](#project) that can run on its own. Generally uses [libraries](#library). A [project](#project) that can run on its own. Generally uses [libraries](#library).
> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries)
### Atomizer ### Atomizer
The Atomizer is an Nx Cloud feature that automatically splits tasks so that they can be executed in parallel. The Atomizer is an Nx Cloud feature that automatically splits tasks so that they can be executed in parallel.
@ -22,7 +20,7 @@ Atomizer automatically splits tasks on [Nx Agents](#nx-agents), providing you de
A [library](#library) that has a `build` [target](#target). Some libraries can be generated with a `build` target using the `--buildable` flag. A [library](#library) that has a `build` [target](#target). Some libraries can be generated with a `build` target using the `--buildable` flag.
> See: [Publishable and Buildable Nx Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) > See: [Publishable and Buildable Nx Libraries](/concepts/buildable-and-publishable-libraries)
### Cache ### Cache
@ -120,14 +118,10 @@ Launch Templates are used to set up an agent machine. They specify a resource cl
A [project](#project) that is used by [applications](#application) or other [libraries](#library). A [project](#project) that is used by [applications](#application) or other [libraries](#library).
> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries)
### Monolith ### Monolith
A large [application](#application) that is difficult to separate into smaller pieces. A large [application](#application) that is difficult to separate into smaller pieces.
> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries)
### Monorepo ### Monorepo
A repository with multiple [projects](#project). A repository with multiple [projects](#project).
@ -180,13 +174,11 @@ Related [projects](#project) spread across multiple repositories.
The unit of code on which a [task](#task) can be run. A project can be an [application](#application) or a [library](#library). The unit of code on which a [task](#task) can be run. A project can be an [application](#application) or a [library](#library).
> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries)
### Publishable Library ### Publishable Library
A [library](#library) that has a `publish` [target](#target). Some libraries can be generated with a `publish` target using the `--publishable` flag. A [library](#library) that has a `publish` [target](#target). Some libraries can be generated with a `publish` target using the `--publishable` flag.
> See: [Publishable and Buildable Nx Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) > See: [Publishable and Buildable Nx Libraries](/concepts/buildable-and-publishable-libraries)
### Remote Cache ### Remote Cache

View File

@ -31,22 +31,22 @@
- [Types of Configuration](/concepts/types-of-configuration) - [Types of Configuration](/concepts/types-of-configuration)
- [Executors and Configurations](/concepts/executors-and-configurations) - [Executors and Configurations](/concepts/executors-and-configurations)
- [Integrated Repos vs. Package-Based Repos vs. Standalone Apps](/concepts/integrated-vs-package-based) - [Integrated Repos vs. Package-Based Repos vs. Standalone Apps](/concepts/integrated-vs-package-based)
- [Nx Daemon](/concepts/nx-daemon)
- [Nx and Turborepo](/concepts/turbo-and-nx)
- [Buildable and Publishable Libraries](/concepts/buildable-and-publishable-libraries)
- [Module Federation](/concepts/module-federation) - [Module Federation](/concepts/module-federation)
- [Module Federation and Nx](/concepts/module-federation/module-federation-and-nx) - [Module Federation and Nx](/concepts/module-federation/module-federation-and-nx)
- [Faster Builds with Module Federation](/concepts/module-federation/faster-builds-with-module-federation) - [Faster Builds with Module Federation](/concepts/module-federation/faster-builds-with-module-federation)
- [Micro Frontend Architecture](/concepts/module-federation/micro-frontend-architecture) - [Micro Frontend Architecture](/concepts/module-federation/micro-frontend-architecture)
- [Manage Library Versions with Module Federation](/concepts/module-federation/manage-library-versions-with-module-federation) - [Manage Library Versions with Module Federation](/concepts/module-federation/manage-library-versions-with-module-federation)
- [More Concepts](/concepts/more-concepts) - [Organizational Decisions](/concepts/decisions)
- [Monorepos](/concepts/more-concepts/why-monorepos) - [Overview](/concepts/decisions/overview)
- [Dependency Management](/concepts/more-concepts/dependency-management) - [Monorepos](/concepts/decisions/why-monorepos)
- [Code Sharing](/concepts/more-concepts/code-sharing) - [Dependency Management](/concepts/decisions/dependency-management)
- [Nx Daemon](/concepts/more-concepts/nx-daemon) - [Code Ownership](/concepts/decisions/code-ownership)
- [Nx and Turborepo](/concepts/more-concepts/turbo-and-nx) - [Project Size](/concepts/decisions/project-size)
- [Applications and Libraries](/concepts/more-concepts/applications-and-libraries) - [Project Dependency Rules](/concepts/decisions/project-dependency-rules)
- [When to Create a New Library](/concepts/more-concepts/creating-libraries) - [Folder Structure](/concepts/decisions/folder-structure)
- [Library Types](/concepts/more-concepts/library-types)
- [Grouping Libraries](/concepts/more-concepts/grouping-libraries)
- [Buildable and Publishable Libraries](/concepts/more-concepts/buildable-and-publishable-libraries)
- [Recipes](/recipes) - [Recipes](/recipes)
- [Installation](/recipes/installation) - [Installation](/recipes/installation)
- [Install Nx in a Non-Javascript Repo](/recipes/installation/install-non-javascript) - [Install Nx in a Non-Javascript Repo](/recipes/installation/install-non-javascript)

View File

@ -106,7 +106,7 @@ The setup includes:
- ESLint preconfigured - ESLint preconfigured
- Jest preconfigured - Jest preconfigured
Typically, an integrated Nx workspace places application projects in the `apps` folder and library projects in the `libs` folder. [Applications are encouraged to be as light-weight as possible](/concepts/more-concepts/applications-and-libraries) so that more code is pushed into libraries and can be reused in other projects. This folder structure is just a suggestion and can be modified to suit your organization's needs. Typically, an integrated Nx workspace places application projects in the `apps` folder and library projects in the `libs` folder. Applications are encouraged to be as light-weight as possible so that more code is pushed into libraries and can be reused in other projects. This folder structure is just a suggestion and can be modified to suit your organization's needs.
The [`nx.json` file](/reference/nx-json) contains configuration settings for Nx itself and global default settings that individual projects inherit. The `apps/angular-store/project.json` file contains [settings that are specific to the `angular-store` project](/reference/project-configuration). We'll examine that file more in the next section. The [`nx.json` file](/reference/nx-json) contains configuration settings for Nx itself and global default settings that individual projects inherit. The `apps/angular-store/project.json` file contains [settings that are specific to the `angular-store` project](/reference/project-configuration). We'll examine that file more in the next section.

View File

@ -886,7 +886,7 @@ Once you modularize your codebase you want to make sure that the modules are not
When building these kinds of constraints you usually have two dimensions: When building these kinds of constraints you usually have two dimensions:
- **type of project:** what is the type of your library. Example: "feature" library, "utility" library, "data-access" library, "ui" library (see [library types](/concepts/more-concepts/library-types)) - **type of project:** what is the type of your library. Example: "feature" library, "utility" library, "data-access" library, "ui" library (see [library types](/concepts/decisions/project-dependency-rules))
- **scope (domain) of the project:** what domain area is covered by the project. Example: "orders", "products", "shared" ... this really depends on the type of product you're developing - **scope (domain) of the project:** what domain area is covered by the project. Example: "orders", "products", "shared" ... this really depends on the type of product you're developing
Nx comes with a generic mechanism that allows you to assign "tags" to projects. "tags" are arbitrary strings you can assign to a project that can be used later when defining boundaries between projects. For example, go to the `project.json` of your `orders` library and assign the tags `type:feature` and `scope:orders` to it. Nx comes with a generic mechanism that allows you to assign "tags" to projects. "tags" are arbitrary strings you can assign to a project that can be used later when defining boundaries between projects. For example, go to the `project.json` of your `orders` library and assign the tags `type:feature` and `scope:orders` to it.

View File

@ -28,7 +28,7 @@ Nx Plugins are optional packages that extend the capabilities of Nx, catering to
Features of an integrated monorepo: Features of an integrated monorepo:
- [Install dependencies at the root by default](/concepts/more-concepts/dependency-management#single-version-policy) - [Install dependencies at the root by default](/concepts/decisions/dependency-management#single-version-policy)
- [Scaffold new code with generators](/features/generate-code) - [Scaffold new code with generators](/features/generate-code)
- [Updates dependencies with automated migrations](/features/automate-updating-dependencies) - [Updates dependencies with automated migrations](/features/automate-updating-dependencies)
@ -103,7 +103,7 @@ The setup includes..
- ESLint preconfigured - ESLint preconfigured
- Jest preconfigured - Jest preconfigured
Typically, an integrated Nx workspace places application projects in the `apps` folder and library projects in the `libs` folder. [Applications are encouraged to be as light-weight as possible](/concepts/more-concepts/applications-and-libraries) so that more code is pushed into libraries and can be reused in other projects. This folder structure is just a suggestion and can be modified to suit your organization's needs. Typically, an integrated Nx workspace places application projects in the `apps` folder and library projects in the `libs` folder. Applications are encouraged to be as light-weight as possible so that more code is pushed into libraries and can be reused in other projects. This folder structure is just a suggestion and can be modified to suit your organization's needs.
The [`nx.json` file](/reference/nx-json) contains configuration settings for Nx itself and global default settings that individual projects inherit. The `apps/react-store/project.json` file contains [settings that are specific to the `react-store` project](/reference/project-configuration). We'll examine that file more in the next section. The [`nx.json` file](/reference/nx-json) contains configuration settings for Nx itself and global default settings that individual projects inherit. The `apps/react-store/project.json` file contains [settings that are specific to the `react-store` project](/reference/project-configuration). We'll examine that file more in the next section.

View File

@ -714,7 +714,7 @@ Once you modularize your codebase you want to make sure that the modules are not
When building these kinds of constraints you usually have two dimensions: When building these kinds of constraints you usually have two dimensions:
- **type of project:** what is the type of your library. Example: "feature" library, "utility" library, "data-access" library, "ui" library (see [library types](/concepts/more-concepts/library-types)) - **type of project:** what is the type of your library. Example: "feature" library, "utility" library, "data-access" library, "ui" library (see [library types](/concepts/decisions/project-dependency-rules))
- **scope (domain) of the project:** what domain area is covered by the project. Example: "orders", "products", "shared" ... this really depends on the type of product you're developing - **scope (domain) of the project:** what domain area is covered by the project. Example: "orders", "products", "shared" ... this really depends on the type of product you're developing
Nx comes with a generic mechanism that allows you to assign "tags" to projects. "tags" are arbitrary strings you can assign to a project that can be used later when defining boundaries between projects. For example, go to the `project.json` of your `orders` library and assign the tags `type:feature` and `scope:orders` to it. Nx comes with a generic mechanism that allows you to assign "tags" to projects. "tags" are arbitrary strings you can assign to a project that can be used later when defining boundaries between projects. For example, go to the `project.json` of your `orders` library and assign the tags `type:feature` and `scope:orders` to it.

View File

@ -1,50 +0,0 @@
# Applications and libraries
A typical Nx workspace is structured into _"apps"_ and _"libs"_. This distinction allows us to have a more modular architecture by following a separation of concerns methodology, incentivizing the organization of our source code and logic into smaller, more focused and highly cohesive units.
Nx automatically creates TypeScript path mappings in the `tsconfig.base.json` file, such that they can be easily consumed by other apps or libs.
```typescript
// example of importing from another workspace library
import { Button } from '@my-organization/ui';
...
```
Therefore, consuming libraries is very straightforward, and similar to what you might already be accustomed to in previous projects.
Having a dedicated library project is a much stronger boundary compared to just separating code into folders, though. Each Nx library has a so-called _"public API"_, represented by an `index.ts` barrel file. This forces developers into an _"API thinking"_ of what should be exposed and thus be made available for others to consume, and what on the others side should remain private within the library itself.
{% callout type="caution" title="Library !== published artifact" %}
[This is a common misconception, moving code into libraries can be done from a pure code organization perspective](#misconception).
{% /callout %}
## Mental model
A common mental model is to **see the application as "containers"** that link, bundle and compile functionality implemented in libraries for being deployed.
As such, if we follow a _80/20 approach_:
- place 80% of your logic into the `libs/` folder
- and 20% into `apps/`
Note, these libraries dont necessarily need to be built separately, but are rather consumed and built by the application itself directly. Hence, nothing changes from a pure deployment point of view.
That said, it is totally possible to create so-called _"[buildable libraries](/concepts/more-concepts/buildable-and-publishable-libraries#buildable-libraries)"_ for enabling incremental builds as
well as _"[publishable libraries](/concepts/more-concepts/buildable-and-publishable-libraries#publishable-libraries)"_ for those scenarios where not only you want to
use a specific library within the current Nx workspace, but also to publish it
to some package repository (e.g. NPM).
### Misconception
> Developers new to Nx are initially often hesitant to move their logic into libraries, because they assume it implies that those libraries need to be general purpose and shareable across applications.
**This is a common misconception, moving code into libraries can be done from a pure code organization perspective.**
Ease of re-use might emerge as a positive side effect of refactoring code into libraries by applying an _"API thinking"_ approach. It is not the main driver though.
In fact when organizing libraries you should think about your business domains.
Most often teams are aligned with those domains and thus a similar organization of the libraries in the `libs/` folder might be most appropriate. Nx allows to nest libraries into sub-folders which makes it easy to reflect such structuring.
- [Learn more about when you need to create a new library or using an existing one](/concepts/more-concepts/creating-libraries)
- [Learn more about the different types of libraries we think you should follow](/concepts/more-concepts/library-types)
- [Learn more about how to group libraries between each other](/concepts/more-concepts/grouping-libraries)

View File

@ -1,33 +0,0 @@
# Creating Libraries
Like a lot of decisions in programming, deciding to make a new Nx library or not is all about trade-offs. Each organization will decide on their own conventions, but here are some trade-offs to bear in mind as you have the conversation.
## Should I Make a New Library?
There are three main benefits to breaking your code up into more libraries.
### 1. Faster Commands
The more granular your libraries are, the more effective `nx affected` and Nx's computation cache will be. For example, if `libraryA` contains 10 tests, but only 5 of them were affected by a particular code change, all 10 tests will be run by `nx affected -t test`. If you can predict which 5 tests are usually run together, you can split all the related code into a separate library to allow the two groups of 5 tests to be executed independently.
### 2. Visualizing Architecture
The `nx graph` command generates a graph of how apps and libraries depend on each other. If most of your code lives in a few giant libraries, this visualization doesn't provide much value. Adding the `--watch` flag to the command will update the visualization in-browser as you make changes.
### 3. Enforcing Constraints
You can enforce constraints on how different types of libraries depend on each other [using tags](/features/enforce-module-boundaries). Following pre-determined conventions on what kind of code can go in different types of libraries allows your tagging system to enforce good architectural patterns.
Also, each library defines its own API, which allows for encapsulating logic that other parts of codebase can not access. You can even use a [CODEOWNERS file](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) to assign ownership of a certain library to a user or team.
## Should I Add to an Existing Library?
Limiting the number of libraries by keeping code in an existing library also has benefits.
### 1. Consolidating Code
Related code should be close together. If a developer can accomplish a task without moving between multiple different folders, it helps them work faster and make less mistakes. Every new library adds some folders and configuration files that are not directly contributing to business value. Nx helps reduce the cost of adding a new library, but it isn't zero.
### 2. Removing Constraints
Especially for rapidly evolving code, the standard architectural constraints may just get in the way of experimentation and exploration. It may be worthwhile to develop for a while in a single library in order to allow a real architecture to emerge and then refactoring into multiple libraries once the pace of change has slowed down.

View File

@ -1,65 +0,0 @@
# Grouping Libraries
Libraries should be grouped by _scope_. A library's scope is either application to which it belongs or (for larger applications) a section within that application.
## Move Generator
Don't be too anxious about choosing the exact right folder structure from the beginning. Libraries can be moved or renamed using the [`@nx/workspace:move` generator](/nx-api/workspace/generators/move).
For instance, if a library under the `booking` folder is now being shared by multiple apps, you can move it to the shared folder like this:
```shell
nx g move --project booking-some-library shared/some-library
```
## Remove Generator
Similarly, if you no longer need a library, you can remove it with the [`@nx/workspace:remove` generator](/nx-api/workspace/generators/remove).
```shell
nx g remove booking-some-library
```
## Example Workspace
Let's use Nrwl Airlines as an example organization. This organization has two apps, `booking` and `check-in`. In the Nx workspace, libraries related to `booking` are grouped under a `libs/booking` folder, libraries related to `check-in` are grouped under a `libs/check-in` folder and libraries used in both applications are placed in `libs/shared`. You can also have nested grouping folders, (i.e. `libs/shared/seatmap`).
The purpose of these folders is to help with organizing by scope. We recommend grouping libraries together which are (usually) updated together. It helps minimize the amount of time a developer spends navigating the folder tree to find the right file.
```text
apps/
booking/
check-in/
libs/
booking/ <---- grouping folder
feature-shell/ <---- library
check-in/
feature-shell/
shared/ <---- grouping folder
data-access/ <---- library
seatmap/ <---- grouping folder
data-access/ <---- library
feature-seatmap/ <---- library
```
## Sharing Libraries
One of the main advantages of using a monorepo is that there is more visibility into code that can be reused across many different applications. Shared libraries are a great way to save developers time and effort by reusing a solution to a common problem.
Lets consider our reference monorepo. The `shared-data-access` library contains the code needed to communicate with the back-end (for example, the URL prefix). We know that this would be the same for all libs; therefore, we should place this in the shared lib and properly document it so that all projects can use it instead of writing their own versions.
```text
libs/
booking/
data-access/ <---- app-specific library
shared/
data-access/ <---- shared library
seatmap/
data-access/ <---- shared library
feature-seatmap/ <---- shared library
```

View File

@ -17,7 +17,11 @@ export function categorizeRelatedDocuments(
{ {
id: 'concepts', id: 'concepts',
name: 'Concepts', name: 'Concepts',
matchers: ['/concepts/', '/concepts/more-concepts/'], matchers: [
'/concepts/',
'/concepts/module-federation/',
'/concepts/decisions/',
],
relatedDocuments: [], relatedDocuments: [],
}, },
{ {

View File

@ -1060,6 +1060,24 @@ const removedDeprecatedUrls = {
'/recipes/storybook/overview-react', // 80 views '/recipes/storybook/overview-react', // 80 views
}; };
const decisionsSection = {
'/concepts/more-concepts/why-monorepos': '/concepts/decisions/why-monorepos',
'/concepts/more-concepts/dependency-management':
'/concepts/decisions/dependency-management',
'/concepts/more-concepts/code-sharing': '/concepts/decisions/code-ownership',
'/concepts/more-concepts/applications-and-libraries':
'/concepts/decisions/project-size',
'/concepts/more-concepts/creating-libraries':
'/concepts/decisions/project-size',
'/concepts/more-concepts/library-types':
'/concepts/decisions/project-dependency-rules',
'/concepts/more-concepts/grouping-libraries':
'/concepts/decisions/folder-structure',
'/concepts/more-concepts/turbo-and-nx': '/concepts/turbo-and-nx',
'/concepts/more-concepts/nx-daemon': '/concepts/nx-daemon',
'/concepts/more-concepts/buildable-and-publishable-libraries':
'/concepts/buildable-and-publishable-libraries',
};
// Blog post redirects // Blog post redirects
const blogPosts = { const blogPosts = {
'/blog/2024-05-07-nx-19-release': '/blog/2024-05-08-nx-19-release', '/blog/2024-05-07-nx-19-release': '/blog/2024-05-08-nx-19-release',
@ -1095,4 +1113,5 @@ module.exports = {
removedDeprecatedUrls, removedDeprecatedUrls,
troubleshootingOutOfRecipes, troubleshootingOutOfRecipes,
blogPosts, blogPosts,
decisionsSection,
}; };