diff --git a/.circleci/config.yml b/.circleci/config.yml index 4b0db7816e8be..ec4547ba3486f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,6 @@ version: 2.1 # ------------------------- orbs: nx: nrwl/nx@1.6.1 - node: circleci/node@5.1.0 rust: circleci/rust@1.6.0 browser-tools: circleci/browser-tools@1.4.0 @@ -20,14 +19,14 @@ executors: linux: <<: *defaults docker: - - image: cimg/rust:1.66.1-browsers + - image: cimg/rust:1.70.0-browsers resource_class: medium+ macos: <<: *defaults resource_class: macos.x86.medium.gen2 macos: - xcode: &_XCODE_VERSION '13.0.0' + xcode: '14.2.0' # ------------------------- # COMMANDS @@ -42,10 +41,22 @@ commands: name: Restore pnpm Package Cache keys: - node-deps-{{ arch }}-v3-{{ checksum "pnpm-lock.yaml" }} - - run: - name: Install pnpm package manager - command: | - npm install -g @pnpm/exe@8.3.1 + - when: + condition: + equal: [<< parameters.os >>, linux] + steps: + - run: + name: Install pnpm package manager (linux) + command: | + npm install --prefix=$HOME/.local -g @pnpm/exe@8.3.1 + - when: + condition: + equal: [<< parameters.os >>, macos] + steps: + - run: + name: Install pnpm package manager (macos) + command: | + npm install -g @pnpm/exe@8.3.1 - run: name: Install Dependencies command: | @@ -95,9 +106,6 @@ commands: sudo apt-get install -y ca-certificates lsof - browser-tools/install-chrome - browser-tools/install-chromedriver - - node/install: - # Use LTS version - node-version: '' - run-pnpm-install: os: << parameters.os >> @@ -137,7 +145,7 @@ jobs: - run: name: Set dynamic nx run variable command: | - echo "export NX_RUN_GROUP=\"run-group-<< parameters.os >>-$CIRCLE_WORKFLOW_ID\";" >> $BASH_ENV + echo "export NX_CI_EXECUTION_ENV=\"<< parameters.os >>\";" >> $BASH_ENV - setup: os: << parameters.os >> - run: @@ -160,7 +168,7 @@ jobs: - run: name: Set dynamic nx run variable command: | - echo "export NX_RUN_GROUP=\"run-group-linux-$CIRCLE_WORKFLOW_ID\";" >> $BASH_ENV + echo "export NX_CI_EXECUTION_ENV=\"linux\";" >> $BASH_ENV - setup: os: linux - nx/set-shas: @@ -179,7 +187,7 @@ jobs: pnpm nx-cloud record -- nx format:check --base=$NX_BASE --head=$NX_HEAD & pids+=($!) - pnpm nx run-many -t check-imports check-commit check-lock-files depcheck check-codeowners documentation --parallel=1 --no-dte & + pnpm nx run-many -t check-imports check-commit check-lock-files check-codeowners documentation --parallel=1 --no-dte & pids+=($!) pnpm nx affected --target=lint --base=$NX_BASE --head=$NX_HEAD --parallel=3 & @@ -200,14 +208,15 @@ jobs: executor: macos environment: NX_E2E_CI_CACHE_KEY: e2e-circleci-macos - NX_DAEMON: 'true' + NX_DAEMON: 'false' # TODO: set to true after #18410 NX_PERF_LOGGING: 'false' SELECTED_PM: 'npm' # explicitly define npm for macOS tests + NX_SKIP_NX_CACHE: 'true' # TODO: Remove after #18410 steps: - run: name: Set dynamic nx run variable command: | - echo "export NX_RUN_GROUP=\"run-group-macos-$CIRCLE_WORKFLOW_ID\";" >> $BASH_ENV + echo "export NX_CI_EXECUTION_ENV=\"macos\";" >> $BASH_ENV - setup: os: macos - rust/install diff --git a/.eslintrc.json b/.eslintrc.json index 13d266de370e4..2aa0de27f3fd9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -47,6 +47,7 @@ "error", { "enforceBuildableLibDependency": true, + "checkDynamicDependenciesExceptions": [".*"], "allow": [], "depConstraints": [ { diff --git a/.verdaccio/config.yml b/.verdaccio/config.yml index 81ff6fb0d5d50..1293b915662c4 100644 --- a/.verdaccio/config.yml +++ b/.verdaccio/config.yml @@ -10,9 +10,13 @@ uplinks: npmjs: url: https://registry.npmjs.org/ maxage: 60m + max_fails: 20 + fail_timeout: 2m yarn: url: https://registry.yarnpkg.com maxage: 60m + max_fails: 20 + fail_timeout: 2m packages: '@*/*': diff --git a/CODEOWNERS b/CODEOWNERS index e118e1e31ea1d..c864973e8d5a6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -4,8 +4,8 @@ /e2e/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry /scripts/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry /tools/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry -package.json @nrwl/nx-pipelines-reviewers -pnpm-lock.yaml @nrwl/nx-pipelines-reviewers +package.json @nrwl/nx-core-reviewers +pnpm-lock.yaml @nrwl/nx-core-reviewers # Docs Site + Graph /docs @nrwl/nx-docs-reviewers @@ -99,6 +99,8 @@ pnpm-lock.yaml @nrwl/nx-pipelines-reviewers /e2e/cypress/** @nrwl/nx-testing-tools-reviewers /packages/jest/** @nrwl/nx-testing-tools-reviewers /e2e/jest/** @nrwl/nx-testing-tools-reviewers +/packages/playwright/** @nrwl/nx-testing-tools-reviewers +/e2e/playwright/** @nrwl/nx-testing-tools-reviewers # Linter /docs/generated/packages/eslint-plugin/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers @@ -159,7 +161,6 @@ pnpm-lock.yaml @nrwl/nx-pipelines-reviewers /CODEOWNERS @FrozenPandaz @AgentEnder # Scripts -/scripts/depcheck @FrozenPandaz @vsavkin @jaysoo /scripts/documentation @nrwl/nx-docs-reviewers /scripts/angular-support-upgrades @nrwl/nx-angular-reviewers diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 50f32d93531bc..b0b7a1f944455 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,13 +76,13 @@ Check out [this video for a live walkthrough](https://youtu.be/Tx257WpNsxc) or f - Run `pnpm local-registry` in Terminal 1 (keep it running) - Run `npm adduser --registry http://localhost:4873` in Terminal 2 (real credentials are not required, you just need to be logged in. You can use test/test/test@test.io.) -- Run `pnpm nx-release 16.0.0 --local` in Terminal 2 - you can choose any nonexistent version number here, but it's recommended to use the next major +- Run `pnpm nx-release 17.0.0 --local` in Terminal 2 - you can choose any nonexistent version number here, but it's recommended to use the next major - Run `cd ./tmp` in Terminal 2 - Run `npx create-nx-workspace@17.0.0` in Terminal 2 If you have problems publishing, make sure you use Node 18 and NPM 8. -**NOTE:** To use this newly published local version, you need to make a new workspace or change all of your target packages to this new version, eg: `"nx": "^16.0.0",` and re-run `pnpm i` in your testing project. +**NOTE:** To use this newly published local version, you need to make a new workspace or change all of your target packages to this new version, eg: `"nx": "^17.0.0",` and re-run `pnpm i` in your testing project. ### Publishing for Yarn 2+ (Berry) diff --git a/Cargo.lock b/Cargo.lock index 03fbb212db6cc..4275246ff42b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "ahash" version = "0.8.3" @@ -9,6 +19,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", ] @@ -22,6 +33,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.14" @@ -48,6 +68,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ast_node" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c09c69dffe06d222d072c878c3afe86eee2179806f20503faec97250268b4c24" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.15", +] + [[package]] name = "async-priority-channel" version = "0.1.0" @@ -102,6 +135,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "better_scoped_tls" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794edcc9b3fb07bb4aecaa11f093fd45663b4feadb782d68303a2268bc2701de" +dependencies = [ + "scoped-tls", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -110,9 +152,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.2.1" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "bstr" @@ -122,7 +164,7 @@ checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" dependencies = [ "memchr", "once_cell", - "regex-automata", + "regex-automata 0.1.10", "serde", ] @@ -355,6 +397,27 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "from_variant" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ec5dc38ee19078d84a692b1c41181ff9f94331c76cee66ff0208c770b5e54f" +dependencies = [ + "pmutil", + "proc-macro2", + "swc_macros_common", + "syn 2.0.15", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -512,7 +575,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786861e84a5793ad5f863d846de5eb064cd23b87e61ad708c8c402608202e7be" dependencies = [ - "bitflags 2.2.1", + "bitflags 2.3.3", "bstr", "gix-path", "libc", @@ -558,7 +621,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07c98204529ac3f24b34754540a852593d2a4c7349008df389240266627a72a" dependencies = [ - "bitflags 2.2.1", + "bitflags 2.3.3", "bstr", "gix-features", "gix-path", @@ -642,7 +705,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "794520043d5a024dfeac335c6e520cb616f6963e30dab995892382e998c12897" dependencies = [ - "bitflags 2.2.1", + "bitflags 2.3.3", "gix-path", "libc", "windows", @@ -686,7 +749,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -754,6 +817,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "ignore" version = "0.4.20" @@ -829,6 +902,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "is-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4467ed1321b310c2625c5aa6c1b1ffc5de4d9e42668cf697a08fb033ee8265e" +dependencies = [ + "Inflector", + "pmutil", + "proc-macro2", + "quote", + "syn 2.0.15", +] + [[package]] name = "itertools" version = "0.10.5" @@ -844,15 +930,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" -[[package]] -name = "jsonc-parser" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b56a20e76235284255a09fcd1f45cf55d3c524ea657ebd3854735925c57743d" -dependencies = [ - "serde_json", -] - [[package]] name = "kqueue" version = "1.0.7" @@ -879,6 +956,79 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lexical" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" +dependencies = [ + "lexical-core", +] + +[[package]] +name = "lexical-core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" +dependencies = [ + "lexical-parse-integer", + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-parse-integer" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" +dependencies = [ + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-util" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lexical-write-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" +dependencies = [ + "lexical-util", + "lexical-write-integer", + "static_assertions", +] + +[[package]] +name = "lexical-write-integer" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" +dependencies = [ + "lexical-util", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.139" @@ -926,7 +1076,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -1010,7 +1160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49ac8112fe5998579b22e29903c7b277fc7f91c7860c0236f35792caf8156e18" dependencies = [ "anyhow", - "bitflags 2.2.1", + "bitflags 2.3.3", "ctor", "napi-derive", "napi-sys", @@ -1062,6 +1212,12 @@ dependencies = [ "libloading", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + [[package]] name = "nibble_vec" version = "0.1.0" @@ -1129,6 +1285,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1171,13 +1349,17 @@ dependencies = [ "ignore", "ignore-files", "itertools", - "jsonc-parser", "napi", "napi-build", "napi-derive", + "once_cell", "rayon", - "serde", - "serde_json", + "regex", + "swc_common", + "swc_ecma_ast", + "swc_ecma_dep_graph", + "swc_ecma_parser", + "swc_ecma_visit", "thiserror", "tokio", "tracing", @@ -1192,9 +1374,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "overload" @@ -1225,13 +1407,19 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + [[package]] name = "phf" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ - "phf_shared", + "phf_shared 0.11.1", ] [[package]] @@ -1240,8 +1428,18 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.1", + "phf_shared 0.11.1", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", ] [[package]] @@ -1250,10 +1448,19 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ - "phf_shared", + "phf_shared 0.11.1", "rand", ] +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "phf_shared" version = "0.11.1" @@ -1275,6 +1482,29 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pmutil" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "predicates" version = "2.1.5" @@ -1322,6 +1552,15 @@ dependencies = [ "tokio-stream", ] +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + [[package]] name = "quote" version = "1.0.27" @@ -1347,6 +1586,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -1355,6 +1606,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "rayon" @@ -1409,13 +1663,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.2", "memchr", - "regex-syntax", + "regex-automata 0.3.3", + "regex-syntax 0.7.4", ] [[package]] @@ -1424,7 +1679,18 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.28", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick 1.0.2", + "memchr", + "regex-syntax 0.7.4", ] [[package]] @@ -1433,6 +1699,18 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.37.3" @@ -1447,12 +1725,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - [[package]] name = "same-file" version = "1.0.6" @@ -1462,6 +1734,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1494,17 +1772,6 @@ dependencies = [ "syn 1.0.107", ] -[[package]] -name = "serde_json" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" -dependencies = [ - "itoa", - "ryu", - "serde", -] - [[package]] name = "sha1_smol" version = "1.0.0" @@ -1550,12 +1817,232 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "string_enum" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fa4d4f81d7c05b9161f8de839975d3326328b8ba2831164b465524cc2f55252" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.15", +] + +[[package]] +name = "swc_atoms" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b1370fa1d31e18a999928aaf18f166616b16c5cb7033ced7d50d06858c5fd90" +dependencies = [ + "once_cell", + "rustc-hash", + "serde", + "string_cache", + "string_cache_codegen", + "triomphe", +] + +[[package]] +name = "swc_common" +version = "0.31.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6414bd4e553f5638961d39b07075ffd37a3d63176829592f4a5900260d94ca1" +dependencies = [ + "ahash", + "ast_node", + "better_scoped_tls", + "cfg-if", + "either", + "from_variant", + "new_debug_unreachable", + "num-bigint", + "once_cell", + "rustc-hash", + "serde", + "siphasher", + "string_cache", + "swc_atoms", + "swc_eq_ignore_macros", + "swc_visit", + "tracing", + "unicode-width", + "url", +] + +[[package]] +name = "swc_ecma_ast" +version = "0.107.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5693558188efdd5b664e517b69ba8056a7f64c214ca8cd034e3ae8314566b866" +dependencies = [ + "bitflags 2.3.3", + "is-macro", + "num-bigint", + "scoped-tls", + "string_enum", + "swc_atoms", + "swc_common", + "unicode-id", +] + +[[package]] +name = "swc_ecma_dep_graph" +version = "0.109.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4535c2a8210bf69f78201f93e6dc741a81046d1c04479e41d26849155752d184" +dependencies = [ + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_parser" +version = "0.137.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1915adb15d9ca1695e76d41524beb4806e9b603280edb7eedbaebe706a41c" +dependencies = [ + "either", + "lexical", + "num-bigint", + "serde", + "smallvec", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "tracing", + "typed-arena", +] + +[[package]] +name = "swc_ecma_visit" +version = "0.93.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82bb87ee3345a7049efcbedc419f121933e0e3967457922848d0026fb3b79dac" +dependencies = [ + "num-bigint", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_visit", + "tracing", +] + +[[package]] +name = "swc_eq_ignore_macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05a95d367e228d52484c53336991fdcf47b6b553ef835d9159db4ba40efb0ee8" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "swc_macros_common" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a273205ccb09b51fabe88c49f3b34c5a4631c4c00a16ae20e03111d6a42e832" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "swc_visit" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87c337fbb2d191bf371173dea6a957f01899adb8f189c6c31b122a6cfc98fc3" +dependencies = [ + "either", + "swc_visit_macros", +] + +[[package]] +name = "swc_visit_macros" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f322730fb82f3930a450ac24de8c98523af7d34ab8cb2f46bcb405839891a99" +dependencies = [ + "Inflector", + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.15", +] + [[package]] name = "syn" version = "1.0.107" @@ -1668,6 +2155,21 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.28.2" @@ -1770,18 +2272,55 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "triomphe" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +dependencies = [ + "serde", + "stable_deref_trait", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-bom" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" +[[package]] +name = "unicode-id" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" + [[package]] name = "unicode-ident" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.10.0" @@ -1794,6 +2333,17 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/community/approved-plugins.json b/community/approved-plugins.json index bc3bb45fd1aa5..548d8c90a1ec3 100644 --- a/community/approved-plugins.json +++ b/community/approved-plugins.json @@ -39,6 +39,11 @@ "description": "An nx plugin for the aws-cdk v2.", "url": "https://github.com/adrian-goe/nx-aws-cdk-v2" }, + { + "name": "@berenddeboer/nx-sst", + "description": "Nx plugin to generate an SST stack and execute all SST commands.", + "url": "https://github.com/berenddeboer/nx-plugins/tree/main/packages/nx-sst" + }, { "name": "@rxap/plugin-localazy", "description": "An Nx plugin for localazy.com upload and download tasks.", diff --git a/docs/README.md b/docs/README.md index eb07a366c0a85..2597cf13f0d81 100644 --- a/docs/README.md +++ b/docs/README.md @@ -67,6 +67,16 @@ You can add specific languages and a filename on the code snippet displayed. ‎``` ```` +#### Terminal command + +To display a terminal command, use: + +```` +‎```shell +‎ npx nx build +‎``` +```` + #### Terminal Output You can display your terminal output with a dedicated component the same way you would show code. @@ -85,6 +95,14 @@ You can optionally also pass a `path` like ‎``` ```` +#### Terminal Video Output + +You can have a more dynamic visualization of a terminal output by using the following component: + +``` +{% terminal-video src="/documentation/shared/images/caching/cache-terminal-animation.mp4" /%} +``` + #### Custom iframes We can display a special iframe and setting its width inside the document. @@ -111,7 +129,7 @@ We can display a special button inviting the reader to go to a GitHub repository You can add an "open in stackblitz" button as follows: ```markdown -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/standalone-angular-app?file=README.md" /%} +{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/angular-standalone?file=README.md" /%} ``` #### Install Nx Console @@ -170,6 +188,14 @@ title="Nx Console Run UI Form" width="100%" /%} ``` +#### Youtube Section Link + +Have a more decent button-like widget that you can place below sections of a tutorial with a link to a specific point in a Youtube video. + +```markdown +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=64" /%} +``` + #### Graph Embed an Nx Graph visualization that can be panned by the user. diff --git a/docs/changelog/15_3_0.md b/docs/changelog/15_3_0.md index d62665e75a795..e691b69aae74c 100644 --- a/docs/changelog/15_3_0.md +++ b/docs/changelog/15_3_0.md @@ -5,7 +5,7 @@ {% youtube src="https://www.youtube.com/embed/KBFQZw5ynFs" title="What's new in Nx 15.3?" -width="100%" /%} +/%} Here are some of our feature highlights: {% cards cols="2" %} diff --git a/docs/changelog/15_4_0.md b/docs/changelog/15_4_0.md index db59088b01693..e7ab69cdd3a49 100644 --- a/docs/changelog/15_4_0.md +++ b/docs/changelog/15_4_0.md @@ -5,7 +5,8 @@ {% youtube src="https://www.youtube.com/embed/G02THNy3PcE" title="Nx 15.4 is out! Here's all you need to know" -width="100%" /%} +/%} + Here are some of our feature highlights: {% cards cols="2" %} diff --git a/docs/changelog/15_7_0.md b/docs/changelog/15_7_0.md index 720965cb2abca..d0df24e9eb2e1 100644 --- a/docs/changelog/15_7_0.md +++ b/docs/changelog/15_7_0.md @@ -5,7 +5,8 @@ {% youtube src="https://www.youtube.com/embed/IStJODzZSoc" title="What's new in Nx 15.7?" -width="100%" /%} +/%} + Here are some of our feature highlights: {% cards cols="2" %} diff --git a/docs/changelog/15_8_0.md b/docs/changelog/15_8_0.md index eb0ed76961be5..1a27559eefde8 100644 --- a/docs/changelog/15_8_0.md +++ b/docs/changelog/15_8_0.md @@ -5,7 +5,8 @@ {% youtube src="https://www.youtube.com/embed/4XdHT5Y7zj4" title="Nx 15.8 - All you need to know!" -width="100%" /%} +/%} + Here are some of our feature highlights: {% cards cols="2" %} diff --git a/docs/changelog/16_0_0.md b/docs/changelog/16_0_0.md index 774164b11d7ae..ace3ea80aceff 100644 --- a/docs/changelog/16_0_0.md +++ b/docs/changelog/16_0_0.md @@ -5,7 +5,8 @@ We’re proud to announce the release of Nx version 16! {% youtube src="https://www.youtube.com/embed/JIhOyJtuxEA" title="Nx 16.0 Release" -width="100%" /%} +/%} + Here are some of our feature highlights: {% cards cols="2" %} diff --git a/docs/changelog/16_5_0.md b/docs/changelog/16_5_0.md new file mode 100644 index 0000000000000..bb086e2e5b9c4 --- /dev/null +++ b/docs/changelog/16_5_0.md @@ -0,0 +1,17 @@ +# Nx 16.5 + +[Read the 16.5 release blog post](https://blog.nrwl.io/nx-16-5-release-7887a27cb5) + +{% youtube +src="https://www.youtube.com/embed/7XLoLOc3afY" +title="Nx 16.5 Release!!!!" +/%} + +Feature highlights: + +{% cards cols="2" %} +{% card title="Targeting Tasks by Tags" type="video" url="https://youtu.be/enQDQmFquGU" /%} +{% card title="Nx Verdaccio Support" type="video" url="https://youtu.be/t1c925TzrzE" /%} +{% card title="externalDependencies Input Type" type="video" url="https://youtu.be/FRqgWBmHmAU" /%} +{% card title="Nx Console Revamped" type="video" url="https://youtu.be/p455D4W7330" /%} +{% /cards %} diff --git a/docs/generated/cli/show.md b/docs/generated/cli/show.md index 7e293151ed8f5..0c22a989345c8 100644 --- a/docs/generated/cli/show.md +++ b/docs/generated/cli/show.md @@ -159,7 +159,7 @@ Show only projects that have a specific target ### project -Show a list of targets in the workspace. +Shows resolved project configuration for a given project. ```shell nx show project @@ -177,7 +177,7 @@ Show help Type: `string` -Show targets for the given project +Which project should be viewed? ##### version diff --git a/docs/generated/devkit/nx_devkit.md b/docs/generated/devkit/nx_devkit.md index 463df7413aef4..d288ca40288b7 100644 --- a/docs/generated/devkit/nx_devkit.md +++ b/docs/generated/devkit/nx_devkit.md @@ -1397,7 +1397,7 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); ### getPackageManagerVersion -▸ **getPackageManagerVersion**(`packageManager?`): `string` +▸ **getPackageManagerVersion**(`packageManager?`, `cwd?`): `string` Returns the version of the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1408,6 +1408,7 @@ but it can also be passed in explicitly. | Name | Type | | :--------------- | :------------------------------------------------------------------ | | `packageManager` | [`PackageManager`](../../devkit/documents/nx_devkit#packagemanager) | +| `cwd` | `string` | #### Returns diff --git a/docs/generated/manifests/cloud.json b/docs/generated/manifests/cloud.json index 7640ebc9a28cb..2c4a81f9ef7ce 100644 --- a/docs/generated/manifests/cloud.json +++ b/docs/generated/manifests/cloud.json @@ -234,8 +234,8 @@ }, "/nx-cloud/private-cloud": { "id": "private-cloud", - "name": "On Prem", - "description": "Learn about Nx Cloud On Premise, dedicated Nx Cloud application hosted on your server, in your network with total private access.", + "name": "Enterprise + On Prem", + "description": "Learn about Nx Cloud Enterprise + On-Prem.", "file": "", "itemList": [ { @@ -268,6 +268,16 @@ "path": "/nx-cloud/private-cloud/auth-github", "tags": [] }, + { + "id": "ami-setup", + "name": "On-Prem VM Setup", + "description": "", + "file": "nx-cloud/private/ami-setup", + "itemList": [], + "isExternal": false, + "path": "/nx-cloud/private-cloud/ami-setup", + "tags": [] + }, { "id": "auth-gitlab", "name": "Authenticate with GitLab", @@ -307,26 +317,6 @@ "isExternal": false, "path": "/nx-cloud/private-cloud/advanced-config", "tags": [] - }, - { - "id": "kubernetes-setup", - "name": "Kubernetes Setup", - "description": "", - "file": "nx-cloud/private/kubernetes-setup", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "tags": [] - }, - { - "id": "standalone", - "name": "Standalone", - "description": "", - "file": "nx-cloud/private/standalone", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/standalone", - "tags": [] } ], "isExternal": false, @@ -363,6 +353,16 @@ "path": "/nx-cloud/private-cloud/auth-github", "tags": [] }, + "/nx-cloud/private-cloud/ami-setup": { + "id": "ami-setup", + "name": "On-Prem VM Setup", + "description": "", + "file": "nx-cloud/private/ami-setup", + "itemList": [], + "isExternal": false, + "path": "/nx-cloud/private-cloud/ami-setup", + "tags": [] + }, "/nx-cloud/private-cloud/auth-gitlab": { "id": "auth-gitlab", "name": "Authenticate with GitLab", @@ -403,26 +403,6 @@ "path": "/nx-cloud/private-cloud/advanced-config", "tags": [] }, - "/nx-cloud/private-cloud/kubernetes-setup": { - "id": "kubernetes-setup", - "name": "Kubernetes Setup", - "description": "", - "file": "nx-cloud/private/kubernetes-setup", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "tags": [] - }, - "/nx-cloud/private-cloud/standalone": { - "id": "standalone", - "name": "Standalone", - "description": "", - "file": "nx-cloud/private/standalone", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/standalone", - "tags": [] - }, "/nx-cloud/reference": { "id": "reference", "name": "Reference", diff --git a/docs/generated/manifests/plugins.json b/docs/generated/manifests/extending-nx.json similarity index 75% rename from docs/generated/manifests/plugins.json rename to docs/generated/manifests/extending-nx.json index b64378ab90b1d..99489bc16055e 100644 --- a/docs/generated/manifests/plugins.json +++ b/docs/generated/manifests/extending-nx.json @@ -1,5 +1,5 @@ { - "/plugins/intro": { + "/extending-nx/intro": { "id": "intro", "name": "Intro", "description": "Learn about plugins.", @@ -12,7 +12,7 @@ "file": "shared/plugins/intro", "itemList": [], "isExternal": false, - "path": "/plugins/intro/getting-started", + "path": "/extending-nx/intro/getting-started", "tags": [] }, { @@ -22,35 +22,35 @@ "file": "", "itemList": [], "isExternal": false, - "path": "/plugins/registry", + "path": "/extending-nx/registry", "tags": [] } ], "isExternal": false, - "path": "/plugins/intro", + "path": "/extending-nx/intro", "tags": [] }, - "/plugins/intro/getting-started": { + "/extending-nx/intro/getting-started": { "id": "getting-started", "name": "Getting Started with Plugins", "description": "Learn how to extend Nx by creating and releasing your own Nx plugin.", "file": "shared/plugins/intro", "itemList": [], "isExternal": false, - "path": "/plugins/intro/getting-started", + "path": "/extending-nx/intro/getting-started", "tags": [] }, - "/plugins/registry": { + "/extending-nx/registry": { "id": "registry", "name": "Plugin Registry", "description": "Browse official and community plugins", "file": "", "itemList": [], "isExternal": false, - "path": "/plugins/registry", + "path": "/extending-nx/registry", "tags": [] }, - "/plugins/tutorials": { + "/extending-nx/tutorials": { "id": "tutorials", "name": "5 Min Tutorials", "description": "Get started with plugins", @@ -63,7 +63,7 @@ "file": "shared/plugins/create-plugin", "itemList": [], "isExternal": false, - "path": "/plugins/tutorials/create-plugin", + "path": "/extending-nx/tutorials/create-plugin", "tags": [] }, { @@ -73,35 +73,35 @@ "file": "shared/plugins/maintain-published-plugin", "itemList": [], "isExternal": false, - "path": "/plugins/tutorials/publish-plugin", + "path": "/extending-nx/tutorials/publish-plugin", "tags": [] } ], "isExternal": false, - "path": "/plugins/tutorials", + "path": "/extending-nx/tutorials", "tags": [] }, - "/plugins/tutorials/create-plugin": { + "/extending-nx/tutorials/create-plugin": { "id": "create-plugin", "name": "Create a Local Plugin", "description": "", "file": "shared/plugins/create-plugin", "itemList": [], "isExternal": false, - "path": "/plugins/tutorials/create-plugin", + "path": "/extending-nx/tutorials/create-plugin", "tags": [] }, - "/plugins/tutorials/publish-plugin": { + "/extending-nx/tutorials/publish-plugin": { "id": "publish-plugin", "name": "Maintain a Published Plugin", "description": "", "file": "shared/plugins/maintain-published-plugin", "itemList": [], "isExternal": false, - "path": "/plugins/tutorials/publish-plugin", + "path": "/extending-nx/tutorials/publish-plugin", "tags": [] }, - "/plugins/recipes": { + "/extending-nx/recipes": { "id": "recipes", "name": "Recipes", "description": "Focused instructions to complete a specific task", @@ -114,7 +114,7 @@ "file": "shared/recipes/plugins/local-executors", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/local-executors", + "path": "/extending-nx/recipes/local-executors", "tags": ["use-task-executors"] }, { @@ -124,7 +124,7 @@ "file": "shared/recipes/plugins/compose-executors", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/compose-executors", + "path": "/extending-nx/recipes/compose-executors", "tags": ["use-task-executors"] }, { @@ -134,7 +134,7 @@ "file": "shared/recipes/generators/local-generators", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/local-generators", + "path": "/extending-nx/recipes/local-generators", "tags": ["use-code-generators"] }, { @@ -144,7 +144,7 @@ "file": "shared/recipes/generators/composing-generators", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/composing-generators", + "path": "/extending-nx/recipes/composing-generators", "tags": ["use-code-generators"] }, { @@ -154,7 +154,7 @@ "file": "shared/recipes/generators/generator-options", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/generator-options", + "path": "/extending-nx/recipes/generator-options", "tags": ["use-code-generators"] }, { @@ -164,7 +164,7 @@ "file": "shared/recipes/generators/creating-files", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/creating-files", + "path": "/extending-nx/recipes/creating-files", "tags": ["use-code-generators"] }, { @@ -174,7 +174,7 @@ "file": "shared/recipes/generators/modifying-files", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/modifying-files", + "path": "/extending-nx/recipes/modifying-files", "tags": ["use-code-generators"] }, { @@ -184,7 +184,7 @@ "file": "shared/recipes/plugins/migration-generators", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/migration-generators", + "path": "/extending-nx/recipes/migration-generators", "tags": ["create-your-own-plugin"] }, { @@ -194,7 +194,7 @@ "file": "shared/recipes/plugins/create-preset", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/create-preset", + "path": "/extending-nx/recipes/create-preset", "tags": ["create-your-own-plugin"] }, { @@ -204,7 +204,7 @@ "file": "shared/recipes/plugins/project-graph-plugins", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/project-graph-plugins", + "path": "/extending-nx/recipes/project-graph-plugins", "tags": ["create-your-own-plugin", "explore-graph"] }, { @@ -214,122 +214,122 @@ "file": "shared/recipes/plugins/project-inference-plugins", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/project-inference-plugins", + "path": "/extending-nx/recipes/project-inference-plugins", "tags": ["create-your-own-plugin"] } ], "isExternal": false, - "path": "/plugins/recipes", + "path": "/extending-nx/recipes", "tags": [] }, - "/plugins/recipes/local-executors": { + "/extending-nx/recipes/local-executors": { "id": "local-executors", "name": "Write a Simple Executor", "description": "", "file": "shared/recipes/plugins/local-executors", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/local-executors", + "path": "/extending-nx/recipes/local-executors", "tags": ["use-task-executors"] }, - "/plugins/recipes/compose-executors": { + "/extending-nx/recipes/compose-executors": { "id": "compose-executors", "name": "Compose Executors", "description": "", "file": "shared/recipes/plugins/compose-executors", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/compose-executors", + "path": "/extending-nx/recipes/compose-executors", "tags": ["use-task-executors"] }, - "/plugins/recipes/local-generators": { + "/extending-nx/recipes/local-generators": { "id": "local-generators", "name": "Write a Simple Generator", "description": "", "file": "shared/recipes/generators/local-generators", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/local-generators", + "path": "/extending-nx/recipes/local-generators", "tags": ["use-code-generators"] }, - "/plugins/recipes/composing-generators": { + "/extending-nx/recipes/composing-generators": { "id": "composing-generators", "name": "Compose Generators", "description": "", "file": "shared/recipes/generators/composing-generators", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/composing-generators", + "path": "/extending-nx/recipes/composing-generators", "tags": ["use-code-generators"] }, - "/plugins/recipes/generator-options": { + "/extending-nx/recipes/generator-options": { "id": "generator-options", "name": "Provide Options for Generators", "description": "", "file": "shared/recipes/generators/generator-options", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/generator-options", + "path": "/extending-nx/recipes/generator-options", "tags": ["use-code-generators"] }, - "/plugins/recipes/creating-files": { + "/extending-nx/recipes/creating-files": { "id": "creating-files", "name": "Create Files", "description": "", "file": "shared/recipes/generators/creating-files", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/creating-files", + "path": "/extending-nx/recipes/creating-files", "tags": ["use-code-generators"] }, - "/plugins/recipes/modifying-files": { + "/extending-nx/recipes/modifying-files": { "id": "modifying-files", "name": "Modify Files", "description": "", "file": "shared/recipes/generators/modifying-files", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/modifying-files", + "path": "/extending-nx/recipes/modifying-files", "tags": ["use-code-generators"] }, - "/plugins/recipes/migration-generators": { + "/extending-nx/recipes/migration-generators": { "id": "migration-generators", "name": "Write a Migration", "description": "", "file": "shared/recipes/plugins/migration-generators", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/migration-generators", + "path": "/extending-nx/recipes/migration-generators", "tags": ["create-your-own-plugin"] }, - "/plugins/recipes/create-preset": { + "/extending-nx/recipes/create-preset": { "id": "create-preset", "name": "Create a Preset", "description": "", "file": "shared/recipes/plugins/create-preset", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/create-preset", + "path": "/extending-nx/recipes/create-preset", "tags": ["create-your-own-plugin"] }, - "/plugins/recipes/project-graph-plugins": { + "/extending-nx/recipes/project-graph-plugins": { "id": "project-graph-plugins", "name": "Modify the Project Graph", "description": "", "file": "shared/recipes/plugins/project-graph-plugins", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/project-graph-plugins", + "path": "/extending-nx/recipes/project-graph-plugins", "tags": ["create-your-own-plugin", "explore-graph"] }, - "/plugins/recipes/project-inference-plugins": { + "/extending-nx/recipes/project-inference-plugins": { "id": "project-inference-plugins", "name": "Identify Custom Projects", "description": "", "file": "shared/recipes/plugins/project-inference-plugins", "itemList": [], "isExternal": false, - "path": "/plugins/recipes/project-inference-plugins", + "path": "/extending-nx/recipes/project-inference-plugins", "tags": ["create-your-own-plugin"] } } diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index ccf379a5e7492..34a383b4bf76a 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -786,9 +786,17 @@ "disableCollapsible": false }, { - "name": "Share Your Cache", - "path": "/core-features/share-your-cache", - "id": "share-your-cache", + "name": "Use Remote Caching", + "path": "/core-features/remote-cache", + "id": "remote-cache", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Distribute Task Execution", + "path": "/core-features/distribute-task-execution", + "id": "distribute-task-execution", "isExternal": false, "children": [], "disableCollapsible": false @@ -802,35 +810,52 @@ "disableCollapsible": false }, { - "name": "Distribute Task Execution", - "path": "/core-features/distribute-task-execution", - "id": "distribute-task-execution", + "name": "Automate Updating Dependencies", + "path": "/core-features/automate-updating-dependencies", + "id": "automate-updating-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Integrate with Editors", - "path": "/core-features/integrate-with-editors", - "id": "integrate-with-editors", + "name": "Enforce Module Boundaries", + "path": "/core-features/enforce-module-boundaries", + "id": "enforce-module-boundaries", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Automate Updating Dependencies", - "path": "/core-features/automate-updating-dependencies", - "id": "automate-updating-dependencies", + "name": "Integrate with Editors", + "path": "/core-features/integrate-with-editors", + "id": "integrate-with-editors", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Enforce Project Boundaries", - "path": "/core-features/enforce-project-boundaries", - "id": "enforce-project-boundaries", + "name": "Plugin Features", + "path": "/core-features/plugin-features", + "id": "plugin-features", "isExternal": false, - "children": [], + "children": [ + { + "name": "Use Task Executors", + "path": "/core-features/plugin-features/use-task-executors", + "id": "use-task-executors", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use Code Generators", + "path": "/core-features/plugin-features/use-code-generators", + "id": "use-code-generators", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false } ], @@ -853,17 +878,9 @@ "disableCollapsible": false }, { - "name": "Share Your Cache", - "path": "/core-features/share-your-cache", - "id": "share-your-cache", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Explore the Graph", - "path": "/core-features/explore-graph", - "id": "explore-graph", + "name": "Use Remote Caching", + "path": "/core-features/remote-cache", + "id": "remote-cache", "isExternal": false, "children": [], "disableCollapsible": false @@ -877,9 +894,9 @@ "disableCollapsible": false }, { - "name": "Integrate with Editors", - "path": "/core-features/integrate-with-editors", - "id": "integrate-with-editors", + "name": "Explore the Graph", + "path": "/core-features/explore-graph", + "id": "explore-graph", "isExternal": false, "children": [], "disableCollapsible": false @@ -893,22 +910,30 @@ "disableCollapsible": false }, { - "name": "Enforce Project Boundaries", - "path": "/core-features/enforce-project-boundaries", - "id": "enforce-project-boundaries", + "name": "Enforce Module Boundaries", + "path": "/core-features/enforce-module-boundaries", + "id": "enforce-module-boundaries", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Integrate with Editors", + "path": "/core-features/integrate-with-editors", + "id": "integrate-with-editors", "isExternal": false, "children": [], "disableCollapsible": false }, { "name": "Plugin Features", - "path": "/plugin-features", + "path": "/core-features/plugin-features", "id": "plugin-features", "isExternal": false, "children": [ { "name": "Use Task Executors", - "path": "/plugin-features/use-task-executors", + "path": "/core-features/plugin-features/use-task-executors", "id": "use-task-executors", "isExternal": false, "children": [], @@ -916,7 +941,7 @@ }, { "name": "Use Code Generators", - "path": "/plugin-features/use-code-generators", + "path": "/core-features/plugin-features/use-code-generators", "id": "use-code-generators", "isExternal": false, "children": [], @@ -927,7 +952,7 @@ }, { "name": "Use Task Executors", - "path": "/plugin-features/use-task-executors", + "path": "/core-features/plugin-features/use-task-executors", "id": "use-task-executors", "isExternal": false, "children": [], @@ -935,7 +960,7 @@ }, { "name": "Use Code Generators", - "path": "/plugin-features/use-code-generators", + "path": "/core-features/plugin-features/use-code-generators", "id": "use-code-generators", "isExternal": false, "children": [], @@ -996,11 +1021,188 @@ "disableCollapsible": false }, { - "name": "More Concept Guides »", - "path": "/more-concepts", - "id": "more-concept-guides", + "name": "More Concepts", + "path": "/concepts/more-concepts", + "id": "more-concepts", "isExternal": false, - "children": [], + "children": [ + { + "name": "Customizing Inputs", + "path": "/concepts/more-concepts/customizing-inputs", + "id": "customizing-inputs", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Incremental Builds", + "path": "/concepts/more-concepts/incremental-builds", + "id": "incremental-builds", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Illustrated Distributed Task Execution", + "path": "/concepts/more-concepts/illustrated-dte", + "id": "illustrated-dte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx and Turborepo", + "path": "/concepts/more-concepts/turbo-and-nx", + "id": "turbo-and-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Monorepos", + "path": "/concepts/more-concepts/why-monorepos", + "id": "why-monorepos", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Dependency Management", + "path": "/concepts/more-concepts/dependency-management", + "id": "dependency-management", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Code Sharing", + "path": "/concepts/more-concepts/code-sharing", + "id": "code-sharing", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Nx at Enterprises", + "path": "/concepts/more-concepts/monorepo-nx-enterprise", + "id": "monorepo-nx-enterprise", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Daemon", + "path": "/concepts/more-concepts/nx-daemon", + "id": "nx-daemon", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx and the Angular CLI", + "path": "/concepts/more-concepts/nx-and-angular", + "id": "nx-and-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Folder Structure", + "path": "/concepts/more-concepts/folder-structure", + "id": "folder-structure", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Devkit and Angular Devkit", + "path": "/concepts/more-concepts/nx-devkit-angular-devkit", + "id": "nx-devkit-angular-devkit", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Micro Frontend Architecture", + "path": "/concepts/more-concepts/micro-frontend-architecture", + "id": "micro-frontend-architecture", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "id": "faster-builds-with-module-federation", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Applications and Libraries", + "path": "/concepts/more-concepts/applications-and-libraries", + "id": "applications-and-libraries", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Creating Libraries", + "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, + "children": [], + "disableCollapsible": false + }, + { + "name": "How the Project Graph is Built", + "path": "/concepts/more-concepts/how-project-graph-is-built", + "id": "how-project-graph-is-built", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx and the Nx Wrapper", + "path": "/concepts/more-concepts/nx-and-the-wrapper", + "id": "nx-and-the-wrapper", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Managing your Global Nx Installation", + "path": "/concepts/more-concepts/global-nx", + "id": "global-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false } ], @@ -1056,13 +1258,13 @@ }, { "name": "More Concepts", - "path": "/more-concepts", + "path": "/concepts/more-concepts", "id": "more-concepts", "isExternal": false, "children": [ { "name": "Customizing Inputs", - "path": "/more-concepts/customizing-inputs", + "path": "/concepts/more-concepts/customizing-inputs", "id": "customizing-inputs", "isExternal": false, "children": [], @@ -1070,7 +1272,7 @@ }, { "name": "Incremental Builds", - "path": "/more-concepts/incremental-builds", + "path": "/concepts/more-concepts/incremental-builds", "id": "incremental-builds", "isExternal": false, "children": [], @@ -1078,7 +1280,7 @@ }, { "name": "Illustrated Distributed Task Execution", - "path": "/more-concepts/illustrated-dte", + "path": "/concepts/more-concepts/illustrated-dte", "id": "illustrated-dte", "isExternal": false, "children": [], @@ -1086,7 +1288,7 @@ }, { "name": "Nx and Turborepo", - "path": "/more-concepts/turbo-and-nx", + "path": "/concepts/more-concepts/turbo-and-nx", "id": "turbo-and-nx", "isExternal": false, "children": [], @@ -1094,7 +1296,7 @@ }, { "name": "Monorepos", - "path": "/more-concepts/why-monorepos", + "path": "/concepts/more-concepts/why-monorepos", "id": "why-monorepos", "isExternal": false, "children": [], @@ -1102,7 +1304,7 @@ }, { "name": "Dependency Management", - "path": "/more-concepts/dependency-management", + "path": "/concepts/more-concepts/dependency-management", "id": "dependency-management", "isExternal": false, "children": [], @@ -1110,7 +1312,7 @@ }, { "name": "Code Sharing", - "path": "/more-concepts/code-sharing", + "path": "/concepts/more-concepts/code-sharing", "id": "code-sharing", "isExternal": false, "children": [], @@ -1118,7 +1320,7 @@ }, { "name": "Using Nx at Enterprises", - "path": "/more-concepts/monorepo-nx-enterprise", + "path": "/concepts/more-concepts/monorepo-nx-enterprise", "id": "monorepo-nx-enterprise", "isExternal": false, "children": [], @@ -1126,7 +1328,7 @@ }, { "name": "Nx Daemon", - "path": "/more-concepts/nx-daemon", + "path": "/concepts/more-concepts/nx-daemon", "id": "nx-daemon", "isExternal": false, "children": [], @@ -1134,7 +1336,7 @@ }, { "name": "Nx and the Angular CLI", - "path": "/more-concepts/nx-and-angular", + "path": "/concepts/more-concepts/nx-and-angular", "id": "nx-and-angular", "isExternal": false, "children": [], @@ -1142,7 +1344,7 @@ }, { "name": "Folder Structure", - "path": "/more-concepts/folder-structure", + "path": "/concepts/more-concepts/folder-structure", "id": "folder-structure", "isExternal": false, "children": [], @@ -1150,7 +1352,7 @@ }, { "name": "Nx Devkit and Angular Devkit", - "path": "/more-concepts/nx-devkit-angular-devkit", + "path": "/concepts/more-concepts/nx-devkit-angular-devkit", "id": "nx-devkit-angular-devkit", "isExternal": false, "children": [], @@ -1158,15 +1360,23 @@ }, { "name": "Micro Frontend Architecture", - "path": "/more-concepts/micro-frontend-architecture", + "path": "/concepts/more-concepts/micro-frontend-architecture", "id": "micro-frontend-architecture", "isExternal": false, "children": [], "disableCollapsible": false }, + { + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "id": "faster-builds-with-module-federation", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Applications and Libraries", - "path": "/more-concepts/applications-and-libraries", + "path": "/concepts/more-concepts/applications-and-libraries", "id": "applications-and-libraries", "isExternal": false, "children": [], @@ -1174,7 +1384,7 @@ }, { "name": "Creating Libraries", - "path": "/more-concepts/creating-libraries", + "path": "/concepts/more-concepts/creating-libraries", "id": "creating-libraries", "isExternal": false, "children": [], @@ -1182,7 +1392,7 @@ }, { "name": "Library Types", - "path": "/more-concepts/library-types", + "path": "/concepts/more-concepts/library-types", "id": "library-types", "isExternal": false, "children": [], @@ -1190,7 +1400,7 @@ }, { "name": "Grouping Libraries", - "path": "/more-concepts/grouping-libraries", + "path": "/concepts/more-concepts/grouping-libraries", "id": "grouping-libraries", "isExternal": false, "children": [], @@ -1198,7 +1408,7 @@ }, { "name": "Buildable and Publishable Libraries", - "path": "/more-concepts/buildable-and-publishable-libraries", + "path": "/concepts/more-concepts/buildable-and-publishable-libraries", "id": "buildable-and-publishable-libraries", "isExternal": false, "children": [], @@ -1206,7 +1416,7 @@ }, { "name": "How the Project Graph is Built", - "path": "/more-concepts/how-project-graph-is-built", + "path": "/concepts/more-concepts/how-project-graph-is-built", "id": "how-project-graph-is-built", "isExternal": false, "children": [], @@ -1214,7 +1424,7 @@ }, { "name": "Nx and the Nx Wrapper", - "path": "/more-concepts/nx-and-the-wrapper", + "path": "/concepts/more-concepts/nx-and-the-wrapper", "id": "nx-and-the-wrapper", "isExternal": false, "children": [], @@ -1222,7 +1432,7 @@ }, { "name": "Managing your Global Nx Installation", - "path": "/more-concepts/global-nx", + "path": "/concepts/more-concepts/global-nx", "id": "global-nx", "isExternal": false, "children": [], @@ -1233,7 +1443,7 @@ }, { "name": "Customizing Inputs", - "path": "/more-concepts/customizing-inputs", + "path": "/concepts/more-concepts/customizing-inputs", "id": "customizing-inputs", "isExternal": false, "children": [], @@ -1241,7 +1451,7 @@ }, { "name": "Incremental Builds", - "path": "/more-concepts/incremental-builds", + "path": "/concepts/more-concepts/incremental-builds", "id": "incremental-builds", "isExternal": false, "children": [], @@ -1249,7 +1459,7 @@ }, { "name": "Illustrated Distributed Task Execution", - "path": "/more-concepts/illustrated-dte", + "path": "/concepts/more-concepts/illustrated-dte", "id": "illustrated-dte", "isExternal": false, "children": [], @@ -1257,7 +1467,7 @@ }, { "name": "Nx and Turborepo", - "path": "/more-concepts/turbo-and-nx", + "path": "/concepts/more-concepts/turbo-and-nx", "id": "turbo-and-nx", "isExternal": false, "children": [], @@ -1265,7 +1475,7 @@ }, { "name": "Monorepos", - "path": "/more-concepts/why-monorepos", + "path": "/concepts/more-concepts/why-monorepos", "id": "why-monorepos", "isExternal": false, "children": [], @@ -1273,7 +1483,7 @@ }, { "name": "Dependency Management", - "path": "/more-concepts/dependency-management", + "path": "/concepts/more-concepts/dependency-management", "id": "dependency-management", "isExternal": false, "children": [], @@ -1281,7 +1491,7 @@ }, { "name": "Code Sharing", - "path": "/more-concepts/code-sharing", + "path": "/concepts/more-concepts/code-sharing", "id": "code-sharing", "isExternal": false, "children": [], @@ -1289,7 +1499,7 @@ }, { "name": "Using Nx at Enterprises", - "path": "/more-concepts/monorepo-nx-enterprise", + "path": "/concepts/more-concepts/monorepo-nx-enterprise", "id": "monorepo-nx-enterprise", "isExternal": false, "children": [], @@ -1297,7 +1507,7 @@ }, { "name": "Nx Daemon", - "path": "/more-concepts/nx-daemon", + "path": "/concepts/more-concepts/nx-daemon", "id": "nx-daemon", "isExternal": false, "children": [], @@ -1305,7 +1515,7 @@ }, { "name": "Nx and the Angular CLI", - "path": "/more-concepts/nx-and-angular", + "path": "/concepts/more-concepts/nx-and-angular", "id": "nx-and-angular", "isExternal": false, "children": [], @@ -1313,7 +1523,7 @@ }, { "name": "Folder Structure", - "path": "/more-concepts/folder-structure", + "path": "/concepts/more-concepts/folder-structure", "id": "folder-structure", "isExternal": false, "children": [], @@ -1321,7 +1531,7 @@ }, { "name": "Nx Devkit and Angular Devkit", - "path": "/more-concepts/nx-devkit-angular-devkit", + "path": "/concepts/more-concepts/nx-devkit-angular-devkit", "id": "nx-devkit-angular-devkit", "isExternal": false, "children": [], @@ -1329,15 +1539,23 @@ }, { "name": "Micro Frontend Architecture", - "path": "/more-concepts/micro-frontend-architecture", + "path": "/concepts/more-concepts/micro-frontend-architecture", "id": "micro-frontend-architecture", "isExternal": false, "children": [], "disableCollapsible": false }, + { + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "id": "faster-builds-with-module-federation", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Applications and Libraries", - "path": "/more-concepts/applications-and-libraries", + "path": "/concepts/more-concepts/applications-and-libraries", "id": "applications-and-libraries", "isExternal": false, "children": [], @@ -1345,7 +1563,7 @@ }, { "name": "Creating Libraries", - "path": "/more-concepts/creating-libraries", + "path": "/concepts/more-concepts/creating-libraries", "id": "creating-libraries", "isExternal": false, "children": [], @@ -1353,7 +1571,7 @@ }, { "name": "Library Types", - "path": "/more-concepts/library-types", + "path": "/concepts/more-concepts/library-types", "id": "library-types", "isExternal": false, "children": [], @@ -1361,7 +1579,7 @@ }, { "name": "Grouping Libraries", - "path": "/more-concepts/grouping-libraries", + "path": "/concepts/more-concepts/grouping-libraries", "id": "grouping-libraries", "isExternal": false, "children": [], @@ -1369,7 +1587,7 @@ }, { "name": "Buildable and Publishable Libraries", - "path": "/more-concepts/buildable-and-publishable-libraries", + "path": "/concepts/more-concepts/buildable-and-publishable-libraries", "id": "buildable-and-publishable-libraries", "isExternal": false, "children": [], @@ -1377,7 +1595,7 @@ }, { "name": "How the Project Graph is Built", - "path": "/more-concepts/how-project-graph-is-built", + "path": "/concepts/more-concepts/how-project-graph-is-built", "id": "how-project-graph-is-built", "isExternal": false, "children": [], @@ -1385,7 +1603,7 @@ }, { "name": "Nx and the Nx Wrapper", - "path": "/more-concepts/nx-and-the-wrapper", + "path": "/concepts/more-concepts/nx-and-the-wrapper", "id": "nx-and-the-wrapper", "isExternal": false, "children": [], @@ -1393,301 +1611,679 @@ }, { "name": "Managing your Global Nx Installation", - "path": "/more-concepts/global-nx", + "path": "/concepts/more-concepts/global-nx", "id": "global-nx", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "All Recipes »", + "name": "Recipes", "path": "/recipes", - "id": "all", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "CI Setup", - "path": "/recipes/ci/ci-setup", - "id": "ci-setup", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Adopting Nx", - "path": "/recipes/adopting-nx", - "id": "adopting-nx", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Reference", - "path": "/reference", - "id": "reference", + "id": "recipes", "isExternal": false, "children": [ { - "name": "Commands", - "path": "/reference/commands", - "id": "commands", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "nx.json", - "path": "/reference/nx-json", - "id": "nx-json", + "name": "Adopting Nx", + "path": "/recipes/adopting-nx", + "id": "adopting-nx", "isExternal": false, - "children": [], + "children": [ + { + "name": "NPM/Yarn/PNPM workspaces", + "path": "/recipes/adopting-nx/adding-to-monorepo", + "id": "adding-to-monorepo", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add to any Project", + "path": "/recipes/adopting-nx/adding-to-existing-project", + "id": "adding-to-existing-project", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx and Lerna", + "path": "/recipes/adopting-nx/lerna-and-nx", + "id": "lerna-and-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Preserving Git Histories", + "path": "/recipes/adopting-nx/preserving-git-histories", + "id": "preserving-git-histories", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Manual migration", + "path": "/recipes/adopting-nx/manual", + "id": "manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Project Configuration", - "path": "/reference/project-configuration", - "id": "project-configuration", + "name": "React", + "path": "/recipes/react", + "id": "react", "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": ".nxignore", - "path": "/reference/nxignore", - "id": "nxignore", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Environment Variables", - "path": "/reference/environment-variables", - "id": "environment-variables", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Packages", - "path": "/packages", - "id": "packages", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "Nx Devkit", - "path": "/packages/devkit/documents/nx_devkit", - "id": "packages-devkit", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "Glossary", - "path": "/reference/glossary", - "id": "glossary", - "isExternal": false, - "children": [], + "children": [ + { + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Changelog", - "path": "/reference/changelog", - "id": "changelog", - "isExternal": true, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Commands", - "path": "/reference/commands", - "id": "commands", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "nx.json", - "path": "/reference/nx-json", - "id": "nx-json", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Project Configuration", - "path": "/reference/project-configuration", - "id": "project-configuration", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": ".nxignore", - "path": "/reference/nxignore", - "id": "nxignore", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Environment Variables", - "path": "/reference/environment-variables", - "id": "environment-variables", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Packages", - "path": "/packages", - "id": "packages", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "Nx Devkit", - "path": "/packages/devkit/documents/nx_devkit", - "id": "packages-devkit", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "Glossary", - "path": "/reference/glossary", - "id": "glossary", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Changelog", - "path": "/reference/changelog", - "id": "changelog", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "Deprecated", - "path": "/deprecated", - "id": "deprecated", - "isExternal": false, - "children": [ - { - "name": "workspace.json", - "path": "/deprecated/workspace-json", - "id": "workspace-json", + "name": "Angular", + "path": "/recipes/angular", + "id": "angular", "isExternal": false, - "children": [], + "children": [ + { + "name": "Migration", + "path": "/recipes/angular/migration", + "id": "migration", + "isExternal": false, + "children": [ + { + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Tailwind CSS with Angular projects", + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "id": "using-tailwind-css-with-angular-projects", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "id": "dynamic-module-federation-with-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup incremental builds for Angular applications", + "path": "/recipes/angular/setup-incremental-builds-angular", + "id": "setup-incremental-builds-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "workspace-lint", - "path": "/deprecated/workspace-lint", - "id": "workspace-lint", + "name": "Node", + "path": "/recipes/node", + "id": "node", "isExternal": false, - "children": [], + "children": [ + { + "name": "Deploying a Node App to Fly.io", + "path": "/recipes/node/node-server-fly-io", + "id": "node-server-fly-io", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add and Deploy Netlify Edge Functions with Node", + "path": "/recipes/node/node-serverless-functions-netlify", + "id": "node-serverless-functions-netlify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying AWS lambda in Node.js", + "path": "/recipes/node/node-aws-lambda", + "id": "node-aws-lambda", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Workspace Generators", - "path": "/deprecated/workspace-generators", - "id": "workspace-generators", + "name": "Storybook", + "path": "/recipes/storybook", + "id": "storybook", "isExternal": false, - "children": [], + "children": [ + { + "name": "One main Storybook instance for all projects", + "path": "/recipes/storybook/one-storybook-for-all", + "id": "one-storybook-for-all", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "One Storybook instance per scope", + "path": "/recipes/storybook/one-storybook-per-scope", + "id": "one-storybook-per-scope", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "One main Storybook instance using Storybook Composition", + "path": "/recipes/storybook/one-storybook-with-composition", + "id": "one-storybook-with-composition", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Workspace Executors", - "path": "/deprecated/workspace-executors", - "id": "workspace-executors", + "name": "Enforce Module Boundaries", + "path": "/recipes/enforce-module-boundaries", + "id": "enforce-module-boundaries", "isExternal": false, - "children": [], + "children": [ + { + "name": "Ban Dependencies with Certain Tags", + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "id": "ban-dependencies-with-tags", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tag in Multiple Dimensions", + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "id": "tag-multiple-dimensions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Ban External Imports", + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "id": "ban-external-imports", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tags Allow List", + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "id": "tags-allow-list", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "defaultCollection", - "path": "/deprecated/default-collection", - "id": "default-collection", + "name": "CI", + "path": "/recipes/ci", + "id": "ci", "isExternal": false, - "children": [], + "children": [ + { + "name": "CI Setup", + "path": "/recipes/ci/ci-setup", + "id": "ci-setup", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Prepare applications for deployment via CI", + "path": "/recipes/ci/ci-deployment", + "id": "ci-deployment", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Azure Pipelines", + "path": "/recipes/ci/monorepo-ci-azure", + "id": "monorepo-ci-azure", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up CircleCI", + "path": "/recipes/ci/monorepo-ci-circle-ci", + "id": "monorepo-ci-circle-ci", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up GitHub Actions", + "path": "/recipes/ci/monorepo-ci-github-actions", + "id": "monorepo-ci-github-actions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Jenkins", + "path": "/recipes/ci/monorepo-ci-jenkins", + "id": "monorepo-ci-jenkins", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up GitLab", + "path": "/recipes/ci/monorepo-ci-gitlab", + "id": "monorepo-ci-gitlab", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Bitbucket", + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "id": "monorepo-ci-bitbucket-pipelines", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "runtimeCacheInputs", - "path": "/deprecated/runtime-cache-inputs", - "id": "runtime-cache-inputs", + "name": "Tips and tricks", + "path": "/recipes/tips-n-tricks", + "id": "tips-n-tricks", "isExternal": false, - "children": [], + "children": [ + { + "name": "Add a Package-based Project in an Integrated Repo", + "path": "/recipes/tips-n-tricks/package-based-in-integrated", + "id": "package-based-in-integrated", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add an Integrated Project in a Package-based Repo", + "path": "/recipes/tips-n-tricks/integrated-in-package-based", + "id": "integrated-in-package-based", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "globalImplicitDependencies", - "path": "/deprecated/global-implicit-dependencies", - "id": "global-implicit-dependencies", + "name": "Troubleshooting", + "path": "/recipes/troubleshooting", + "id": "troubleshooting", "isExternal": false, - "children": [], + "children": [ + { + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Troubleshooting Nx Install Issues", + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "id": "troubleshoot-nx-install-issues", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Unknown Local Cache Error", + "path": "/recipes/troubleshooting/unknown-local-cache", + "id": "unknown-local-cache", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling", + "id": "performance-profiling", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Storybook deprecated docs", - "path": "/deprecated/storybook", - "id": "storybook", + "name": "Nx Console", + "path": "/recipes/nx-console", + "id": "nx-console", "isExternal": false, "children": [ { - "name": "Angular: Information about the Storybook targets", - "path": "/deprecated/storybook/angular-storybook-targets", - "id": "angular-storybook-targets", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: The browserTarget", - "path": "/deprecated/storybook/angular-browser-target", - "id": "angular-browser-target", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Storybook Migration to webpackFinal", - "path": "/deprecated/storybook/migrate-webpack-final-angular", - "id": "migrate-webpack-final-angular", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-angular", - "id": "upgrade-storybook-v6-angular", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Storybook Migration to webpackFinal and the Nx Addon", - "path": "/deprecated/storybook/migrate-webpack-final-react", - "id": "migrate-webpack-final-react", + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-react", - "id": "upgrade-storybook-v6-react", + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Other", + "path": "/recipes/other", + "id": "other", + "isExternal": false, + "children": [ + { + "name": "Serverless deployment with Deno Deploy", + "path": "/recipes/other/deno-deploy", + "id": "deno-deploy", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add and Deploy Netlify Edge Functions with Deno", + "path": "/recipes/other/deno-netlify-functions", + "id": "deno-netlify-functions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Rescope Packages from @nrwl to @nx", + "path": "/recipes/other/rescope", + "id": "rescope", "isExternal": false, "children": [], "disableCollapsible": false @@ -1699,111 +2295,168 @@ "disableCollapsible": false }, { - "name": "workspace.json", - "path": "/deprecated/workspace-json", - "id": "workspace-json", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "workspace-lint", - "path": "/deprecated/workspace-lint", - "id": "workspace-lint", + "name": "Adopting Nx", + "path": "/recipes/adopting-nx", + "id": "adopting-nx", "isExternal": false, - "children": [], + "children": [ + { + "name": "NPM/Yarn/PNPM workspaces", + "path": "/recipes/adopting-nx/adding-to-monorepo", + "id": "adding-to-monorepo", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add to any Project", + "path": "/recipes/adopting-nx/adding-to-existing-project", + "id": "adding-to-existing-project", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx and Lerna", + "path": "/recipes/adopting-nx/lerna-and-nx", + "id": "lerna-and-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Preserving Git Histories", + "path": "/recipes/adopting-nx/preserving-git-histories", + "id": "preserving-git-histories", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Manual migration", + "path": "/recipes/adopting-nx/manual", + "id": "manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Workspace Generators", - "path": "/deprecated/workspace-generators", - "id": "workspace-generators", + "name": "NPM/Yarn/PNPM workspaces", + "path": "/recipes/adopting-nx/adding-to-monorepo", + "id": "adding-to-monorepo", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Executors", - "path": "/deprecated/workspace-executors", - "id": "workspace-executors", + "name": "Add to any Project", + "path": "/recipes/adopting-nx/adding-to-existing-project", + "id": "adding-to-existing-project", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "defaultCollection", - "path": "/deprecated/default-collection", - "id": "default-collection", + "name": "Nx and Lerna", + "path": "/recipes/adopting-nx/lerna-and-nx", + "id": "lerna-and-nx", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "runtimeCacheInputs", - "path": "/deprecated/runtime-cache-inputs", - "id": "runtime-cache-inputs", + "name": "Preserving Git Histories", + "path": "/recipes/adopting-nx/preserving-git-histories", + "id": "preserving-git-histories", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "globalImplicitDependencies", - "path": "/deprecated/global-implicit-dependencies", - "id": "global-implicit-dependencies", + "name": "Manual migration", + "path": "/recipes/adopting-nx/manual", + "id": "manual", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Storybook deprecated docs", - "path": "/deprecated/storybook", - "id": "storybook", + "name": "React", + "path": "/recipes/react", + "id": "react", "isExternal": false, "children": [ { - "name": "Angular: Information about the Storybook targets", - "path": "/deprecated/storybook/angular-storybook-targets", - "id": "angular-storybook-targets", + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: The browserTarget", - "path": "/deprecated/storybook/angular-browser-target", - "id": "angular-browser-target", + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Storybook Migration to webpackFinal", - "path": "/deprecated/storybook/migrate-webpack-final-angular", - "id": "migrate-webpack-final-angular", + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-angular", - "id": "upgrade-storybook-v6-angular", + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Storybook Migration to webpackFinal and the Nx Addon", - "path": "/deprecated/storybook/migrate-webpack-final-react", - "id": "migrate-webpack-final-react", + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-react", - "id": "upgrade-storybook-v6-react", + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", "isExternal": false, "children": [], "disableCollapsible": false @@ -1812,127 +2465,201 @@ "disableCollapsible": false }, { - "name": "Angular: Information about the Storybook targets", - "path": "/deprecated/storybook/angular-storybook-targets", - "id": "angular-storybook-targets", + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: The browserTarget", - "path": "/deprecated/storybook/angular-browser-target", - "id": "angular-browser-target", + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Storybook Migration to webpackFinal", - "path": "/deprecated/storybook/migrate-webpack-final-angular", - "id": "migrate-webpack-final-angular", + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-angular", - "id": "upgrade-storybook-v6-angular", + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Storybook Migration to webpackFinal and the Nx Addon", - "path": "/deprecated/storybook/migrate-webpack-final-react", - "id": "migrate-webpack-final-react", + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-react", - "id": "upgrade-storybook-v6-react", + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "See Also", - "path": "/see-also", - "id": "see-also", + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular", + "path": "/recipes/angular", + "id": "angular", "isExternal": false, "children": [ { - "name": "Nx Cloud Documentation", - "path": "/nx-cloud/intro/what-is-nx-cloud", - "id": "nx-cloud-documentation", - "isExternal": true, + "name": "Migration", + "path": "/recipes/angular/migration", + "id": "migration", + "isExternal": false, + "children": [ + { + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Cloud Main Site", - "path": "https://nx.app", - "id": "nx-cloud-main-site", - "isExternal": true, + "name": "Using Tailwind CSS with Angular projects", + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "id": "using-tailwind-css-with-angular-projects", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "--skip-nx-cache flag", - "path": "/packages/nx/documents/affected#skip-nx-cache", - "id": "skip-nx-cache-flag", - "isExternal": true, + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "tasks-runner-options property", - "path": "/reference/nx-json#tasks-runner-options", - "id": "tasks-runner-options-property", - "isExternal": true, + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "id": "dynamic-module-federation-with-angular", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json reference: inputs and namedInputs", - "path": "/reference/nx-json#inputs-&-namedinputs", - "id": "nxjson-inputs", - "isExternal": true, + "name": "Setup incremental builds for Angular applications", + "path": "/recipes/angular/setup-incremental-builds-angular", + "id": "setup-incremental-builds-angular", + "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Migration", + "path": "/recipes/angular/migration", + "id": "migration", + "isExternal": false, + "children": [ { - "name": "Project Configuration reference: inputs and namedInputs", - "path": "/reference/project-configuration#inputs-&-namedinputs", - "id": "project-config-inputs", - "isExternal": true, + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json workspaceLayout property", - "path": "/reference/nx-json#workspace-layout", - "id": "nxjson-workspaceLayout", - "isExternal": true, + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json generator defaults", - "path": "/reference/nx-json#generators", - "id": "nxjson-generator-defaults", - "isExternal": true, + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Site Map", - "path": "/see-also/sitemap", - "id": "sitemap", + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", "isExternal": false, "children": [], "disableCollapsible": false @@ -1941,149 +2668,160 @@ "disableCollapsible": false }, { - "name": "Nx Cloud Documentation", - "path": "/nx-cloud/intro/what-is-nx-cloud", - "id": "nx-cloud-documentation", - "isExternal": true, + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "--skip-nx-cache flag", - "path": "/packages/nx/documents/affected#skip-nx-cache", - "id": "skip-nx-cache-flag", - "isExternal": true, + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "tasks-runner-options property", - "path": "/reference/nx-json#tasks-runner-options", - "id": "tasks-runner-options-property", - "isExternal": true, + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json reference: inputs and namedInputs", - "path": "/reference/nx-json#inputs-&-namedinputs", - "id": "nxjson-inputs", - "isExternal": true, + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Project Configuration reference: inputs and namedInputs", - "path": "/reference/project-configuration#inputs-&-namedinputs", - "id": "project-config-inputs", - "isExternal": true, + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json workspaceLayout property", - "path": "/reference/nx-json#workspace-layout", - "id": "nxjson-workspaceLayout", - "isExternal": true, + "name": "Using Tailwind CSS with Angular projects", + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "id": "using-tailwind-css-with-angular-projects", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json generator defaults", - "path": "/reference/nx-json#generators", - "id": "nxjson-generator-defaults", - "isExternal": true, + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Site Map", - "path": "/see-also/sitemap", - "id": "sitemap", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "id": "dynamic-module-federation-with-angular", "isExternal": false, "children": [], "disableCollapsible": false - } - ] - }, - { - "id": "recipes", - "menu": [ - { - "name": "Getting Started", - "path": "/recipes/getting-started", - "id": "getting-started", - "isExternal": false, - "children": [ - { - "name": "Set up a new workspace", - "path": "/recipes/getting-started/set-up-a-new-workspace", - "id": "set-up-a-new-workspace", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false }, { - "name": "Set up a new workspace", - "path": "/recipes/getting-started/set-up-a-new-workspace", - "id": "set-up-a-new-workspace", + "name": "Setup incremental builds for Angular applications", + "path": "/recipes/angular/setup-incremental-builds-angular", + "id": "setup-incremental-builds-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console", - "path": "/recipes/nx-console", - "id": "nx-console", + "name": "Node", + "path": "/recipes/node", + "id": "node", "isExternal": false, "children": [ { - "name": "Nx Console Telemetry", - "path": "/recipes/nx-console/console-telemetry", - "id": "console-telemetry", + "name": "Deploying a Node App to Fly.io", + "path": "/recipes/node/node-server-fly-io", + "id": "node-server-fly-io", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Generate Command", - "path": "/recipes/nx-console/console-generate-command", - "id": "console-generate-command", + "name": "Add and Deploy Netlify Edge Functions with Node", + "path": "/recipes/node/node-serverless-functions-netlify", + "id": "node-serverless-functions-netlify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Run Command", - "path": "/recipes/nx-console/console-run-command", - "id": "console-run-command", + "name": "Deploying AWS lambda in Node.js", + "path": "/recipes/node/node-aws-lambda", + "id": "node-aws-lambda", "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Deploying a Node App to Fly.io", + "path": "/recipes/node/node-server-fly-io", + "id": "node-server-fly-io", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add and Deploy Netlify Edge Functions with Node", + "path": "/recipes/node/node-serverless-functions-netlify", + "id": "node-serverless-functions-netlify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying AWS lambda in Node.js", + "path": "/recipes/node/node-aws-lambda", + "id": "node-aws-lambda", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Storybook", + "path": "/recipes/storybook", + "id": "storybook", + "isExternal": false, + "children": [ { - "name": "Nx Console Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command", - "id": "console-add-dependency-command", + "name": "One main Storybook instance for all projects", + "path": "/recipes/storybook/one-storybook-for-all", + "id": "one-storybook-for-all", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Project Pane", - "path": "/recipes/nx-console/console-project-pane", - "id": "console-project-pane", + "name": "One Storybook instance per scope", + "path": "/recipes/storybook/one-storybook-per-scope", + "id": "one-storybook-per-scope", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts", - "id": "console-shortcuts", + "name": "One main Storybook instance using Storybook Composition", + "path": "/recipes/storybook/one-storybook-with-composition", + "id": "one-storybook-with-composition", "isExternal": false, "children": [], "disableCollapsible": false @@ -2092,49 +2830,98 @@ "disableCollapsible": false }, { - "name": "Nx Console Telemetry", - "path": "/recipes/nx-console/console-telemetry", - "id": "console-telemetry", + "name": "One main Storybook instance for all projects", + "path": "/recipes/storybook/one-storybook-for-all", + "id": "one-storybook-for-all", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Generate Command", - "path": "/recipes/nx-console/console-generate-command", - "id": "console-generate-command", + "name": "One Storybook instance per scope", + "path": "/recipes/storybook/one-storybook-per-scope", + "id": "one-storybook-per-scope", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "One main Storybook instance using Storybook Composition", + "path": "/recipes/storybook/one-storybook-with-composition", + "id": "one-storybook-with-composition", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Run Command", - "path": "/recipes/nx-console/console-run-command", - "id": "console-run-command", + "name": "Enforce Module Boundaries", + "path": "/recipes/enforce-module-boundaries", + "id": "enforce-module-boundaries", + "isExternal": false, + "children": [ + { + "name": "Ban Dependencies with Certain Tags", + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "id": "ban-dependencies-with-tags", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tag in Multiple Dimensions", + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "id": "tag-multiple-dimensions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Ban External Imports", + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "id": "ban-external-imports", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tags Allow List", + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "id": "tags-allow-list", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Ban Dependencies with Certain Tags", + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "id": "ban-dependencies-with-tags", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command", - "id": "console-add-dependency-command", + "name": "Tag in Multiple Dimensions", + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "id": "tag-multiple-dimensions", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Project Pane", - "path": "/recipes/nx-console/console-project-pane", - "id": "console-project-pane", + "name": "Ban External Imports", + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "id": "ban-external-imports", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts", - "id": "console-shortcuts", + "name": "Tags Allow List", + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "id": "tags-allow-list", "isExternal": false, "children": [], "disableCollapsible": false @@ -2208,14 +2995,6 @@ "isExternal": false, "children": [], "disableCollapsible": false - }, - { - "name": "Troubleshooting Nx Install Issues", - "path": "/recipes/ci/troubleshoot-nx-install-issues", - "id": "troubleshoot-nx-install-issues", - "isExternal": false, - "children": [], - "disableCollapsible": false } ], "disableCollapsible": false @@ -2285,355 +3064,127 @@ "disableCollapsible": false }, { - "name": "Troubleshooting Nx Install Issues", - "path": "/recipes/ci/troubleshoot-nx-install-issues", - "id": "troubleshoot-nx-install-issues", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Adopting Nx", - "path": "/recipes/adopting-nx", - "id": "adopting-nx", + "name": "Tips and tricks", + "path": "/recipes/tips-n-tricks", + "id": "tips-n-tricks", "isExternal": false, "children": [ { - "name": "NPM/Yarn/PNPM workspaces", - "path": "/recipes/adopting-nx/adding-to-monorepo", - "id": "adding-to-monorepo", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Add to any Project", - "path": "/recipes/adopting-nx/adding-to-existing-project", - "id": "adding-to-existing-project", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "From CRA", - "path": "/recipes/adopting-nx/migration-cra", - "id": "migration-cra", + "name": "Add a Package-based Project in an Integrated Repo", + "path": "/recipes/tips-n-tricks/package-based-in-integrated", + "id": "package-based-in-integrated", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "From Angular CLI", - "path": "/recipes/adopting-nx/migration-angular", - "id": "migration-angular", + "name": "Add an Integrated Project in a Package-based Repo", + "path": "/recipes/tips-n-tricks/integrated-in-package-based", + "id": "integrated-in-package-based", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx and Lerna", - "path": "/recipes/adopting-nx/lerna-and-nx", - "id": "lerna-and-nx", + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "From AngularJS", - "path": "/recipes/adopting-nx/migration-angularjs", - "id": "migration-angularjs", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Preserving Git Histories", - "path": "/recipes/adopting-nx/preserving-git-histories", - "id": "preserving-git-histories", + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Manual migration", - "path": "/recipes/adopting-nx/manual", - "id": "manual", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "NPM/Yarn/PNPM workspaces", - "path": "/recipes/adopting-nx/adding-to-monorepo", - "id": "adding-to-monorepo", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Add to any Project", - "path": "/recipes/adopting-nx/adding-to-existing-project", - "id": "adding-to-existing-project", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "From CRA", - "path": "/recipes/adopting-nx/migration-cra", - "id": "migration-cra", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "From Angular CLI", - "path": "/recipes/adopting-nx/migration-angular", - "id": "migration-angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Nx and Lerna", - "path": "/recipes/adopting-nx/lerna-and-nx", - "id": "lerna-and-nx", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "From AngularJS", - "path": "/recipes/adopting-nx/migration-angularjs", - "id": "migration-angularjs", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Preserving Git Histories", - "path": "/recipes/adopting-nx/preserving-git-histories", - "id": "preserving-git-histories", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Manual migration", - "path": "/recipes/adopting-nx/manual", - "id": "manual", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Adopting Nx From Angular CLI", - "path": "/recipes/adopting-nx-angular", - "id": "adopting-nx-angular", - "isExternal": false, - "children": [ - { - "name": "From Angular CLI", - "path": "/recipes/adopting-nx-angular/migration-angular", - "id": "migration-angular", + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "From Angular CLI to Integrated", - "path": "/recipes/adopting-nx-angular/angular-integrated", - "id": "angular-integrated", + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "From Angular CLI Manually", - "path": "/recipes/adopting-nx-angular/angular-manual", - "id": "angular-manual", + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "From Multiple Angular CLI Repos", - "path": "/recipes/adopting-nx-angular/angular-multiple", - "id": "angular-multiple", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "From Angular CLI", - "path": "/recipes/adopting-nx-angular/migration-angular", - "id": "migration-angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "From Angular CLI to Integrated", - "path": "/recipes/adopting-nx-angular/angular-integrated", - "id": "angular-integrated", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "From Angular CLI Manually", - "path": "/recipes/adopting-nx-angular/angular-manual", - "id": "angular-manual", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "From Multiple Angular CLI Repos", - "path": "/recipes/adopting-nx-angular/angular-multiple", - "id": "angular-multiple", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Executors", - "path": "/recipes/executors", - "id": "executors", - "isExternal": false, - "children": [ - { - "name": "Use Executor Configurations", - "path": "/recipes/executors/use-executor-configurations", - "id": "use-executor-configurations", + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Running Custom Commands", - "path": "/recipes/executors/run-commands-executor", - "id": "run-commands-executor", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Use Executor Configurations", - "path": "/recipes/executors/use-executor-configurations", - "id": "use-executor-configurations", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Running Custom Commands", - "path": "/recipes/executors/run-commands-executor", - "id": "run-commands-executor", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Environment Variables", - "path": "/recipes/environment-variables", - "id": "environment-variables", - "isExternal": false, - "children": [ - { - "name": "Define Environment Variables", - "path": "/recipes/environment-variables/define-environment-variables", - "id": "define-environment-variables", + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use Environment Variables in React", - "path": "/recipes/environment-variables/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use Environment Variables in Angular", - "path": "/recipes/environment-variables/use-environment-variables-in-angular", - "id": "use-environment-variables-in-angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Define Environment Variables", - "path": "/recipes/environment-variables/define-environment-variables", - "id": "define-environment-variables", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Use Environment Variables in React", - "path": "/recipes/environment-variables/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Use Environment Variables in Angular", - "path": "/recipes/environment-variables/use-environment-variables-in-angular", - "id": "use-environment-variables-in-angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Module Federation and Micro Frontends", - "path": "/recipes/module-federation", - "id": "module-federation", - "isExternal": false, - "children": [ - { - "name": "Faster Builds with Module Federation", - "path": "/recipes/module-federation/faster-builds", - "id": "faster-builds", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup Module Federation with SSR for Angular and React", - "path": "/recipes/module-federation/module-federation-with-ssr", - "id": "module-federation-with-ssr", + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/module-federation/dynamic-module-federation-with-angular", - "id": "dynamic-module-federation-with-angular", + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Micro-Frontend Example", - "path": "/recipes/module-federation/nx-examples", - "id": "nx-examples", + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", "isExternal": false, "children": [], "disableCollapsible": false @@ -2642,241 +3193,167 @@ "disableCollapsible": false }, { - "name": "Faster Builds with Module Federation", - "path": "/recipes/module-federation/faster-builds", - "id": "faster-builds", + "name": "Add a Package-based Project in an Integrated Repo", + "path": "/recipes/tips-n-tricks/package-based-in-integrated", + "id": "package-based-in-integrated", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup Module Federation with SSR for Angular and React", - "path": "/recipes/module-federation/module-federation-with-ssr", - "id": "module-federation-with-ssr", + "name": "Add an Integrated Project in a Package-based Repo", + "path": "/recipes/tips-n-tricks/integrated-in-package-based", + "id": "integrated-in-package-based", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/module-federation/dynamic-module-federation-with-angular", - "id": "dynamic-module-federation-with-angular", + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Micro-Frontend Example", - "path": "/recipes/module-federation/nx-examples", - "id": "nx-examples", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Storybook", - "path": "/recipes/storybook", - "id": "storybook", + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", "isExternal": false, - "children": [ - { - "name": "Publishing Storybook: One main Storybook instance for all projects", - "path": "/recipes/storybook/one-storybook-for-all", - "id": "one-storybook-for-all", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Publishing Storybook: One Storybook instance per scope", - "path": "/recipes/storybook/one-storybook-per-scope", - "id": "one-storybook-per-scope", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Publishing Storybook: One main Storybook instance using Storybook Composition", - "path": "/recipes/storybook/one-storybook-with-composition", - "id": "one-storybook-with-composition", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], + "children": [], "disableCollapsible": false }, { - "name": "Publishing Storybook: One main Storybook instance for all projects", - "path": "/recipes/storybook/one-storybook-for-all", - "id": "one-storybook-for-all", + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Publishing Storybook: One Storybook instance per scope", - "path": "/recipes/storybook/one-storybook-per-scope", - "id": "one-storybook-per-scope", + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Publishing Storybook: One main Storybook instance using Storybook Composition", - "path": "/recipes/storybook/one-storybook-with-composition", - "id": "one-storybook-with-composition", + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Deployment", - "path": "/recipes/deployment", - "id": "deployment", + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", "isExternal": false, - "children": [ - { - "name": "Deploying a Node App to Fly.io", - "path": "/recipes/deployment/node-server-fly-io", - "id": "node-server-fly-io", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Add and Deploy Netlify Edge Functions with Node", - "path": "/recipes/deployment/node-serverless-functions-netlify", - "id": "node-serverless-functions-netlify", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Deploying AWS lambda in Node.js", - "path": "/recipes/deployment/node-aws-lambda", - "id": "node-aws-lambda", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Serverless deployment with Deno Deploy", - "path": "/recipes/deployment/deno-deploy", - "id": "deno-deploy", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Add and Deploy Netlify Edge Functions with Deno", - "path": "/recipes/deployment/deno-netlify-functions", - "id": "deno-netlify-functions", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Deploying Next.js applications to Vercel", - "path": "/recipes/deployment/deploy-nextjs-to-vercel", - "id": "deploy-nextjs-to-vercel", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], + "children": [], "disableCollapsible": false }, { - "name": "Deploying a Node App to Fly.io", - "path": "/recipes/deployment/node-server-fly-io", - "id": "node-server-fly-io", + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add and Deploy Netlify Edge Functions with Node", - "path": "/recipes/deployment/node-serverless-functions-netlify", - "id": "node-serverless-functions-netlify", + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Deploying AWS lambda in Node.js", - "path": "/recipes/deployment/node-aws-lambda", - "id": "node-aws-lambda", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Serverless deployment with Deno Deploy", - "path": "/recipes/deployment/deno-deploy", - "id": "deno-deploy", + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add and Deploy Netlify Edge Functions with Deno", - "path": "/recipes/deployment/deno-netlify-functions", - "id": "deno-netlify-functions", + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Deploying Next.js applications to Vercel", - "path": "/recipes/deployment/deploy-nextjs-to-vercel", - "id": "deploy-nextjs-to-vercel", + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Database", - "path": "/recipes/database", - "id": "database", + "name": "Troubleshooting", + "path": "/recipes/troubleshooting", + "id": "troubleshooting", "isExternal": false, "children": [ { - "name": "Using Prisma with NestJS", - "path": "/recipes/database/nestjs-prisma", - "id": "nestjs-prisma", + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Mongo with Fastify", - "path": "/recipes/database/mongo-fastify", - "id": "mongo-fastify", + "name": "Troubleshooting Nx Install Issues", + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "id": "troubleshoot-nx-install-issues", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Redis with Fastify", - "path": "/recipes/database/redis-fastify", - "id": "redis-fastify", + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Postgres with Fastify", - "path": "/recipes/database/postgres-fastify", - "id": "postgres-fastify", + "name": "Unknown Local Cache Error", + "path": "/recipes/troubleshooting/unknown-local-cache", + "id": "unknown-local-cache", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/database/serverless-fastify-planetscale", - "id": "serverless-fastify-planetscale", + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling", + "id": "performance-profiling", "isExternal": false, "children": [], "disableCollapsible": false @@ -2885,79 +3362,95 @@ "disableCollapsible": false }, { - "name": "Using Prisma with NestJS", - "path": "/recipes/database/nestjs-prisma", - "id": "nestjs-prisma", + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Mongo with Fastify", - "path": "/recipes/database/mongo-fastify", - "id": "mongo-fastify", + "name": "Troubleshooting Nx Install Issues", + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "id": "troubleshoot-nx-install-issues", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Redis with Fastify", - "path": "/recipes/database/redis-fastify", - "id": "redis-fastify", + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Postgres with Fastify", - "path": "/recipes/database/postgres-fastify", - "id": "postgres-fastify", + "name": "Unknown Local Cache Error", + "path": "/recipes/troubleshooting/unknown-local-cache", + "id": "unknown-local-cache", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/database/serverless-fastify-planetscale", - "id": "serverless-fastify-planetscale", + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling", + "id": "performance-profiling", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Enforce Module Boundaries", - "path": "/recipes/enforce-module-boundaries", - "id": "enforce-module-boundaries", + "name": "Nx Console", + "path": "/recipes/nx-console", + "id": "nx-console", "isExternal": false, "children": [ { - "name": "Ban Dependencies with Certain Tags", - "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", - "id": "ban-dependencies-with-tags", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Tag in Multiple Dimensions", - "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", - "id": "tag-multiple-dimensions", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Ban External Imports", - "path": "/recipes/enforce-module-boundaries/ban-external-imports", - "id": "ban-external-imports", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Tags Allow List", - "path": "/recipes/enforce-module-boundaries/tags-allow-list", - "id": "tags-allow-list", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", "isExternal": false, "children": [], "disableCollapsible": false @@ -2966,71 +3459,79 @@ "disableCollapsible": false }, { - "name": "Ban Dependencies with Certain Tags", - "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", - "id": "ban-dependencies-with-tags", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Tag in Multiple Dimensions", - "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", - "id": "tag-multiple-dimensions", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Ban External Imports", - "path": "/recipes/enforce-module-boundaries/ban-external-imports", - "id": "ban-external-imports", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Tags Allow List", - "path": "/recipes/enforce-module-boundaries/tags-allow-list", - "id": "tags-allow-list", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Example Repos", - "path": "/recipes/example-repos", - "id": "example-repos", + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Other", + "path": "/recipes/other", + "id": "other", "isExternal": false, "children": [ { - "name": "Powering Up React Development With Nx", - "path": "/recipes/example-repos/react-nx", - "id": "react-nx", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Apollo GraphQL", - "path": "/recipes/example-repos/apollo-react", - "id": "apollo-react", + "name": "Serverless deployment with Deno Deploy", + "path": "/recipes/other/deno-deploy", + "id": "deno-deploy", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and Caching", - "path": "/recipes/example-repos/caching", - "id": "caching", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "path": "/recipes/other/deno-netlify-functions", + "id": "deno-netlify-functions", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and DTE", - "path": "/recipes/example-repos/dte", - "id": "dte", + "name": "Rescope Packages from @nrwl to @nx", + "path": "/recipes/other/rescope", + "id": "rescope", "isExternal": false, "children": [], "disableCollapsible": false @@ -3038,459 +3539,882 @@ ], "disableCollapsible": false }, - { - "name": "Powering Up React Development With Nx", - "path": "/recipes/example-repos/react-nx", - "id": "react-nx", + { + "name": "Serverless deployment with Deno Deploy", + "path": "/recipes/other/deno-deploy", + "id": "deno-deploy", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Apollo GraphQL", - "path": "/recipes/example-repos/apollo-react", - "id": "apollo-react", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "path": "/recipes/other/deno-netlify-functions", + "id": "deno-netlify-functions", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and Caching", - "path": "/recipes/example-repos/caching", - "id": "caching", + "name": "Rescope Packages from @nrwl to @nx", + "path": "/recipes/other/rescope", + "id": "rescope", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and DTE", - "path": "/recipes/example-repos/dte", - "id": "dte", + "name": "Showcase", + "path": "/showcase", + "id": "showcase", "isExternal": false, - "children": [], + "children": [ + { + "name": "Example Repos", + "path": "/showcase/example-repos", + "id": "example-repos", + "isExternal": false, + "children": [ + { + "name": "Add a Lit Project", + "path": "/showcase/example-repos/add-lit", + "id": "add-lit", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add a Solid Project", + "path": "/showcase/example-repos/add-solid", + "id": "add-solid", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add a Qwik Project", + "path": "/showcase/example-repos/add-qwik", + "id": "add-qwik", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Powering Up React Development With Nx", + "path": "/showcase/example-repos/react-nx", + "id": "react-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Apollo GraphQL", + "path": "/showcase/example-repos/apollo-react", + "id": "apollo-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Prisma with NestJS", + "path": "/showcase/example-repos/nestjs-prisma", + "id": "nestjs-prisma", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Mongo with Fastify", + "path": "/showcase/example-repos/mongo-fastify", + "id": "mongo-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Redis with Fastify", + "path": "/showcase/example-repos/redis-fastify", + "id": "redis-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Postgres with Fastify", + "path": "/showcase/example-repos/postgres-fastify", + "id": "postgres-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using PlanetScale with Serverless Fastify", + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "id": "serverless-fastify-planetscale", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and Caching", + "path": "/showcase/example-repos/caching", + "id": "caching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and DTE", + "path": "/showcase/example-repos/dte", + "id": "dte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Micro-Frontend Example", + "path": "/showcase/example-repos/mfe", + "id": "mfe", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Other", - "path": "/recipes/other", - "id": "other", + "name": "Example Repos", + "path": "/showcase/example-repos", + "id": "example-repos", "isExternal": false, "children": [ { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/other/root-level-scripts", - "id": "root-level-scripts", + "name": "Add a Lit Project", + "path": "/showcase/example-repos/add-lit", + "id": "add-lit", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/other/analyze-source-files", - "id": "analyze-source-files", + "name": "Add a Solid Project", + "path": "/showcase/example-repos/add-solid", + "id": "add-solid", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Watching", - "path": "/recipes/other/workspace-watching", - "id": "workspace-watching", + "name": "Add a Qwik Project", + "path": "/showcase/example-repos/add-qwik", + "id": "add-qwik", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Advanced Update Process", - "path": "/recipes/other/advanced-update", - "id": "advanced-update", + "name": "Powering Up React Development With Nx", + "path": "/showcase/example-repos/react-nx", + "id": "react-nx", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "JavaScript and TypeScript", - "path": "/recipes/other/js-and-ts", - "id": "js-and-ts", + "name": "Using Apollo GraphQL", + "path": "/showcase/example-repos/apollo-react", + "id": "apollo-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React Native with Nx", - "path": "/recipes/other/react-native", - "id": "react-native", + "name": "Using Prisma with NestJS", + "path": "/showcase/example-repos/nestjs-prisma", + "id": "nestjs-prisma", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Remix with Nx", - "path": "/recipes/other/remix", - "id": "remix", + "name": "Using Mongo with Fastify", + "path": "/showcase/example-repos/mongo-fastify", + "id": "mongo-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Adding Images, Fonts, and Files", - "path": "/recipes/other/adding-assets-react", - "id": "adding-assets-react", + "name": "Using Redis with Fastify", + "path": "/showcase/example-repos/redis-fastify", + "id": "redis-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup incremental builds for Angular applications", - "path": "/recipes/other/setup-incremental-builds-angular", - "id": "setup-incremental-builds-angular", + "name": "Using Postgres with Fastify", + "path": "/showcase/example-repos/postgres-fastify", + "id": "postgres-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Profiling Build Performance", - "path": "/recipes/other/performance-profiling", - "id": "performance-profiling", + "name": "Using PlanetScale with Serverless Fastify", + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "id": "serverless-fastify-planetscale", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using ESLint in Nx Workspaces", - "path": "/recipes/other/eslint", - "id": "eslint", + "name": "Large Repo and Caching", + "path": "/showcase/example-repos/caching", + "id": "caching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Configuring Browser Support", - "path": "/recipes/other/browser-support", - "id": "browser-support", + "name": "Large Repo and DTE", + "path": "/showcase/example-repos/dte", + "id": "dte", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS in React", - "path": "/recipes/other/using-tailwind-css-in-react", - "id": "using-tailwind-css-in-react", + "name": "Nx Micro-Frontend Example", + "path": "/showcase/example-repos/mfe", + "id": "mfe", "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Add a Lit Project", + "path": "/showcase/example-repos/add-lit", + "id": "add-lit", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add a Solid Project", + "path": "/showcase/example-repos/add-solid", + "id": "add-solid", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add a Qwik Project", + "path": "/showcase/example-repos/add-qwik", + "id": "add-qwik", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Powering Up React Development With Nx", + "path": "/showcase/example-repos/react-nx", + "id": "react-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Apollo GraphQL", + "path": "/showcase/example-repos/apollo-react", + "id": "apollo-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Prisma with NestJS", + "path": "/showcase/example-repos/nestjs-prisma", + "id": "nestjs-prisma", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Mongo with Fastify", + "path": "/showcase/example-repos/mongo-fastify", + "id": "mongo-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Redis with Fastify", + "path": "/showcase/example-repos/redis-fastify", + "id": "redis-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Postgres with Fastify", + "path": "/showcase/example-repos/postgres-fastify", + "id": "postgres-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using PlanetScale with Serverless Fastify", + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "id": "serverless-fastify-planetscale", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and Caching", + "path": "/showcase/example-repos/caching", + "id": "caching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and DTE", + "path": "/showcase/example-repos/dte", + "id": "dte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Micro-Frontend Example", + "path": "/showcase/example-repos/mfe", + "id": "mfe", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Reference", + "path": "/reference", + "id": "reference", + "isExternal": false, + "children": [ { - "name": "React 18 Migration", - "path": "/recipes/other/react-18", - "id": "react-18", + "name": "Nx Configuration", + "path": "/reference/nx-json", + "id": "nx-json", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS with Angular projects", - "path": "/recipes/other/using-tailwind-css-with-angular-projects", - "id": "using-tailwind-css-with-angular-projects", + "name": "Project Configuration", + "path": "/reference/project-configuration", + "id": "project-configuration", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using NgRx", - "path": "/recipes/other/misc-ngrx", - "id": "misc-ngrx", + "name": ".nxignore", + "path": "/reference/nxignore", + "id": "nxignore", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Data Persistence operators", - "path": "/recipes/other/misc-data-persistence", - "id": "misc-data-persistence", + "name": "Environment Variables", + "path": "/reference/environment-variables", + "id": "environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Find the Last Successful Commit in Azure Pipelines", - "path": "/recipes/other/azure-last-successful-commit", - "id": "azure-last-successful-commit", + "name": "Glossary", + "path": "/reference/glossary", + "id": "glossary", "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Nx Configuration", + "path": "/reference/nx-json", + "id": "nx-json", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Project Configuration", + "path": "/reference/project-configuration", + "id": "project-configuration", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": ".nxignore", + "path": "/reference/nxignore", + "id": "nxignore", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Environment Variables", + "path": "/reference/environment-variables", + "id": "environment-variables", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Glossary", + "path": "/reference/glossary", + "id": "glossary", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deprecated", + "path": "/deprecated", + "id": "deprecated", + "isExternal": false, + "children": [ { - "name": "Troubleshoot Cache Misses", - "path": "/recipes/other/troubleshoot-cache-misses", - "id": "troubleshoot-cache-misses", + "name": "workspace.json", + "path": "/deprecated/workspace-json", + "id": "workspace-json", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Export Project Graph", - "path": "/recipes/other/export-project-graph", - "id": "export-project-graph", + "name": "workspace-lint", + "path": "/deprecated/workspace-lint", + "id": "workspace-lint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Resolve Circular Dependencies", - "path": "/recipes/other/resolve-circular-dependencies", - "id": "resolve-circular-dependencies", + "name": "Workspace Generators", + "path": "/deprecated/workspace-generators", + "id": "workspace-generators", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Include All package.json Files as Projects", - "path": "/recipes/other/include-all-packagejson", - "id": "include-all-packagejson", + "name": "Workspace Executors", + "path": "/deprecated/workspace-executors", + "id": "workspace-executors", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Include Assets in Build", - "path": "/recipes/other/include-assets-in-build", - "id": "include-assets-in-build", + "name": "defaultCollection", + "path": "/deprecated/default-collection", + "id": "default-collection", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Identify Dependencies Between Folders", - "path": "/recipes/other/identify-dependencies-between-folders", - "id": "identify-dependencies-between-folders", + "name": "runtimeCacheInputs", + "path": "/deprecated/runtime-cache-inputs", + "id": "runtime-cache-inputs", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Rescope Packages from @nrwl to @nx", - "path": "/recipes/other/rescope", - "id": "rescope", + "name": "globalImplicitDependencies", + "path": "/deprecated/global-implicit-dependencies", + "id": "global-implicit-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Standalone NgRx APIs", - "path": "/recipes/other/standalone-ngrx-apis", - "id": "standalone-ngrx-apis", + "name": "Storybook deprecated docs", + "path": "/deprecated/storybook", + "id": "storybook", "isExternal": false, - "children": [], + "children": [ + { + "name": "Angular: Information about the Storybook targets", + "path": "/deprecated/storybook/angular-storybook-targets", + "id": "angular-storybook-targets", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: The browserTarget", + "path": "/deprecated/storybook/angular-browser-target", + "id": "angular-browser-target", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: Storybook Migration to webpackFinal", + "path": "/deprecated/storybook/migrate-webpack-final-angular", + "id": "migrate-webpack-final-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-angular", + "id": "upgrade-storybook-v6-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Storybook Migration to webpackFinal and the Nx Addon", + "path": "/deprecated/storybook/migrate-webpack-final-react", + "id": "migrate-webpack-final-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-react", + "id": "upgrade-storybook-v6-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false } ], "disableCollapsible": false }, { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/other/root-level-scripts", - "id": "root-level-scripts", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/other/analyze-source-files", - "id": "analyze-source-files", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Workspace Watching", - "path": "/recipes/other/workspace-watching", - "id": "workspace-watching", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Advanced Update Process", - "path": "/recipes/other/advanced-update", - "id": "advanced-update", + "name": "workspace.json", + "path": "/deprecated/workspace-json", + "id": "workspace-json", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "JavaScript and TypeScript", - "path": "/recipes/other/js-and-ts", - "id": "js-and-ts", + "name": "workspace-lint", + "path": "/deprecated/workspace-lint", + "id": "workspace-lint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React Native with Nx", - "path": "/recipes/other/react-native", - "id": "react-native", + "name": "Workspace Generators", + "path": "/deprecated/workspace-generators", + "id": "workspace-generators", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Remix with Nx", - "path": "/recipes/other/remix", - "id": "remix", + "name": "Workspace Executors", + "path": "/deprecated/workspace-executors", + "id": "workspace-executors", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Adding Images, Fonts, and Files", - "path": "/recipes/other/adding-assets-react", - "id": "adding-assets-react", + "name": "defaultCollection", + "path": "/deprecated/default-collection", + "id": "default-collection", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup incremental builds for Angular applications", - "path": "/recipes/other/setup-incremental-builds-angular", - "id": "setup-incremental-builds-angular", + "name": "runtimeCacheInputs", + "path": "/deprecated/runtime-cache-inputs", + "id": "runtime-cache-inputs", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Profiling Build Performance", - "path": "/recipes/other/performance-profiling", - "id": "performance-profiling", + "name": "globalImplicitDependencies", + "path": "/deprecated/global-implicit-dependencies", + "id": "global-implicit-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using ESLint in Nx Workspaces", - "path": "/recipes/other/eslint", - "id": "eslint", + "name": "Storybook deprecated docs", + "path": "/deprecated/storybook", + "id": "storybook", "isExternal": false, - "children": [], + "children": [ + { + "name": "Angular: Information about the Storybook targets", + "path": "/deprecated/storybook/angular-storybook-targets", + "id": "angular-storybook-targets", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: The browserTarget", + "path": "/deprecated/storybook/angular-browser-target", + "id": "angular-browser-target", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: Storybook Migration to webpackFinal", + "path": "/deprecated/storybook/migrate-webpack-final-angular", + "id": "migrate-webpack-final-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-angular", + "id": "upgrade-storybook-v6-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Storybook Migration to webpackFinal and the Nx Addon", + "path": "/deprecated/storybook/migrate-webpack-final-react", + "id": "migrate-webpack-final-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-react", + "id": "upgrade-storybook-v6-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Configuring Browser Support", - "path": "/recipes/other/browser-support", - "id": "browser-support", + "name": "Angular: Information about the Storybook targets", + "path": "/deprecated/storybook/angular-storybook-targets", + "id": "angular-storybook-targets", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS in React", - "path": "/recipes/other/using-tailwind-css-in-react", - "id": "using-tailwind-css-in-react", + "name": "Angular: The browserTarget", + "path": "/deprecated/storybook/angular-browser-target", + "id": "angular-browser-target", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React 18 Migration", - "path": "/recipes/other/react-18", - "id": "react-18", + "name": "Angular: Storybook Migration to webpackFinal", + "path": "/deprecated/storybook/migrate-webpack-final-angular", + "id": "migrate-webpack-final-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS with Angular projects", - "path": "/recipes/other/using-tailwind-css-with-angular-projects", - "id": "using-tailwind-css-with-angular-projects", + "name": "Angular: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-angular", + "id": "upgrade-storybook-v6-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using NgRx", - "path": "/recipes/other/misc-ngrx", - "id": "misc-ngrx", + "name": "React: Storybook Migration to webpackFinal and the Nx Addon", + "path": "/deprecated/storybook/migrate-webpack-final-react", + "id": "migrate-webpack-final-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Data Persistence operators", - "path": "/recipes/other/misc-data-persistence", - "id": "misc-data-persistence", + "name": "React: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-react", + "id": "upgrade-storybook-v6-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Find the Last Successful Commit in Azure Pipelines", - "path": "/recipes/other/azure-last-successful-commit", - "id": "azure-last-successful-commit", + "name": "See Also", + "path": "/see-also", + "id": "see-also", "isExternal": false, - "children": [], + "children": [ + { + "name": "Nx Cloud Documentation", + "path": "/nx-cloud/intro/what-is-nx-cloud", + "id": "nx-cloud-documentation", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Cloud Main Site", + "path": "https://nx.app", + "id": "nx-cloud-main-site", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "--skip-nx-cache flag", + "path": "/packages/nx/documents/affected#skip-nx-cache", + "id": "skip-nx-cache-flag", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "tasks-runner-options property", + "path": "/reference/nx-json#tasks-runner-options", + "id": "tasks-runner-options-property", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "nx.json reference: inputs and namedInputs", + "path": "/reference/nx-json#inputs-&-namedinputs", + "id": "nxjson-inputs", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "Project Configuration reference: inputs and namedInputs", + "path": "/reference/project-configuration#inputs-&-namedinputs", + "id": "project-config-inputs", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "nx.json workspaceLayout property", + "path": "/reference/nx-json#workspace-layout", + "id": "nxjson-workspaceLayout", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "nx.json generator defaults", + "path": "/reference/nx-json#generators", + "id": "nxjson-generator-defaults", + "isExternal": true, + "children": [], + "disableCollapsible": false + }, + { + "name": "Site Map", + "path": "/see-also/sitemap", + "id": "sitemap", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Troubleshoot Cache Misses", - "path": "/recipes/other/troubleshoot-cache-misses", - "id": "troubleshoot-cache-misses", - "isExternal": false, + "name": "Nx Cloud Documentation", + "path": "/nx-cloud/intro/what-is-nx-cloud", + "id": "nx-cloud-documentation", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Export Project Graph", - "path": "/recipes/other/export-project-graph", - "id": "export-project-graph", - "isExternal": false, + "name": "--skip-nx-cache flag", + "path": "/packages/nx/documents/affected#skip-nx-cache", + "id": "skip-nx-cache-flag", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Resolve Circular Dependencies", - "path": "/recipes/other/resolve-circular-dependencies", - "id": "resolve-circular-dependencies", - "isExternal": false, + "name": "tasks-runner-options property", + "path": "/reference/nx-json#tasks-runner-options", + "id": "tasks-runner-options-property", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Include All package.json Files as Projects", - "path": "/recipes/other/include-all-packagejson", - "id": "include-all-packagejson", - "isExternal": false, + "name": "nx.json reference: inputs and namedInputs", + "path": "/reference/nx-json#inputs-&-namedinputs", + "id": "nxjson-inputs", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Include Assets in Build", - "path": "/recipes/other/include-assets-in-build", - "id": "include-assets-in-build", - "isExternal": false, + "name": "Project Configuration reference: inputs and namedInputs", + "path": "/reference/project-configuration#inputs-&-namedinputs", + "id": "project-config-inputs", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Identify Dependencies Between Folders", - "path": "/recipes/other/identify-dependencies-between-folders", - "id": "identify-dependencies-between-folders", - "isExternal": false, + "name": "nx.json workspaceLayout property", + "path": "/reference/nx-json#workspace-layout", + "id": "nxjson-workspaceLayout", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Rescope Packages from @nrwl to @nx", - "path": "/recipes/other/rescope", - "id": "rescope", - "isExternal": false, + "name": "nx.json generator defaults", + "path": "/reference/nx-json#generators", + "id": "nxjson-generator-defaults", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Standalone NgRx APIs", - "path": "/recipes/other/standalone-ngrx-apis", - "id": "standalone-ngrx-apis", + "name": "Site Map", + "path": "/see-also/sitemap", + "id": "sitemap", "isExternal": false, "children": [], "disableCollapsible": false @@ -3498,17 +4422,17 @@ ] }, { - "id": "plugins", + "id": "extending-nx", "menu": [ { "name": "Intro", - "path": "/plugins/intro", + "path": "/extending-nx/intro", "id": "intro", "isExternal": false, "children": [ { "name": "Getting Started with Plugins", - "path": "/plugins/intro/getting-started", + "path": "/extending-nx/intro/getting-started", "id": "getting-started", "isExternal": false, "children": [], @@ -3516,7 +4440,7 @@ }, { "name": "Plugin Registry", - "path": "/plugins/registry", + "path": "/extending-nx/registry", "id": "registry", "isExternal": false, "children": [], @@ -3527,7 +4451,7 @@ }, { "name": "Getting Started with Plugins", - "path": "/plugins/intro/getting-started", + "path": "/extending-nx/intro/getting-started", "id": "getting-started", "isExternal": false, "children": [], @@ -3535,7 +4459,7 @@ }, { "name": "Plugin Registry", - "path": "/plugins/registry", + "path": "/extending-nx/registry", "id": "registry", "isExternal": false, "children": [], @@ -3543,13 +4467,13 @@ }, { "name": "5 Min Tutorials", - "path": "/plugins/tutorials", + "path": "/extending-nx/tutorials", "id": "tutorials", "isExternal": false, "children": [ { "name": "Create a Local Plugin", - "path": "/plugins/tutorials/create-plugin", + "path": "/extending-nx/tutorials/create-plugin", "id": "create-plugin", "isExternal": false, "children": [], @@ -3557,7 +4481,7 @@ }, { "name": "Maintain a Published Plugin", - "path": "/plugins/tutorials/publish-plugin", + "path": "/extending-nx/tutorials/publish-plugin", "id": "publish-plugin", "isExternal": false, "children": [], @@ -3568,7 +4492,7 @@ }, { "name": "Create a Local Plugin", - "path": "/plugins/tutorials/create-plugin", + "path": "/extending-nx/tutorials/create-plugin", "id": "create-plugin", "isExternal": false, "children": [], @@ -3576,7 +4500,7 @@ }, { "name": "Maintain a Published Plugin", - "path": "/plugins/tutorials/publish-plugin", + "path": "/extending-nx/tutorials/publish-plugin", "id": "publish-plugin", "isExternal": false, "children": [], @@ -3584,13 +4508,13 @@ }, { "name": "Recipes", - "path": "/plugins/recipes", + "path": "/extending-nx/recipes", "id": "recipes", "isExternal": false, "children": [ { "name": "Write a Simple Executor", - "path": "/plugins/recipes/local-executors", + "path": "/extending-nx/recipes/local-executors", "id": "local-executors", "isExternal": false, "children": [], @@ -3598,7 +4522,7 @@ }, { "name": "Compose Executors", - "path": "/plugins/recipes/compose-executors", + "path": "/extending-nx/recipes/compose-executors", "id": "compose-executors", "isExternal": false, "children": [], @@ -3606,7 +4530,7 @@ }, { "name": "Write a Simple Generator", - "path": "/plugins/recipes/local-generators", + "path": "/extending-nx/recipes/local-generators", "id": "local-generators", "isExternal": false, "children": [], @@ -3614,7 +4538,7 @@ }, { "name": "Compose Generators", - "path": "/plugins/recipes/composing-generators", + "path": "/extending-nx/recipes/composing-generators", "id": "composing-generators", "isExternal": false, "children": [], @@ -3622,7 +4546,7 @@ }, { "name": "Provide Options for Generators", - "path": "/plugins/recipes/generator-options", + "path": "/extending-nx/recipes/generator-options", "id": "generator-options", "isExternal": false, "children": [], @@ -3630,7 +4554,7 @@ }, { "name": "Create Files", - "path": "/plugins/recipes/creating-files", + "path": "/extending-nx/recipes/creating-files", "id": "creating-files", "isExternal": false, "children": [], @@ -3638,7 +4562,7 @@ }, { "name": "Modify Files", - "path": "/plugins/recipes/modifying-files", + "path": "/extending-nx/recipes/modifying-files", "id": "modifying-files", "isExternal": false, "children": [], @@ -3646,7 +4570,7 @@ }, { "name": "Write a Migration", - "path": "/plugins/recipes/migration-generators", + "path": "/extending-nx/recipes/migration-generators", "id": "migration-generators", "isExternal": false, "children": [], @@ -3654,7 +4578,7 @@ }, { "name": "Create a Preset", - "path": "/plugins/recipes/create-preset", + "path": "/extending-nx/recipes/create-preset", "id": "create-preset", "isExternal": false, "children": [], @@ -3662,7 +4586,7 @@ }, { "name": "Modify the Project Graph", - "path": "/plugins/recipes/project-graph-plugins", + "path": "/extending-nx/recipes/project-graph-plugins", "id": "project-graph-plugins", "isExternal": false, "children": [], @@ -3670,7 +4594,7 @@ }, { "name": "Identify Custom Projects", - "path": "/plugins/recipes/project-inference-plugins", + "path": "/extending-nx/recipes/project-inference-plugins", "id": "project-inference-plugins", "isExternal": false, "children": [], @@ -3681,7 +4605,7 @@ }, { "name": "Write a Simple Executor", - "path": "/plugins/recipes/local-executors", + "path": "/extending-nx/recipes/local-executors", "id": "local-executors", "isExternal": false, "children": [], @@ -3689,7 +4613,7 @@ }, { "name": "Compose Executors", - "path": "/plugins/recipes/compose-executors", + "path": "/extending-nx/recipes/compose-executors", "id": "compose-executors", "isExternal": false, "children": [], @@ -3697,7 +4621,7 @@ }, { "name": "Write a Simple Generator", - "path": "/plugins/recipes/local-generators", + "path": "/extending-nx/recipes/local-generators", "id": "local-generators", "isExternal": false, "children": [], @@ -3705,7 +4629,7 @@ }, { "name": "Compose Generators", - "path": "/plugins/recipes/composing-generators", + "path": "/extending-nx/recipes/composing-generators", "id": "composing-generators", "isExternal": false, "children": [], @@ -3713,7 +4637,7 @@ }, { "name": "Provide Options for Generators", - "path": "/plugins/recipes/generator-options", + "path": "/extending-nx/recipes/generator-options", "id": "generator-options", "isExternal": false, "children": [], @@ -3721,7 +4645,7 @@ }, { "name": "Create Files", - "path": "/plugins/recipes/creating-files", + "path": "/extending-nx/recipes/creating-files", "id": "creating-files", "isExternal": false, "children": [], @@ -3729,7 +4653,7 @@ }, { "name": "Modify Files", - "path": "/plugins/recipes/modifying-files", + "path": "/extending-nx/recipes/modifying-files", "id": "modifying-files", "isExternal": false, "children": [], @@ -3737,7 +4661,7 @@ }, { "name": "Write a Migration", - "path": "/plugins/recipes/migration-generators", + "path": "/extending-nx/recipes/migration-generators", "id": "migration-generators", "isExternal": false, "children": [], @@ -3745,7 +4669,7 @@ }, { "name": "Create a Preset", - "path": "/plugins/recipes/create-preset", + "path": "/extending-nx/recipes/create-preset", "id": "create-preset", "isExternal": false, "children": [], @@ -3753,7 +4677,7 @@ }, { "name": "Modify the Project Graph", - "path": "/plugins/recipes/project-graph-plugins", + "path": "/extending-nx/recipes/project-graph-plugins", "id": "project-graph-plugins", "isExternal": false, "children": [], @@ -3761,7 +4685,7 @@ }, { "name": "Identify Custom Projects", - "path": "/plugins/recipes/project-inference-plugins", + "path": "/extending-nx/recipes/project-inference-plugins", "id": "project-inference-plugins", "isExternal": false, "children": [], @@ -3960,7 +4884,7 @@ "disableCollapsible": false }, { - "name": "On Prem", + "name": "Enterprise + On Prem", "path": "/nx-cloud/private-cloud", "id": "private-cloud", "isExternal": false, @@ -3989,6 +4913,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "On-Prem VM Setup", + "path": "/nx-cloud/private-cloud/ami-setup", + "id": "ami-setup", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Authenticate with GitLab", "path": "/nx-cloud/private-cloud/auth-gitlab", @@ -4020,22 +4952,6 @@ "isExternal": false, "children": [], "disableCollapsible": false - }, - { - "name": "Kubernetes Setup", - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "id": "kubernetes-setup", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Standalone", - "path": "/nx-cloud/private-cloud/standalone", - "id": "standalone", - "isExternal": false, - "children": [], - "disableCollapsible": false } ], "disableCollapsible": false @@ -4064,6 +4980,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "On-Prem VM Setup", + "path": "/nx-cloud/private-cloud/ami-setup", + "id": "ami-setup", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Authenticate with GitLab", "path": "/nx-cloud/private-cloud/auth-gitlab", @@ -4096,22 +5020,6 @@ "children": [], "disableCollapsible": false }, - { - "name": "Kubernetes Setup", - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "id": "kubernetes-setup", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Standalone", - "path": "/nx-cloud/private-cloud/standalone", - "id": "standalone", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, { "name": "Reference", "path": "/nx-cloud/reference", @@ -4265,6 +5173,14 @@ "isExternal": false, "disableCollapsible": false }, + { + "id": "browser-esbuild", + "path": "/packages/angular/executors/browser-esbuild", + "name": "browser-esbuild", + "children": [], + "isExternal": false, + "disableCollapsible": false + }, { "id": "webpack-browser", "path": "/packages/angular/executors/webpack-browser", @@ -4663,17 +5579,17 @@ "disableCollapsible": false }, { - "id": "cypress-e2e-configuration", - "path": "/packages/cypress/generators/cypress-e2e-configuration", - "name": "cypress-e2e-configuration", + "id": "configuration", + "path": "/packages/cypress/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false }, { - "id": "cypress-component-configuration", - "path": "/packages/cypress/generators/cypress-component-configuration", - "name": "cypress-component-configuration", + "id": "component-configuration", + "path": "/packages/cypress/generators/component-configuration", + "name": "component-configuration", "children": [], "isExternal": false, "disableCollapsible": false @@ -4857,9 +5773,9 @@ "disableCollapsible": false }, { - "id": "esbuild-project", - "path": "/packages/esbuild/generators/esbuild-project", - "name": "esbuild-project", + "id": "configuration", + "path": "/packages/esbuild/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false @@ -4897,6 +5813,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "The `dependency-checks` rule", + "path": "/packages/eslint-plugin/documents/dependency-checks", + "id": "dependency-checks", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "isExternal": false, @@ -5182,9 +6106,9 @@ "disableCollapsible": false }, { - "id": "jest-project", - "path": "/packages/jest/generators/jest-project", - "name": "jest-project", + "id": "configuration", + "path": "/packages/jest/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false @@ -6010,6 +6934,74 @@ "isExternal": false, "disableCollapsible": false }, + { + "id": "playwright", + "path": "/packages/playwright", + "name": "playwright", + "children": [ + { + "id": "documents", + "path": "/packages/playwright/documents", + "name": "documents", + "children": [ + { + "name": "Overview", + "path": "/packages/playwright/documents/overview", + "id": "overview", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "isExternal": false, + "disableCollapsible": false + }, + { + "id": "executors", + "path": "/packages/playwright/executors", + "name": "executors", + "children": [ + { + "id": "playwright", + "path": "/packages/playwright/executors/playwright", + "name": "playwright", + "children": [], + "isExternal": false, + "disableCollapsible": false + } + ], + "isExternal": false, + "disableCollapsible": false + }, + { + "id": "generators", + "path": "/packages/playwright/generators", + "name": "generators", + "children": [ + { + "id": "configuration", + "path": "/packages/playwright/generators/configuration", + "name": "configuration", + "children": [], + "isExternal": false, + "disableCollapsible": false + }, + { + "id": "init", + "path": "/packages/playwright/generators/init", + "name": "init", + "children": [], + "isExternal": false, + "disableCollapsible": false + } + ], + "isExternal": false, + "disableCollapsible": false + } + ], + "isExternal": false, + "disableCollapsible": false + }, { "id": "plugin", "path": "/packages/plugin", @@ -6538,9 +7530,9 @@ "disableCollapsible": false }, { - "id": "rollup-project", - "path": "/packages/rollup/generators/rollup-project", - "name": "rollup-project", + "id": "configuration", + "path": "/packages/rollup/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false @@ -6619,6 +7611,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Setting up Storybook Interaction Tests with Nx", + "path": "/packages/storybook/documents/storybook-interaction-tests", + "id": "storybook-interaction-tests", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Setting up Storybook Composition with Nx", "path": "/packages/storybook/documents/storybook-composition-setup", @@ -6994,9 +7994,9 @@ "disableCollapsible": false }, { - "id": "webpack-project", - "path": "/packages/webpack/generators/webpack-project", - "name": "webpack-project", + "id": "configuration", + "path": "/packages/webpack/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false @@ -7085,6 +8085,14 @@ "isExternal": false, "disableCollapsible": false }, + { + "id": "convert-to-monorepo", + "path": "/packages/workspace/generators/convert-to-monorepo", + "name": "convert-to-monorepo", + "children": [], + "isExternal": false, + "disableCollapsible": false + }, { "id": "new", "path": "/packages/workspace/generators/new", diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 905e1c190280d..605a919fac732 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -957,7 +957,7 @@ { "id": "run-tasks", "name": "Run Tasks", - "description": "", + "description": "Learn about the various ways you can use Nx to run tasks in your workspace.", "file": "shared/core-features/run-tasks", "itemList": [], "isExternal": false, @@ -967,7 +967,7 @@ { "id": "cache-task-results", "name": "Cache Task Results", - "description": "", + "description": "Learn how to define cacheable tasks, how to fine-tune with inputs and outputs, where the cache is stored and much more.", "file": "shared/core-features/cache-task-results", "itemList": [], "isExternal": false, @@ -975,29 +975,19 @@ "tags": ["cache-task-results"] }, { - "id": "share-your-cache", - "name": "Share Your Cache", - "description": "", - "file": "shared/core-features/share-your-cache", - "itemList": [], - "isExternal": false, - "path": "/core-features/share-your-cache", - "tags": ["share-your-cache"] - }, - { - "id": "explore-graph", - "name": "Explore the Graph", - "description": "", - "file": "shared/core-features/explore-graph", + "id": "remote-cache", + "name": "Use Remote Caching", + "description": "Learn how to enable remote caching s.t. you don't just benefit locally from it but also in CI.", + "file": "shared/core-features/remote-cache", "itemList": [], "isExternal": false, - "path": "/core-features/explore-graph", - "tags": ["explore-graph"] + "path": "/core-features/remote-cache", + "tags": ["remote-cache"] }, { "id": "distribute-task-execution", "name": "Distribute Task Execution", - "description": "", + "description": "Learn how to efficiently distribute tasks across machines to take full advantage of parallelization. Nx Cloud has a built-in DTE mechanism which makes this a trivial task.", "file": "shared/core-features/distribute-task-execution", "itemList": [], "isExternal": false, @@ -1005,19 +995,19 @@ "tags": ["distribute-task-execution"] }, { - "id": "integrate-with-editors", - "name": "Integrate with Editors", - "description": "", - "file": "shared/core-features/integrate-with-editors", + "id": "explore-graph", + "name": "Explore the Graph", + "description": "Nx uses a graph behind the scenes to optimize your operations. You can also visualize and use the graph to better understand your workspace structure. Learn more in this guide.", + "file": "shared/core-features/explore-graph", "itemList": [], "isExternal": false, - "path": "/core-features/integrate-with-editors", - "tags": ["integrate-with-editors"] + "path": "/core-features/explore-graph", + "tags": ["explore-graph"] }, { "id": "automate-updating-dependencies", "name": "Automate Updating Dependencies", - "description": "", + "description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.", "file": "shared/core-features/automate-updating-dependencies", "itemList": [], "isExternal": false, @@ -1025,14 +1015,55 @@ "tags": ["automate-updating-dependencies"] }, { - "id": "enforce-project-boundaries", - "name": "Enforce Project Boundaries", - "description": "", - "file": "shared/core-features/enforce-project-boundaries", + "id": "enforce-module-boundaries", + "name": "Enforce Module Boundaries", + "description": "Learn how to avoid dependency hell and scale a codebase by imposing constraints on your projects using the module boundary lint rule.", + "file": "shared/core-features/enforce-module-boundaries", + "itemList": [], + "isExternal": false, + "path": "/core-features/enforce-module-boundaries", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "integrate-with-editors", + "name": "Integrate with Editors", + "description": "Learn about Nx Console, an extension for VS Code and WebStorm.", + "file": "shared/core-features/integrate-with-editors", "itemList": [], "isExternal": false, - "path": "/core-features/enforce-project-boundaries", - "tags": ["enforce-project-boundaries"] + "path": "/core-features/integrate-with-editors", + "tags": ["integrate-with-editors"] + }, + { + "id": "plugin-features", + "name": "Plugin Features", + "description": "Learn what is a plugin, the different type of plugins and how to create one.", + "file": "", + "itemList": [ + { + "id": "use-task-executors", + "name": "Use Task Executors", + "description": "", + "file": "shared/plugin-features/use-task-executors", + "itemList": [], + "isExternal": false, + "path": "/core-features/plugin-features/use-task-executors", + "tags": ["use-task-executors"] + }, + { + "id": "use-code-generators", + "name": "Use Code Generators", + "description": "", + "file": "shared/plugin-features/use-code-generators", + "itemList": [], + "isExternal": false, + "path": "/core-features/plugin-features/use-code-generators", + "tags": ["use-code-generators"] + } + ], + "isExternal": false, + "path": "/core-features/plugin-features", + "tags": [] } ], "isExternal": false, @@ -1042,7 +1073,7 @@ "/core-features/run-tasks": { "id": "run-tasks", "name": "Run Tasks", - "description": "", + "description": "Learn about the various ways you can use Nx to run tasks in your workspace.", "file": "shared/core-features/run-tasks", "itemList": [], "isExternal": false, @@ -1052,74 +1083,74 @@ "/core-features/cache-task-results": { "id": "cache-task-results", "name": "Cache Task Results", - "description": "", + "description": "Learn how to define cacheable tasks, how to fine-tune with inputs and outputs, where the cache is stored and much more.", "file": "shared/core-features/cache-task-results", "itemList": [], "isExternal": false, "path": "/core-features/cache-task-results", "tags": ["cache-task-results"] }, - "/core-features/share-your-cache": { - "id": "share-your-cache", - "name": "Share Your Cache", - "description": "", - "file": "shared/core-features/share-your-cache", - "itemList": [], - "isExternal": false, - "path": "/core-features/share-your-cache", - "tags": ["share-your-cache"] - }, - "/core-features/explore-graph": { - "id": "explore-graph", - "name": "Explore the Graph", - "description": "", - "file": "shared/core-features/explore-graph", + "/core-features/remote-cache": { + "id": "remote-cache", + "name": "Use Remote Caching", + "description": "Learn how to enable remote caching s.t. you don't just benefit locally from it but also in CI.", + "file": "shared/core-features/remote-cache", "itemList": [], "isExternal": false, - "path": "/core-features/explore-graph", - "tags": ["explore-graph"] + "path": "/core-features/remote-cache", + "tags": ["remote-cache"] }, "/core-features/distribute-task-execution": { "id": "distribute-task-execution", "name": "Distribute Task Execution", - "description": "", + "description": "Learn how to efficiently distribute tasks across machines to take full advantage of parallelization. Nx Cloud has a built-in DTE mechanism which makes this a trivial task.", "file": "shared/core-features/distribute-task-execution", "itemList": [], "isExternal": false, "path": "/core-features/distribute-task-execution", "tags": ["distribute-task-execution"] }, - "/core-features/integrate-with-editors": { - "id": "integrate-with-editors", - "name": "Integrate with Editors", - "description": "", - "file": "shared/core-features/integrate-with-editors", + "/core-features/explore-graph": { + "id": "explore-graph", + "name": "Explore the Graph", + "description": "Nx uses a graph behind the scenes to optimize your operations. You can also visualize and use the graph to better understand your workspace structure. Learn more in this guide.", + "file": "shared/core-features/explore-graph", "itemList": [], "isExternal": false, - "path": "/core-features/integrate-with-editors", - "tags": ["integrate-with-editors"] + "path": "/core-features/explore-graph", + "tags": ["explore-graph"] }, "/core-features/automate-updating-dependencies": { "id": "automate-updating-dependencies", "name": "Automate Updating Dependencies", - "description": "", + "description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.", "file": "shared/core-features/automate-updating-dependencies", "itemList": [], "isExternal": false, "path": "/core-features/automate-updating-dependencies", "tags": ["automate-updating-dependencies"] }, - "/core-features/enforce-project-boundaries": { - "id": "enforce-project-boundaries", - "name": "Enforce Project Boundaries", - "description": "", - "file": "shared/core-features/enforce-project-boundaries", + "/core-features/enforce-module-boundaries": { + "id": "enforce-module-boundaries", + "name": "Enforce Module Boundaries", + "description": "Learn how to avoid dependency hell and scale a codebase by imposing constraints on your projects using the module boundary lint rule.", + "file": "shared/core-features/enforce-module-boundaries", + "itemList": [], + "isExternal": false, + "path": "/core-features/enforce-module-boundaries", + "tags": ["enforce-module-boundaries"] + }, + "/core-features/integrate-with-editors": { + "id": "integrate-with-editors", + "name": "Integrate with Editors", + "description": "Learn about Nx Console, an extension for VS Code and WebStorm.", + "file": "shared/core-features/integrate-with-editors", "itemList": [], "isExternal": false, - "path": "/core-features/enforce-project-boundaries", - "tags": ["enforce-project-boundaries"] + "path": "/core-features/integrate-with-editors", + "tags": ["integrate-with-editors"] }, - "/plugin-features": { + "/core-features/plugin-features": { "id": "plugin-features", "name": "Plugin Features", "description": "Learn what is a plugin, the different type of plugins and how to create one.", @@ -1132,7 +1163,7 @@ "file": "shared/plugin-features/use-task-executors", "itemList": [], "isExternal": false, - "path": "/plugin-features/use-task-executors", + "path": "/core-features/plugin-features/use-task-executors", "tags": ["use-task-executors"] }, { @@ -1142,32 +1173,32 @@ "file": "shared/plugin-features/use-code-generators", "itemList": [], "isExternal": false, - "path": "/plugin-features/use-code-generators", + "path": "/core-features/plugin-features/use-code-generators", "tags": ["use-code-generators"] } ], "isExternal": false, - "path": "/plugin-features", + "path": "/core-features/plugin-features", "tags": [] }, - "/plugin-features/use-task-executors": { + "/core-features/plugin-features/use-task-executors": { "id": "use-task-executors", "name": "Use Task Executors", "description": "", "file": "shared/plugin-features/use-task-executors", "itemList": [], "isExternal": false, - "path": "/plugin-features/use-task-executors", + "path": "/core-features/plugin-features/use-task-executors", "tags": ["use-task-executors"] }, - "/plugin-features/use-code-generators": { + "/core-features/plugin-features/use-code-generators": { "id": "use-code-generators", "name": "Use Code Generators", "description": "", "file": "shared/plugin-features/use-code-generators", "itemList": [], "isExternal": false, - "path": "/plugin-features/use-code-generators", + "path": "/core-features/plugin-features/use-code-generators", "tags": ["use-code-generators"] }, "/concepts": { @@ -1184,7 +1215,7 @@ "itemList": [], "isExternal": false, "path": "/concepts/integrated-vs-package-based", - "tags": ["intro"] + "tags": ["intro", "repository-types"] }, { "id": "mental-model", @@ -1237,13 +1268,239 @@ "tags": ["run-tasks"] }, { - "id": "more-concept-guides", - "name": "More Concept Guides »", - "description": "", + "id": "more-concepts", + "name": "More Concepts", + "description": "Get deeper into how Nx works and its different aspects.", "file": "", - "itemList": [], + "itemList": [ + { + "id": "customizing-inputs", + "name": "Customizing Inputs", + "description": "", + "file": "shared/concepts/customizing-inputs", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/customizing-inputs", + "tags": ["cache-task-results"] + }, + { + "id": "incremental-builds", + "name": "Incremental Builds", + "description": "", + "file": "shared/incremental-builds", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/incremental-builds", + "tags": ["use-task-executors"] + }, + { + "id": "illustrated-dte", + "name": "Illustrated Distributed Task Execution", + "description": "", + "file": "shared/concepts/illustrated-dte-guide", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/illustrated-dte", + "tags": ["distribute-task-execution"] + }, + { + "id": "turbo-and-nx", + "name": "Nx and Turborepo", + "description": "", + "file": "shared/guides/turbo-and-nx", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/turbo-and-nx", + "tags": [] + }, + { + "id": "why-monorepos", + "name": "Monorepos", + "description": "", + "file": "shared/guides/why-monorepos", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/why-monorepos", + "tags": [] + }, + { + "id": "dependency-management", + "name": "Dependency Management", + "description": "", + "file": "shared/concepts/dependency-management", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/dependency-management", + "tags": [] + }, + { + "id": "code-sharing", + "name": "Code Sharing", + "description": "", + "file": "shared/concepts/code-sharing", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/code-sharing", + "tags": [] + }, + { + "id": "monorepo-nx-enterprise", + "name": "Using Nx at Enterprises", + "description": "", + "file": "shared/monorepo-nx-enterprise", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/monorepo-nx-enterprise", + "tags": ["enforce-module-boundaries", "use-code-generators"] + }, + { + "id": "nx-daemon", + "name": "Nx Daemon", + "description": "", + "file": "shared/daemon", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/nx-daemon", + "tags": [] + }, + { + "id": "nx-and-angular", + "name": "Nx and the Angular CLI", + "description": "", + "file": "shared/guides/nx-and-angular-cli", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/nx-and-angular", + "tags": [] + }, + { + "id": "folder-structure", + "name": "Folder Structure", + "description": "", + "file": "shared/guides/integrated-repo-folder-structure", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/folder-structure", + "tags": [] + }, + { + "id": "nx-devkit-angular-devkit", + "name": "Nx Devkit and Angular Devkit", + "description": "", + "file": "shared/guides/nx-devkit-angular-devkit", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/nx-devkit-angular-devkit", + "tags": ["create-your-own-plugin"] + }, + { + "id": "micro-frontend-architecture", + "name": "Micro Frontend Architecture", + "description": "", + "file": "shared/guides/module-federation/micro-frontend-architecture", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/micro-frontend-architecture", + "tags": [] + }, + { + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "tags": [ + "use-task-executors", + "module-federation", + "angular", + "react" + ] + }, + { + "id": "applications-and-libraries", + "name": "Applications and Libraries", + "description": "", + "file": "shared/workspace/applications-and-libraries", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/applications-and-libraries", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "creating-libraries", + "name": "Creating Libraries", + "description": "", + "file": "shared/workspace/creating-libraries", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/creating-libraries", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "library-types", + "name": "Library Types", + "description": "", + "file": "shared/workspace/library-types", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/library-types", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "grouping-libraries", + "name": "Grouping Libraries", + "description": "", + "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": "", + "file": "shared/workspace/buildable-and-publishable-libraries", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/buildable-and-publishable-libraries", + "tags": [] + }, + { + "id": "how-project-graph-is-built", + "name": "How the Project Graph is Built", + "description": "", + "file": "shared/concepts/how-project-graph-is-built", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/how-project-graph-is-built", + "tags": ["explore-graph"] + }, + { + "id": "nx-and-the-wrapper", + "name": "Nx and the Nx Wrapper", + "description": "", + "file": "shared/guides/nx-and-the-wrapper", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/nx-and-the-wrapper", + "tags": [] + }, + { + "id": "global-nx", + "name": "Managing your Global Nx Installation", + "description": "", + "file": "shared/guides/global-nx", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/global-nx", + "tags": [] + } + ], "isExternal": false, - "path": "/more-concepts", + "path": "/concepts/more-concepts", "tags": [] } ], @@ -1259,7 +1516,7 @@ "itemList": [], "isExternal": false, "path": "/concepts/integrated-vs-package-based", - "tags": ["intro"] + "tags": ["intro", "repository-types"] }, "/concepts/mental-model": { "id": "mental-model", @@ -1311,7 +1568,7 @@ "path": "/concepts/affected", "tags": ["run-tasks"] }, - "/more-concepts": { + "/concepts/more-concepts": { "id": "more-concepts", "name": "More Concepts", "description": "Get deeper into how Nx works and its different aspects.", @@ -1324,7 +1581,7 @@ "file": "shared/concepts/customizing-inputs", "itemList": [], "isExternal": false, - "path": "/more-concepts/customizing-inputs", + "path": "/concepts/more-concepts/customizing-inputs", "tags": ["cache-task-results"] }, { @@ -1334,7 +1591,7 @@ "file": "shared/incremental-builds", "itemList": [], "isExternal": false, - "path": "/more-concepts/incremental-builds", + "path": "/concepts/more-concepts/incremental-builds", "tags": ["use-task-executors"] }, { @@ -1344,7 +1601,7 @@ "file": "shared/concepts/illustrated-dte-guide", "itemList": [], "isExternal": false, - "path": "/more-concepts/illustrated-dte", + "path": "/concepts/more-concepts/illustrated-dte", "tags": ["distribute-task-execution"] }, { @@ -1354,7 +1611,7 @@ "file": "shared/guides/turbo-and-nx", "itemList": [], "isExternal": false, - "path": "/more-concepts/turbo-and-nx", + "path": "/concepts/more-concepts/turbo-and-nx", "tags": [] }, { @@ -1364,7 +1621,7 @@ "file": "shared/guides/why-monorepos", "itemList": [], "isExternal": false, - "path": "/more-concepts/why-monorepos", + "path": "/concepts/more-concepts/why-monorepos", "tags": [] }, { @@ -1374,7 +1631,7 @@ "file": "shared/concepts/dependency-management", "itemList": [], "isExternal": false, - "path": "/more-concepts/dependency-management", + "path": "/concepts/more-concepts/dependency-management", "tags": [] }, { @@ -1384,7 +1641,7 @@ "file": "shared/concepts/code-sharing", "itemList": [], "isExternal": false, - "path": "/more-concepts/code-sharing", + "path": "/concepts/more-concepts/code-sharing", "tags": [] }, { @@ -1394,8 +1651,8 @@ "file": "shared/monorepo-nx-enterprise", "itemList": [], "isExternal": false, - "path": "/more-concepts/monorepo-nx-enterprise", - "tags": ["enforce-project-boundaries", "use-code-generators"] + "path": "/concepts/more-concepts/monorepo-nx-enterprise", + "tags": ["enforce-module-boundaries", "use-code-generators"] }, { "id": "nx-daemon", @@ -1404,7 +1661,7 @@ "file": "shared/daemon", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-daemon", + "path": "/concepts/more-concepts/nx-daemon", "tags": [] }, { @@ -1414,7 +1671,7 @@ "file": "shared/guides/nx-and-angular-cli", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-and-angular", + "path": "/concepts/more-concepts/nx-and-angular", "tags": [] }, { @@ -1424,7 +1681,7 @@ "file": "shared/guides/integrated-repo-folder-structure", "itemList": [], "isExternal": false, - "path": "/more-concepts/folder-structure", + "path": "/concepts/more-concepts/folder-structure", "tags": [] }, { @@ -1434,7 +1691,7 @@ "file": "shared/guides/nx-devkit-angular-devkit", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-devkit-angular-devkit", + "path": "/concepts/more-concepts/nx-devkit-angular-devkit", "tags": ["create-your-own-plugin"] }, { @@ -1444,9 +1701,19 @@ "file": "shared/guides/module-federation/micro-frontend-architecture", "itemList": [], "isExternal": false, - "path": "/more-concepts/micro-frontend-architecture", + "path": "/concepts/more-concepts/micro-frontend-architecture", "tags": [] }, + { + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "tags": ["use-task-executors", "module-federation", "angular", "react"] + }, { "id": "applications-and-libraries", "name": "Applications and Libraries", @@ -1454,8 +1721,8 @@ "file": "shared/workspace/applications-and-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/applications-and-libraries", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/applications-and-libraries", + "tags": ["enforce-module-boundaries"] }, { "id": "creating-libraries", @@ -1464,8 +1731,8 @@ "file": "shared/workspace/creating-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/creating-libraries", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/creating-libraries", + "tags": ["enforce-module-boundaries"] }, { "id": "library-types", @@ -1474,8 +1741,8 @@ "file": "shared/workspace/library-types", "itemList": [], "isExternal": false, - "path": "/more-concepts/library-types", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/library-types", + "tags": ["enforce-module-boundaries"] }, { "id": "grouping-libraries", @@ -1484,8 +1751,8 @@ "file": "shared/workspace/grouping-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/grouping-libraries", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/grouping-libraries", + "tags": ["enforce-module-boundaries"] }, { "id": "buildable-and-publishable-libraries", @@ -1494,7 +1761,7 @@ "file": "shared/workspace/buildable-and-publishable-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/buildable-and-publishable-libraries", + "path": "/concepts/more-concepts/buildable-and-publishable-libraries", "tags": [] }, { @@ -1504,7 +1771,7 @@ "file": "shared/concepts/how-project-graph-is-built", "itemList": [], "isExternal": false, - "path": "/more-concepts/how-project-graph-is-built", + "path": "/concepts/more-concepts/how-project-graph-is-built", "tags": ["explore-graph"] }, { @@ -1514,7 +1781,7 @@ "file": "shared/guides/nx-and-the-wrapper", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-and-the-wrapper", + "path": "/concepts/more-concepts/nx-and-the-wrapper", "tags": [] }, { @@ -1524,273 +1791,3092 @@ "file": "shared/guides/global-nx", "itemList": [], "isExternal": false, - "path": "/more-concepts/global-nx", + "path": "/concepts/more-concepts/global-nx", "tags": [] } ], "isExternal": false, - "path": "/more-concepts", + "path": "/concepts/more-concepts", "tags": [] }, - "/more-concepts/customizing-inputs": { + "/concepts/more-concepts/customizing-inputs": { "id": "customizing-inputs", "name": "Customizing Inputs", "description": "", "file": "shared/concepts/customizing-inputs", "itemList": [], "isExternal": false, - "path": "/more-concepts/customizing-inputs", + "path": "/concepts/more-concepts/customizing-inputs", "tags": ["cache-task-results"] }, - "/more-concepts/incremental-builds": { + "/concepts/more-concepts/incremental-builds": { "id": "incremental-builds", "name": "Incremental Builds", "description": "", "file": "shared/incremental-builds", "itemList": [], "isExternal": false, - "path": "/more-concepts/incremental-builds", + "path": "/concepts/more-concepts/incremental-builds", "tags": ["use-task-executors"] }, - "/more-concepts/illustrated-dte": { + "/concepts/more-concepts/illustrated-dte": { "id": "illustrated-dte", "name": "Illustrated Distributed Task Execution", "description": "", "file": "shared/concepts/illustrated-dte-guide", "itemList": [], "isExternal": false, - "path": "/more-concepts/illustrated-dte", + "path": "/concepts/more-concepts/illustrated-dte", "tags": ["distribute-task-execution"] }, - "/more-concepts/turbo-and-nx": { + "/concepts/more-concepts/turbo-and-nx": { "id": "turbo-and-nx", "name": "Nx and Turborepo", "description": "", "file": "shared/guides/turbo-and-nx", "itemList": [], "isExternal": false, - "path": "/more-concepts/turbo-and-nx", + "path": "/concepts/more-concepts/turbo-and-nx", "tags": [] }, - "/more-concepts/why-monorepos": { + "/concepts/more-concepts/why-monorepos": { "id": "why-monorepos", "name": "Monorepos", "description": "", "file": "shared/guides/why-monorepos", "itemList": [], "isExternal": false, - "path": "/more-concepts/why-monorepos", + "path": "/concepts/more-concepts/why-monorepos", "tags": [] }, - "/more-concepts/dependency-management": { + "/concepts/more-concepts/dependency-management": { "id": "dependency-management", "name": "Dependency Management", "description": "", "file": "shared/concepts/dependency-management", "itemList": [], "isExternal": false, - "path": "/more-concepts/dependency-management", + "path": "/concepts/more-concepts/dependency-management", "tags": [] }, - "/more-concepts/code-sharing": { + "/concepts/more-concepts/code-sharing": { "id": "code-sharing", "name": "Code Sharing", "description": "", "file": "shared/concepts/code-sharing", "itemList": [], "isExternal": false, - "path": "/more-concepts/code-sharing", + "path": "/concepts/more-concepts/code-sharing", "tags": [] }, - "/more-concepts/monorepo-nx-enterprise": { + "/concepts/more-concepts/monorepo-nx-enterprise": { "id": "monorepo-nx-enterprise", "name": "Using Nx at Enterprises", "description": "", "file": "shared/monorepo-nx-enterprise", "itemList": [], "isExternal": false, - "path": "/more-concepts/monorepo-nx-enterprise", - "tags": ["enforce-project-boundaries", "use-code-generators"] + "path": "/concepts/more-concepts/monorepo-nx-enterprise", + "tags": ["enforce-module-boundaries", "use-code-generators"] }, - "/more-concepts/nx-daemon": { + "/concepts/more-concepts/nx-daemon": { "id": "nx-daemon", "name": "Nx Daemon", "description": "", "file": "shared/daemon", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-daemon", + "path": "/concepts/more-concepts/nx-daemon", "tags": [] }, - "/more-concepts/nx-and-angular": { + "/concepts/more-concepts/nx-and-angular": { "id": "nx-and-angular", "name": "Nx and the Angular CLI", "description": "", "file": "shared/guides/nx-and-angular-cli", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-and-angular", + "path": "/concepts/more-concepts/nx-and-angular", "tags": [] }, - "/more-concepts/folder-structure": { + "/concepts/more-concepts/folder-structure": { "id": "folder-structure", "name": "Folder Structure", "description": "", "file": "shared/guides/integrated-repo-folder-structure", "itemList": [], "isExternal": false, - "path": "/more-concepts/folder-structure", + "path": "/concepts/more-concepts/folder-structure", "tags": [] }, - "/more-concepts/nx-devkit-angular-devkit": { + "/concepts/more-concepts/nx-devkit-angular-devkit": { "id": "nx-devkit-angular-devkit", "name": "Nx Devkit and Angular Devkit", "description": "", "file": "shared/guides/nx-devkit-angular-devkit", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-devkit-angular-devkit", + "path": "/concepts/more-concepts/nx-devkit-angular-devkit", "tags": ["create-your-own-plugin"] }, - "/more-concepts/micro-frontend-architecture": { + "/concepts/more-concepts/micro-frontend-architecture": { "id": "micro-frontend-architecture", "name": "Micro Frontend Architecture", "description": "", "file": "shared/guides/module-federation/micro-frontend-architecture", "itemList": [], "isExternal": false, - "path": "/more-concepts/micro-frontend-architecture", + "path": "/concepts/more-concepts/micro-frontend-architecture", "tags": [] }, - "/more-concepts/applications-and-libraries": { + "/concepts/more-concepts/faster-builds-with-module-federation": { + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "tags": ["use-task-executors", "module-federation", "angular", "react"] + }, + "/concepts/more-concepts/applications-and-libraries": { "id": "applications-and-libraries", "name": "Applications and Libraries", "description": "", "file": "shared/workspace/applications-and-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/applications-and-libraries", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/applications-and-libraries", + "tags": ["enforce-module-boundaries"] }, - "/more-concepts/creating-libraries": { + "/concepts/more-concepts/creating-libraries": { "id": "creating-libraries", "name": "Creating Libraries", "description": "", "file": "shared/workspace/creating-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/creating-libraries", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/creating-libraries", + "tags": ["enforce-module-boundaries"] }, - "/more-concepts/library-types": { + "/concepts/more-concepts/library-types": { "id": "library-types", "name": "Library Types", "description": "", "file": "shared/workspace/library-types", "itemList": [], "isExternal": false, - "path": "/more-concepts/library-types", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/library-types", + "tags": ["enforce-module-boundaries"] }, - "/more-concepts/grouping-libraries": { + "/concepts/more-concepts/grouping-libraries": { "id": "grouping-libraries", "name": "Grouping Libraries", "description": "", "file": "shared/workspace/grouping-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/grouping-libraries", - "tags": ["enforce-project-boundaries"] + "path": "/concepts/more-concepts/grouping-libraries", + "tags": ["enforce-module-boundaries"] }, - "/more-concepts/buildable-and-publishable-libraries": { + "/concepts/more-concepts/buildable-and-publishable-libraries": { "id": "buildable-and-publishable-libraries", "name": "Buildable and Publishable Libraries", "description": "", "file": "shared/workspace/buildable-and-publishable-libraries", "itemList": [], "isExternal": false, - "path": "/more-concepts/buildable-and-publishable-libraries", + "path": "/concepts/more-concepts/buildable-and-publishable-libraries", "tags": [] }, - "/more-concepts/how-project-graph-is-built": { + "/concepts/more-concepts/how-project-graph-is-built": { "id": "how-project-graph-is-built", "name": "How the Project Graph is Built", "description": "", "file": "shared/concepts/how-project-graph-is-built", "itemList": [], "isExternal": false, - "path": "/more-concepts/how-project-graph-is-built", + "path": "/concepts/more-concepts/how-project-graph-is-built", "tags": ["explore-graph"] }, - "/more-concepts/nx-and-the-wrapper": { + "/concepts/more-concepts/nx-and-the-wrapper": { "id": "nx-and-the-wrapper", "name": "Nx and the Nx Wrapper", "description": "", "file": "shared/guides/nx-and-the-wrapper", "itemList": [], "isExternal": false, - "path": "/more-concepts/nx-and-the-wrapper", + "path": "/concepts/more-concepts/nx-and-the-wrapper", "tags": [] }, - "/more-concepts/global-nx": { + "/concepts/more-concepts/global-nx": { "id": "global-nx", "name": "Managing your Global Nx Installation", "description": "", "file": "shared/guides/global-nx", "itemList": [], "isExternal": false, - "path": "/more-concepts/global-nx", + "path": "/concepts/more-concepts/global-nx", "tags": [] }, "/recipes": { - "id": "all", - "name": "All Recipes »", - "description": "", - "file": "", - "itemList": [], - "isExternal": false, - "path": "/recipes", - "tags": [] - }, - "/recipes/ci/ci-setup": { - "id": "ci-setup", - "name": "CI Setup", - "description": "", - "file": "", - "itemList": [], - "isExternal": false, - "path": "/recipes/ci/ci-setup", - "tags": [] - }, - "/recipes/adopting-nx": { - "id": "adopting-nx", - "name": "Adopting Nx", - "description": "", + "id": "recipes", + "name": "Recipes", + "description": "In depth recipes for common tasks", "file": "", - "itemList": [], - "isExternal": false, - "path": "/recipes/adopting-nx", - "tags": [] - }, - "/reference": { - "id": "reference", - "name": "Reference", - "description": "Understand how to use Nx functionalities, what arguments and options are available for each component.", + "itemList": [ + { + "id": "adopting-nx", + "name": "Adopting Nx", + "description": "Adopting Nx incrementally, on existing project or from scratch.", + "file": "", + "itemList": [ + { + "id": "adding-to-monorepo", + "name": "NPM/Yarn/PNPM workspaces", + "description": "", + "file": "shared/migration/adding-to-monorepo", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-monorepo", + "tags": [] + }, + { + "id": "adding-to-existing-project", + "name": "Add to any Project", + "description": "", + "file": "shared/migration/adding-to-existing-project", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-existing-project", + "tags": [] + }, + { + "id": "lerna-and-nx", + "name": "Nx and Lerna", + "description": "", + "file": "shared/migration/lerna-and-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/lerna-and-nx", + "tags": [] + }, + { + "id": "preserving-git-histories", + "name": "Preserving Git Histories", + "description": "", + "file": "shared/migration/preserving-git-histories", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/preserving-git-histories", + "tags": [] + }, + { + "id": "manual", + "name": "Manual migration", + "description": "", + "file": "shared/migration/manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/manual", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/adopting-nx", + "tags": [] + }, + { + "id": "react", + "name": "React", + "description": "Advanced guides to adopt Nx in React.", + "file": "", + "itemList": [ + { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/react", + "tags": [] + }, + { + "id": "angular", + "name": "Angular", + "description": "Advanced guides to adopt Nx in Angular.", + "file": "", + "itemList": [ + { + "id": "migration", + "name": "Migration", + "description": "", + "file": "", + "itemList": [ + { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular/migration", + "tags": [] + }, + { + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "description": "", + "file": "shared/guides/use-environment-variables-in-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/use-environment-variables-in-angular", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-with-angular-projects", + "name": "Using Tailwind CSS with Angular projects", + "description": "", + "file": "shared/guides/using-tailwind-css-with-angular-projects", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for Angular", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "dynamic-module-federation-with-angular", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "description": "", + "file": "shared/guides/module-federation/dynamic-mfe-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "setup-incremental-builds-angular", + "name": "Setup incremental builds for Angular applications", + "description": "", + "file": "shared/guides/setup-incremental-builds-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/setup-incremental-builds-angular", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular", + "tags": [] + }, + { + "id": "node", + "name": "Node", + "description": "Set of Node related recipes.", + "file": "", + "itemList": [ + { + "id": "node-server-fly-io", + "name": "Deploying a Node App to Fly.io", + "description": "", + "file": "shared/recipes/deployment/node-server-fly-io", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-server-fly-io", + "tags": ["deployment", "node"] + }, + { + "id": "node-serverless-functions-netlify", + "name": "Add and Deploy Netlify Edge Functions with Node", + "description": "", + "file": "shared/recipes/deployment/node-serverless-functions-netlify", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-serverless-functions-netlify", + "tags": ["deployment", "node"] + }, + { + "id": "node-aws-lambda", + "name": "Deploying AWS lambda in Node.js", + "description": "", + "file": "shared/recipes/deployment/node-aws-lambda", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-aws-lambda", + "tags": ["deployment", "node"] + } + ], + "isExternal": false, + "path": "/recipes/node", + "tags": [] + }, + { + "id": "storybook", + "name": "Storybook", + "description": "Storybook how tos.", + "file": "", + "itemList": [ + { + "id": "one-storybook-for-all", + "name": "One main Storybook instance for all projects", + "description": "", + "file": "shared/recipes/one-storybook-for-all", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-for-all", + "tags": ["storybook"] + }, + { + "id": "one-storybook-per-scope", + "name": "One Storybook instance per scope", + "description": "", + "file": "shared/recipes/one-storybook-per-scope", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-per-scope", + "tags": ["storybook"] + }, + { + "id": "one-storybook-with-composition", + "name": "One main Storybook instance using Storybook Composition", + "description": "", + "file": "shared/recipes/one-storybook-with-composition", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-with-composition", + "tags": ["storybook"] + } + ], + "isExternal": false, + "path": "/recipes/storybook", + "tags": [] + }, + { + "id": "enforce-module-boundaries", + "name": "Enforce Module Boundaries", + "description": "Configuring the enforce module boundaries rule", + "file": "", + "itemList": [ + { + "id": "ban-dependencies-with-tags", + "name": "Ban Dependencies with Certain Tags", + "description": "", + "file": "shared/recipes/ban-dependencies-with-tags", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "tag-multiple-dimensions", + "name": "Tag in Multiple Dimensions", + "description": "", + "file": "shared/recipes/tag-multiple-dimensions", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "ban-external-imports", + "name": "Ban External Imports", + "description": "", + "file": "shared/recipes/ban-external-imports", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "tags-allow-list", + "name": "Tags Allow List", + "description": "", + "file": "shared/recipes/tags-allow-list", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "tags": ["enforce-module-boundaries"] + } + ], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries", + "tags": [] + }, + { + "id": "ci", + "name": "CI", + "description": "All recipes about how to use Nx to make your CI faster.", + "file": "", + "itemList": [ + { + "id": "ci-setup", + "name": "CI Setup", + "description": "", + "file": "shared/ci-overview", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-setup", + "tags": ["distribute-task-execution"] + }, + { + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "description": "", + "file": "shared/recipes/ci-deployment", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-deployment", + "tags": ["docker", "deploy"] + }, + { + "id": "monorepo-ci-azure", + "name": "Setting up Azure Pipelines", + "description": "", + "file": "shared/monorepo-ci-azure", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-azure", + "tags": [] + }, + { + "id": "monorepo-ci-circle-ci", + "name": "Setting up CircleCI", + "description": "", + "file": "shared/monorepo-ci-circle-ci", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-circle-ci", + "tags": [] + }, + { + "id": "monorepo-ci-github-actions", + "name": "Setting up GitHub Actions", + "description": "", + "file": "shared/monorepo-ci-github-actions", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-github-actions", + "tags": [] + }, + { + "id": "monorepo-ci-jenkins", + "name": "Setting up Jenkins", + "description": "", + "file": "shared/monorepo-ci-jenkins", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-jenkins", + "tags": [] + }, + { + "id": "monorepo-ci-gitlab", + "name": "Setting up GitLab", + "description": "", + "file": "shared/monorepo-ci-gitlab", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-gitlab", + "tags": [] + }, + { + "id": "monorepo-ci-bitbucket-pipelines", + "name": "Setting up Bitbucket", + "description": "", + "file": "shared/monorepo-ci-bitbucket-pipelines", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/ci", + "tags": [] + }, + { + "id": "tips-n-tricks", + "name": "Tips and tricks", + "description": "Various tips and tricks for using Nx.", + "file": "", + "itemList": [ + { + "id": "package-based-in-integrated", + "name": "Add a Package-based Project in an Integrated Repo", + "description": "", + "file": "shared/recipes/repo-types/package-based-in-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/package-based-in-integrated", + "tags": ["repository-types"] + }, + { + "id": "integrated-in-package-based", + "name": "Add an Integrated Project in a Package-based Repo", + "description": "", + "file": "shared/recipes/repo-types/integrated-in-package-based", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/integrated-in-package-based", + "tags": ["repository-types"] + }, + { + "id": "eslint", + "name": "Configuring ESLint with Typescript", + "description": "", + "file": "shared/eslint", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/eslint", + "tags": [] + }, + { + "id": "define-environment-variables", + "name": "Define Environment Variables", + "description": "", + "file": "shared/guides/define-environment-variables", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/define-environment-variables", + "tags": ["environment-variables"] + }, + { + "id": "browser-support", + "name": "Configuring Browser Support", + "description": "", + "file": "shared/guides/browser-support", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/browser-support", + "tags": [] + }, + { + "id": "include-assets-in-build", + "name": "Include Assets in Build", + "description": "", + "file": "shared/recipes/include-assets-in-build", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "tags": [] + }, + { + "id": "include-all-packagejson", + "name": "Include All package.json Files as Projects", + "description": "", + "file": "shared/recipes/include-all-packagejson", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "tags": [] + }, + { + "id": "identify-dependencies-between-folders", + "name": "Identify Dependencies Between Folders", + "description": "", + "file": "shared/recipes/identify-dependencies-between-folders", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "tags": [] + }, + { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/root-level-scripts", + "tags": ["run-tasks"] + }, + { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/analyze-source-files", + "tags": ["explore-graph"] + }, + { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/workspace-watching", + "tags": ["workspace-watching"] + }, + { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "tags": ["repository-types"] + }, + { + "id": "js-and-ts", + "name": "Use JavaScript instead TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/js-and-ts", + "tags": [] + }, + { + "id": "advanced-update", + "name": "Altering Migration Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + { + "id": "run-commands-executor", + "name": "Running Custom Commands", + "description": "", + "file": "shared/running-custom-commands", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/run-commands-executor", + "tags": ["use-task-executors"] + } + ], + "isExternal": false, + "path": "/recipes/tips-n-tricks", + "tags": [] + }, + { + "id": "troubleshooting", + "name": "Troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "file": "", + "itemList": [ + { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + } + ], + "isExternal": false, + "path": "/recipes/troubleshooting", + "tags": [] + }, + { + "id": "nx-console", + "name": "Nx Console", + "description": "Checkout all the recipes related to Nx Console.", + "file": "", + "itemList": [ + { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + } + ], + "isExternal": false, + "path": "/recipes/nx-console", + "tags": [] + }, + { + "id": "other", + "name": "Other", + "description": "Other recipes you will find useful.", + "file": "", + "itemList": [ + { + "id": "deno-deploy", + "name": "Serverless deployment with Deno Deploy", + "description": "", + "file": "shared/recipes/deployment/deno-deploy", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-deploy", + "tags": ["deployment", "deno"] + }, + { + "id": "deno-netlify-functions", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "description": "", + "file": "shared/recipes/deployment/deno-netlify-edge-functions", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-netlify-functions", + "tags": ["deployment", "deno"] + }, + { + "id": "rescope", + "name": "Rescope Packages from @nrwl to @nx", + "description": "", + "file": "shared/recipes/rescope", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/rescope", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/other", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes", + "tags": [] + }, + "/recipes/adopting-nx": { + "id": "adopting-nx", + "name": "Adopting Nx", + "description": "Adopting Nx incrementally, on existing project or from scratch.", + "file": "", + "itemList": [ + { + "id": "adding-to-monorepo", + "name": "NPM/Yarn/PNPM workspaces", + "description": "", + "file": "shared/migration/adding-to-monorepo", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-monorepo", + "tags": [] + }, + { + "id": "adding-to-existing-project", + "name": "Add to any Project", + "description": "", + "file": "shared/migration/adding-to-existing-project", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-existing-project", + "tags": [] + }, + { + "id": "lerna-and-nx", + "name": "Nx and Lerna", + "description": "", + "file": "shared/migration/lerna-and-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/lerna-and-nx", + "tags": [] + }, + { + "id": "preserving-git-histories", + "name": "Preserving Git Histories", + "description": "", + "file": "shared/migration/preserving-git-histories", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/preserving-git-histories", + "tags": [] + }, + { + "id": "manual", + "name": "Manual migration", + "description": "", + "file": "shared/migration/manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/manual", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/adopting-nx", + "tags": [] + }, + "/recipes/adopting-nx/adding-to-monorepo": { + "id": "adding-to-monorepo", + "name": "NPM/Yarn/PNPM workspaces", + "description": "", + "file": "shared/migration/adding-to-monorepo", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-monorepo", + "tags": [] + }, + "/recipes/adopting-nx/adding-to-existing-project": { + "id": "adding-to-existing-project", + "name": "Add to any Project", + "description": "", + "file": "shared/migration/adding-to-existing-project", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-existing-project", + "tags": [] + }, + "/recipes/adopting-nx/lerna-and-nx": { + "id": "lerna-and-nx", + "name": "Nx and Lerna", + "description": "", + "file": "shared/migration/lerna-and-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/lerna-and-nx", + "tags": [] + }, + "/recipes/adopting-nx/preserving-git-histories": { + "id": "preserving-git-histories", + "name": "Preserving Git Histories", + "description": "", + "file": "shared/migration/preserving-git-histories", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/preserving-git-histories", + "tags": [] + }, + "/recipes/adopting-nx/manual": { + "id": "manual", + "name": "Manual migration", + "description": "", + "file": "shared/migration/manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/manual", + "tags": [] + }, + "/recipes/react": { + "id": "react", + "name": "React", + "description": "Advanced guides to adopt Nx in React.", + "file": "", + "itemList": [ + { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/react", + "tags": [] + }, + "/recipes/react/migration-cra": { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + "/recipes/react/react-18": { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + "/recipes/react/react-native": { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + "/recipes/react/remix": { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + "/recipes/react/use-environment-variables-in-react": { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + "/recipes/react/using-tailwind-css-in-react": { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + "/recipes/react/adding-assets-react": { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + "/recipes/react/module-federation-with-ssr": { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + "/recipes/react/deploy-nextjs-to-vercel": { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + }, + "/recipes/angular": { + "id": "angular", + "name": "Angular", + "description": "Advanced guides to adopt Nx in Angular.", + "file": "", + "itemList": [ + { + "id": "migration", + "name": "Migration", + "description": "", + "file": "", + "itemList": [ + { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular/migration", + "tags": [] + }, + { + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "description": "", + "file": "shared/guides/use-environment-variables-in-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/use-environment-variables-in-angular", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-with-angular-projects", + "name": "Using Tailwind CSS with Angular projects", + "description": "", + "file": "shared/guides/using-tailwind-css-with-angular-projects", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for Angular", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "dynamic-module-federation-with-angular", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "description": "", + "file": "shared/guides/module-federation/dynamic-mfe-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "setup-incremental-builds-angular", + "name": "Setup incremental builds for Angular applications", + "description": "", + "file": "shared/guides/setup-incremental-builds-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/setup-incremental-builds-angular", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular", + "tags": [] + }, + "/recipes/angular/migration": { + "id": "migration", + "name": "Migration", + "description": "", + "file": "", + "itemList": [ + { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular/migration", + "tags": [] + }, + "/recipes/angular/migration/angular": { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + "/recipes/angular/migration/angular-multiple": { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + "/recipes/angular/migration/angular-manual": { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + "/recipes/angular/migration/angularjs": { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + }, + "/recipes/angular/use-environment-variables-in-angular": { + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "description": "", + "file": "shared/guides/use-environment-variables-in-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/use-environment-variables-in-angular", + "tags": ["environment-variables"] + }, + "/recipes/angular/using-tailwind-css-with-angular-projects": { + "id": "using-tailwind-css-with-angular-projects", + "name": "Using Tailwind CSS with Angular projects", + "description": "", + "file": "shared/guides/using-tailwind-css-with-angular-projects", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "tags": [] + }, + "/recipes/angular/module-federation-with-ssr": { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for Angular", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + "/recipes/angular/dynamic-module-federation-with-angular": { + "id": "dynamic-module-federation-with-angular", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "description": "", + "file": "shared/guides/module-federation/dynamic-mfe-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + "/recipes/angular/setup-incremental-builds-angular": { + "id": "setup-incremental-builds-angular", + "name": "Setup incremental builds for Angular applications", + "description": "", + "file": "shared/guides/setup-incremental-builds-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/setup-incremental-builds-angular", + "tags": [] + }, + "/recipes/node": { + "id": "node", + "name": "Node", + "description": "Set of Node related recipes.", + "file": "", + "itemList": [ + { + "id": "node-server-fly-io", + "name": "Deploying a Node App to Fly.io", + "description": "", + "file": "shared/recipes/deployment/node-server-fly-io", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-server-fly-io", + "tags": ["deployment", "node"] + }, + { + "id": "node-serverless-functions-netlify", + "name": "Add and Deploy Netlify Edge Functions with Node", + "description": "", + "file": "shared/recipes/deployment/node-serverless-functions-netlify", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-serverless-functions-netlify", + "tags": ["deployment", "node"] + }, + { + "id": "node-aws-lambda", + "name": "Deploying AWS lambda in Node.js", + "description": "", + "file": "shared/recipes/deployment/node-aws-lambda", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-aws-lambda", + "tags": ["deployment", "node"] + } + ], + "isExternal": false, + "path": "/recipes/node", + "tags": [] + }, + "/recipes/node/node-server-fly-io": { + "id": "node-server-fly-io", + "name": "Deploying a Node App to Fly.io", + "description": "", + "file": "shared/recipes/deployment/node-server-fly-io", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-server-fly-io", + "tags": ["deployment", "node"] + }, + "/recipes/node/node-serverless-functions-netlify": { + "id": "node-serverless-functions-netlify", + "name": "Add and Deploy Netlify Edge Functions with Node", + "description": "", + "file": "shared/recipes/deployment/node-serverless-functions-netlify", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-serverless-functions-netlify", + "tags": ["deployment", "node"] + }, + "/recipes/node/node-aws-lambda": { + "id": "node-aws-lambda", + "name": "Deploying AWS lambda in Node.js", + "description": "", + "file": "shared/recipes/deployment/node-aws-lambda", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-aws-lambda", + "tags": ["deployment", "node"] + }, + "/recipes/storybook": { + "id": "storybook", + "name": "Storybook", + "description": "Storybook how tos.", + "file": "", + "itemList": [ + { + "id": "one-storybook-for-all", + "name": "One main Storybook instance for all projects", + "description": "", + "file": "shared/recipes/one-storybook-for-all", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-for-all", + "tags": ["storybook"] + }, + { + "id": "one-storybook-per-scope", + "name": "One Storybook instance per scope", + "description": "", + "file": "shared/recipes/one-storybook-per-scope", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-per-scope", + "tags": ["storybook"] + }, + { + "id": "one-storybook-with-composition", + "name": "One main Storybook instance using Storybook Composition", + "description": "", + "file": "shared/recipes/one-storybook-with-composition", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-with-composition", + "tags": ["storybook"] + } + ], + "isExternal": false, + "path": "/recipes/storybook", + "tags": [] + }, + "/recipes/storybook/one-storybook-for-all": { + "id": "one-storybook-for-all", + "name": "One main Storybook instance for all projects", + "description": "", + "file": "shared/recipes/one-storybook-for-all", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-for-all", + "tags": ["storybook"] + }, + "/recipes/storybook/one-storybook-per-scope": { + "id": "one-storybook-per-scope", + "name": "One Storybook instance per scope", + "description": "", + "file": "shared/recipes/one-storybook-per-scope", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-per-scope", + "tags": ["storybook"] + }, + "/recipes/storybook/one-storybook-with-composition": { + "id": "one-storybook-with-composition", + "name": "One main Storybook instance using Storybook Composition", + "description": "", + "file": "shared/recipes/one-storybook-with-composition", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-with-composition", + "tags": ["storybook"] + }, + "/recipes/enforce-module-boundaries": { + "id": "enforce-module-boundaries", + "name": "Enforce Module Boundaries", + "description": "Configuring the enforce module boundaries rule", + "file": "", + "itemList": [ + { + "id": "ban-dependencies-with-tags", + "name": "Ban Dependencies with Certain Tags", + "description": "", + "file": "shared/recipes/ban-dependencies-with-tags", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "tag-multiple-dimensions", + "name": "Tag in Multiple Dimensions", + "description": "", + "file": "shared/recipes/tag-multiple-dimensions", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "ban-external-imports", + "name": "Ban External Imports", + "description": "", + "file": "shared/recipes/ban-external-imports", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "tags": ["enforce-module-boundaries"] + }, + { + "id": "tags-allow-list", + "name": "Tags Allow List", + "description": "", + "file": "shared/recipes/tags-allow-list", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "tags": ["enforce-module-boundaries"] + } + ], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries", + "tags": [] + }, + "/recipes/enforce-module-boundaries/ban-dependencies-with-tags": { + "id": "ban-dependencies-with-tags", + "name": "Ban Dependencies with Certain Tags", + "description": "", + "file": "shared/recipes/ban-dependencies-with-tags", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "tags": ["enforce-module-boundaries"] + }, + "/recipes/enforce-module-boundaries/tag-multiple-dimensions": { + "id": "tag-multiple-dimensions", + "name": "Tag in Multiple Dimensions", + "description": "", + "file": "shared/recipes/tag-multiple-dimensions", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "tags": ["enforce-module-boundaries"] + }, + "/recipes/enforce-module-boundaries/ban-external-imports": { + "id": "ban-external-imports", + "name": "Ban External Imports", + "description": "", + "file": "shared/recipes/ban-external-imports", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "tags": ["enforce-module-boundaries"] + }, + "/recipes/enforce-module-boundaries/tags-allow-list": { + "id": "tags-allow-list", + "name": "Tags Allow List", + "description": "", + "file": "shared/recipes/tags-allow-list", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "tags": ["enforce-module-boundaries"] + }, + "/recipes/ci": { + "id": "ci", + "name": "CI", + "description": "All recipes about how to use Nx to make your CI faster.", + "file": "", + "itemList": [ + { + "id": "ci-setup", + "name": "CI Setup", + "description": "", + "file": "shared/ci-overview", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-setup", + "tags": ["distribute-task-execution"] + }, + { + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "description": "", + "file": "shared/recipes/ci-deployment", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-deployment", + "tags": ["docker", "deploy"] + }, + { + "id": "monorepo-ci-azure", + "name": "Setting up Azure Pipelines", + "description": "", + "file": "shared/monorepo-ci-azure", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-azure", + "tags": [] + }, + { + "id": "monorepo-ci-circle-ci", + "name": "Setting up CircleCI", + "description": "", + "file": "shared/monorepo-ci-circle-ci", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-circle-ci", + "tags": [] + }, + { + "id": "monorepo-ci-github-actions", + "name": "Setting up GitHub Actions", + "description": "", + "file": "shared/monorepo-ci-github-actions", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-github-actions", + "tags": [] + }, + { + "id": "monorepo-ci-jenkins", + "name": "Setting up Jenkins", + "description": "", + "file": "shared/monorepo-ci-jenkins", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-jenkins", + "tags": [] + }, + { + "id": "monorepo-ci-gitlab", + "name": "Setting up GitLab", + "description": "", + "file": "shared/monorepo-ci-gitlab", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-gitlab", + "tags": [] + }, + { + "id": "monorepo-ci-bitbucket-pipelines", + "name": "Setting up Bitbucket", + "description": "", + "file": "shared/monorepo-ci-bitbucket-pipelines", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/ci", + "tags": [] + }, + "/recipes/ci/ci-setup": { + "id": "ci-setup", + "name": "CI Setup", + "description": "", + "file": "shared/ci-overview", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-setup", + "tags": ["distribute-task-execution"] + }, + "/recipes/ci/ci-deployment": { + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "description": "", + "file": "shared/recipes/ci-deployment", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-deployment", + "tags": ["docker", "deploy"] + }, + "/recipes/ci/monorepo-ci-azure": { + "id": "monorepo-ci-azure", + "name": "Setting up Azure Pipelines", + "description": "", + "file": "shared/monorepo-ci-azure", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-azure", + "tags": [] + }, + "/recipes/ci/monorepo-ci-circle-ci": { + "id": "monorepo-ci-circle-ci", + "name": "Setting up CircleCI", + "description": "", + "file": "shared/monorepo-ci-circle-ci", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-circle-ci", + "tags": [] + }, + "/recipes/ci/monorepo-ci-github-actions": { + "id": "monorepo-ci-github-actions", + "name": "Setting up GitHub Actions", + "description": "", + "file": "shared/monorepo-ci-github-actions", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-github-actions", + "tags": [] + }, + "/recipes/ci/monorepo-ci-jenkins": { + "id": "monorepo-ci-jenkins", + "name": "Setting up Jenkins", + "description": "", + "file": "shared/monorepo-ci-jenkins", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-jenkins", + "tags": [] + }, + "/recipes/ci/monorepo-ci-gitlab": { + "id": "monorepo-ci-gitlab", + "name": "Setting up GitLab", + "description": "", + "file": "shared/monorepo-ci-gitlab", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-gitlab", + "tags": [] + }, + "/recipes/ci/monorepo-ci-bitbucket-pipelines": { + "id": "monorepo-ci-bitbucket-pipelines", + "name": "Setting up Bitbucket", + "description": "", + "file": "shared/monorepo-ci-bitbucket-pipelines", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "tags": [] + }, + "/recipes/tips-n-tricks": { + "id": "tips-n-tricks", + "name": "Tips and tricks", + "description": "Various tips and tricks for using Nx.", + "file": "", + "itemList": [ + { + "id": "package-based-in-integrated", + "name": "Add a Package-based Project in an Integrated Repo", + "description": "", + "file": "shared/recipes/repo-types/package-based-in-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/package-based-in-integrated", + "tags": ["repository-types"] + }, + { + "id": "integrated-in-package-based", + "name": "Add an Integrated Project in a Package-based Repo", + "description": "", + "file": "shared/recipes/repo-types/integrated-in-package-based", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/integrated-in-package-based", + "tags": ["repository-types"] + }, + { + "id": "eslint", + "name": "Configuring ESLint with Typescript", + "description": "", + "file": "shared/eslint", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/eslint", + "tags": [] + }, + { + "id": "define-environment-variables", + "name": "Define Environment Variables", + "description": "", + "file": "shared/guides/define-environment-variables", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/define-environment-variables", + "tags": ["environment-variables"] + }, + { + "id": "browser-support", + "name": "Configuring Browser Support", + "description": "", + "file": "shared/guides/browser-support", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/browser-support", + "tags": [] + }, + { + "id": "include-assets-in-build", + "name": "Include Assets in Build", + "description": "", + "file": "shared/recipes/include-assets-in-build", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "tags": [] + }, + { + "id": "include-all-packagejson", + "name": "Include All package.json Files as Projects", + "description": "", + "file": "shared/recipes/include-all-packagejson", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "tags": [] + }, + { + "id": "identify-dependencies-between-folders", + "name": "Identify Dependencies Between Folders", + "description": "", + "file": "shared/recipes/identify-dependencies-between-folders", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "tags": [] + }, + { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/root-level-scripts", + "tags": ["run-tasks"] + }, + { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/analyze-source-files", + "tags": ["explore-graph"] + }, + { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/workspace-watching", + "tags": ["workspace-watching"] + }, + { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "tags": ["repository-types"] + }, + { + "id": "js-and-ts", + "name": "Use JavaScript instead TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/js-and-ts", + "tags": [] + }, + { + "id": "advanced-update", + "name": "Altering Migration Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + { + "id": "run-commands-executor", + "name": "Running Custom Commands", + "description": "", + "file": "shared/running-custom-commands", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/run-commands-executor", + "tags": ["use-task-executors"] + } + ], + "isExternal": false, + "path": "/recipes/tips-n-tricks", + "tags": [] + }, + "/recipes/tips-n-tricks/package-based-in-integrated": { + "id": "package-based-in-integrated", + "name": "Add a Package-based Project in an Integrated Repo", + "description": "", + "file": "shared/recipes/repo-types/package-based-in-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/package-based-in-integrated", + "tags": ["repository-types"] + }, + "/recipes/tips-n-tricks/integrated-in-package-based": { + "id": "integrated-in-package-based", + "name": "Add an Integrated Project in a Package-based Repo", + "description": "", + "file": "shared/recipes/repo-types/integrated-in-package-based", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/integrated-in-package-based", + "tags": ["repository-types"] + }, + "/recipes/tips-n-tricks/eslint": { + "id": "eslint", + "name": "Configuring ESLint with Typescript", + "description": "", + "file": "shared/eslint", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/eslint", + "tags": [] + }, + "/recipes/tips-n-tricks/define-environment-variables": { + "id": "define-environment-variables", + "name": "Define Environment Variables", + "description": "", + "file": "shared/guides/define-environment-variables", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/define-environment-variables", + "tags": ["environment-variables"] + }, + "/recipes/tips-n-tricks/browser-support": { + "id": "browser-support", + "name": "Configuring Browser Support", + "description": "", + "file": "shared/guides/browser-support", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/browser-support", + "tags": [] + }, + "/recipes/tips-n-tricks/include-assets-in-build": { + "id": "include-assets-in-build", + "name": "Include Assets in Build", + "description": "", + "file": "shared/recipes/include-assets-in-build", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "tags": [] + }, + "/recipes/tips-n-tricks/include-all-packagejson": { + "id": "include-all-packagejson", + "name": "Include All package.json Files as Projects", + "description": "", + "file": "shared/recipes/include-all-packagejson", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "tags": [] + }, + "/recipes/tips-n-tricks/identify-dependencies-between-folders": { + "id": "identify-dependencies-between-folders", + "name": "Identify Dependencies Between Folders", + "description": "", + "file": "shared/recipes/identify-dependencies-between-folders", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "tags": [] + }, + "/recipes/tips-n-tricks/root-level-scripts": { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/root-level-scripts", + "tags": ["run-tasks"] + }, + "/recipes/tips-n-tricks/analyze-source-files": { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/analyze-source-files", + "tags": ["explore-graph"] + }, + "/recipes/tips-n-tricks/workspace-watching": { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/workspace-watching", + "tags": ["workspace-watching"] + }, + "/recipes/tips-n-tricks/standalone-to-integrated": { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "tags": ["repository-types"] + }, + "/recipes/tips-n-tricks/js-and-ts": { + "id": "js-and-ts", + "name": "Use JavaScript instead TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/js-and-ts", + "tags": [] + }, + "/recipes/tips-n-tricks/advanced-update": { + "id": "advanced-update", + "name": "Altering Migration Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + "/recipes/tips-n-tricks/run-commands-executor": { + "id": "run-commands-executor", + "name": "Running Custom Commands", + "description": "", + "file": "shared/running-custom-commands", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/run-commands-executor", + "tags": ["use-task-executors"] + }, + "/recipes/troubleshooting": { + "id": "troubleshooting", + "name": "Troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "file": "", + "itemList": [ + { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + } + ], + "isExternal": false, + "path": "/recipes/troubleshooting", + "tags": [] + }, + "/recipes/troubleshooting/resolve-circular-dependencies": { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + "/recipes/troubleshooting/troubleshoot-nx-install-issues": { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + "/recipes/troubleshooting/troubleshoot-cache-misses": { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + "/recipes/troubleshooting/unknown-local-cache": { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + "/recipes/troubleshooting/performance-profiling": { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + }, + "/recipes/nx-console": { + "id": "nx-console", + "name": "Nx Console", + "description": "Checkout all the recipes related to Nx Console.", + "file": "", + "itemList": [ + { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + } + ], + "isExternal": false, + "path": "/recipes/nx-console", + "tags": [] + }, + "/recipes/nx-console/console-telemetry": { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-generate-command": { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-run-command": { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-add-dependency-command": { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-project-pane": { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-shortcuts": { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + }, + "/recipes/other": { + "id": "other", + "name": "Other", + "description": "Other recipes you will find useful.", + "file": "", + "itemList": [ + { + "id": "deno-deploy", + "name": "Serverless deployment with Deno Deploy", + "description": "", + "file": "shared/recipes/deployment/deno-deploy", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-deploy", + "tags": ["deployment", "deno"] + }, + { + "id": "deno-netlify-functions", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "description": "", + "file": "shared/recipes/deployment/deno-netlify-edge-functions", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-netlify-functions", + "tags": ["deployment", "deno"] + }, + { + "id": "rescope", + "name": "Rescope Packages from @nrwl to @nx", + "description": "", + "file": "shared/recipes/rescope", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/rescope", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/other", + "tags": [] + }, + "/recipes/other/deno-deploy": { + "id": "deno-deploy", + "name": "Serverless deployment with Deno Deploy", + "description": "", + "file": "shared/recipes/deployment/deno-deploy", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-deploy", + "tags": ["deployment", "deno"] + }, + "/recipes/other/deno-netlify-functions": { + "id": "deno-netlify-functions", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "description": "", + "file": "shared/recipes/deployment/deno-netlify-edge-functions", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-netlify-functions", + "tags": ["deployment", "deno"] + }, + "/recipes/other/rescope": { + "id": "rescope", + "name": "Rescope Packages from @nrwl to @nx", + "description": "", + "file": "shared/recipes/rescope", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/rescope", + "tags": [] + }, + "/showcase": { + "id": "showcase", + "name": "Showcase", + "description": "Discover our selection of examples and benchmarks.", + "file": "", + "itemList": [ + { + "id": "example-repos", + "name": "Example Repos", + "description": "Examples of different ways to use Nx", + "file": "", + "itemList": [ + { + "id": "add-lit", + "name": "Add a Lit Project", + "description": "Add a Lit project to your repo", + "file": "shared/recipes/add-stack/add-lit", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-lit", + "tags": [] + }, + { + "id": "add-solid", + "name": "Add a Solid Project", + "description": "Add a Solid project to your repo", + "file": "shared/recipes/add-stack/add-solid", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-solid", + "tags": [] + }, + { + "id": "add-qwik", + "name": "Add a Qwik Project", + "description": "Add a Qwik project to your repo", + "file": "shared/recipes/add-stack/add-qwik", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-qwik", + "tags": [] + }, + { + "id": "react-nx", + "name": "Powering Up React Development With Nx", + "description": "", + "file": "shared/examples/react-nx", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/react-nx", + "tags": [] + }, + { + "id": "apollo-react", + "name": "Using Apollo GraphQL", + "description": "", + "file": "shared/examples/apollo-react", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/apollo-react", + "tags": [] + }, + { + "id": "nestjs-prisma", + "name": "Using Prisma with NestJS", + "description": "", + "file": "shared/recipes/database/nestjs-prisma", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/nestjs-prisma", + "tags": ["database", "node"] + }, + { + "id": "mongo-fastify", + "name": "Using Mongo with Fastify", + "description": "", + "file": "shared/recipes/database/mongo-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mongo-fastify", + "tags": ["database", "node"] + }, + { + "id": "redis-fastify", + "name": "Using Redis with Fastify", + "description": "", + "file": "shared/recipes/database/redis-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/redis-fastify", + "tags": ["database", "node"] + }, + { + "id": "postgres-fastify", + "name": "Using Postgres with Fastify", + "description": "", + "file": "shared/recipes/database/postgres-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/postgres-fastify", + "tags": ["database", "node"] + }, + { + "id": "serverless-fastify-planetscale", + "name": "Using PlanetScale with Serverless Fastify", + "description": "", + "file": "shared/recipes/database/serverless-fastify-planetscale", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"] + }, + { + "id": "caching", + "name": "Large Repo and Caching", + "description": "", + "file": "shared/examples/caching", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/caching", + "tags": [] + }, + { + "id": "dte", + "name": "Large Repo and DTE", + "description": "", + "file": "shared/examples/dte", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/dte", + "tags": [] + }, + { + "id": "mfe", + "name": "Nx Micro-Frontend Example", + "description": "", + "file": "shared/examples/nx-examples", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mfe", + "tags": [] + } + ], + "isExternal": false, + "path": "/showcase/example-repos", + "tags": [] + } + ], + "isExternal": false, + "path": "/showcase", + "tags": [] + }, + "/showcase/example-repos": { + "id": "example-repos", + "name": "Example Repos", + "description": "Examples of different ways to use Nx", "file": "", "itemList": [ { - "id": "commands", - "name": "Commands", + "id": "add-lit", + "name": "Add a Lit Project", + "description": "Add a Lit project to your repo", + "file": "shared/recipes/add-stack/add-lit", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-lit", + "tags": [] + }, + { + "id": "add-solid", + "name": "Add a Solid Project", + "description": "Add a Solid project to your repo", + "file": "shared/recipes/add-stack/add-solid", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-solid", + "tags": [] + }, + { + "id": "add-qwik", + "name": "Add a Qwik Project", + "description": "Add a Qwik project to your repo", + "file": "shared/recipes/add-stack/add-qwik", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-qwik", + "tags": [] + }, + { + "id": "react-nx", + "name": "Powering Up React Development With Nx", + "description": "", + "file": "shared/examples/react-nx", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/react-nx", + "tags": [] + }, + { + "id": "apollo-react", + "name": "Using Apollo GraphQL", + "description": "", + "file": "shared/examples/apollo-react", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/apollo-react", + "tags": [] + }, + { + "id": "nestjs-prisma", + "name": "Using Prisma with NestJS", + "description": "", + "file": "shared/recipes/database/nestjs-prisma", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/nestjs-prisma", + "tags": ["database", "node"] + }, + { + "id": "mongo-fastify", + "name": "Using Mongo with Fastify", + "description": "", + "file": "shared/recipes/database/mongo-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mongo-fastify", + "tags": ["database", "node"] + }, + { + "id": "redis-fastify", + "name": "Using Redis with Fastify", + "description": "", + "file": "shared/recipes/database/redis-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/redis-fastify", + "tags": ["database", "node"] + }, + { + "id": "postgres-fastify", + "name": "Using Postgres with Fastify", + "description": "", + "file": "shared/recipes/database/postgres-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/postgres-fastify", + "tags": ["database", "node"] + }, + { + "id": "serverless-fastify-planetscale", + "name": "Using PlanetScale with Serverless Fastify", + "description": "", + "file": "shared/recipes/database/serverless-fastify-planetscale", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"] + }, + { + "id": "caching", + "name": "Large Repo and Caching", + "description": "", + "file": "shared/examples/caching", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/caching", + "tags": [] + }, + { + "id": "dte", + "name": "Large Repo and DTE", "description": "", - "file": "shared/reference/commands", + "file": "shared/examples/dte", "itemList": [], "isExternal": false, - "path": "/reference/commands", + "path": "/showcase/example-repos/dte", "tags": [] }, + { + "id": "mfe", + "name": "Nx Micro-Frontend Example", + "description": "", + "file": "shared/examples/nx-examples", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mfe", + "tags": [] + } + ], + "isExternal": false, + "path": "/showcase/example-repos", + "tags": [] + }, + "/showcase/example-repos/add-lit": { + "id": "add-lit", + "name": "Add a Lit Project", + "description": "Add a Lit project to your repo", + "file": "shared/recipes/add-stack/add-lit", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-lit", + "tags": [] + }, + "/showcase/example-repos/add-solid": { + "id": "add-solid", + "name": "Add a Solid Project", + "description": "Add a Solid project to your repo", + "file": "shared/recipes/add-stack/add-solid", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-solid", + "tags": [] + }, + "/showcase/example-repos/add-qwik": { + "id": "add-qwik", + "name": "Add a Qwik Project", + "description": "Add a Qwik project to your repo", + "file": "shared/recipes/add-stack/add-qwik", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-qwik", + "tags": [] + }, + "/showcase/example-repos/react-nx": { + "id": "react-nx", + "name": "Powering Up React Development With Nx", + "description": "", + "file": "shared/examples/react-nx", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/react-nx", + "tags": [] + }, + "/showcase/example-repos/apollo-react": { + "id": "apollo-react", + "name": "Using Apollo GraphQL", + "description": "", + "file": "shared/examples/apollo-react", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/apollo-react", + "tags": [] + }, + "/showcase/example-repos/nestjs-prisma": { + "id": "nestjs-prisma", + "name": "Using Prisma with NestJS", + "description": "", + "file": "shared/recipes/database/nestjs-prisma", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/nestjs-prisma", + "tags": ["database", "node"] + }, + "/showcase/example-repos/mongo-fastify": { + "id": "mongo-fastify", + "name": "Using Mongo with Fastify", + "description": "", + "file": "shared/recipes/database/mongo-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mongo-fastify", + "tags": ["database", "node"] + }, + "/showcase/example-repos/redis-fastify": { + "id": "redis-fastify", + "name": "Using Redis with Fastify", + "description": "", + "file": "shared/recipes/database/redis-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/redis-fastify", + "tags": ["database", "node"] + }, + "/showcase/example-repos/postgres-fastify": { + "id": "postgres-fastify", + "name": "Using Postgres with Fastify", + "description": "", + "file": "shared/recipes/database/postgres-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/postgres-fastify", + "tags": ["database", "node"] + }, + "/showcase/example-repos/serverless-fastify-planetscale": { + "id": "serverless-fastify-planetscale", + "name": "Using PlanetScale with Serverless Fastify", + "description": "", + "file": "shared/recipes/database/serverless-fastify-planetscale", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"] + }, + "/showcase/example-repos/caching": { + "id": "caching", + "name": "Large Repo and Caching", + "description": "", + "file": "shared/examples/caching", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/caching", + "tags": [] + }, + "/showcase/example-repos/dte": { + "id": "dte", + "name": "Large Repo and DTE", + "description": "", + "file": "shared/examples/dte", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/dte", + "tags": [] + }, + "/showcase/example-repos/mfe": { + "id": "mfe", + "name": "Nx Micro-Frontend Example", + "description": "", + "file": "shared/examples/nx-examples", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mfe", + "tags": [] + }, + "/reference": { + "id": "reference", + "name": "Reference", + "description": "Understand how to use Nx functionalities, what arguments and options are available for each component.", + "file": "", + "itemList": [ { "id": "nx-json", - "name": "nx.json", + "name": "Nx Configuration", "description": "", "file": "shared/reference/nx-json", "itemList": [], @@ -1816,7 +4902,7 @@ "itemList": [], "isExternal": false, "path": "/reference/nxignore", - "tags": ["enforce-project-boundaries"] + "tags": ["enforce-module-boundaries"] }, { "id": "environment-variables", @@ -1828,26 +4914,6 @@ "path": "/reference/environment-variables", "tags": ["environment-variables"] }, - { - "id": "packages", - "name": "Packages", - "description": "", - "file": "", - "itemList": [], - "isExternal": true, - "path": "/packages", - "tags": [] - }, - { - "id": "packages-devkit", - "name": "Nx Devkit", - "description": "", - "file": "", - "itemList": [], - "isExternal": true, - "path": "/packages/devkit/documents/nx_devkit", - "tags": ["create-your-own-plugin"] - }, { "id": "glossary", "name": "Glossary", @@ -1857,35 +4923,15 @@ "isExternal": false, "path": "/reference/glossary", "tags": [] - }, - { - "id": "changelog", - "name": "Changelog", - "description": "", - "file": "", - "itemList": [], - "isExternal": true, - "path": "/reference/changelog", - "tags": [] } ], "isExternal": false, "path": "/reference", "tags": [] }, - "/reference/commands": { - "id": "commands", - "name": "Commands", - "description": "", - "file": "shared/reference/commands", - "itemList": [], - "isExternal": false, - "path": "/reference/commands", - "tags": [] - }, "/reference/nx-json": { "id": "nx-json", - "name": "nx.json", + "name": "Nx Configuration", "description": "", "file": "shared/reference/nx-json", "itemList": [], @@ -1911,7 +4957,7 @@ "itemList": [], "isExternal": false, "path": "/reference/nxignore", - "tags": ["enforce-project-boundaries"] + "tags": ["enforce-module-boundaries"] }, "/reference/environment-variables": { "id": "environment-variables", @@ -1923,26 +4969,6 @@ "path": "/reference/environment-variables", "tags": ["environment-variables"] }, - "/packages": { - "id": "packages", - "name": "Packages", - "description": "", - "file": "", - "itemList": [], - "isExternal": true, - "path": "/packages", - "tags": [] - }, - "/packages/devkit/documents/nx_devkit": { - "id": "packages-devkit", - "name": "Nx Devkit", - "description": "", - "file": "", - "itemList": [], - "isExternal": true, - "path": "/packages/devkit/documents/nx_devkit", - "tags": ["create-your-own-plugin"] - }, "/reference/glossary": { "id": "glossary", "name": "Glossary", @@ -1953,16 +4979,6 @@ "path": "/reference/glossary", "tags": [] }, - "/reference/changelog": { - "id": "changelog", - "name": "Changelog", - "description": "", - "file": "", - "itemList": [], - "isExternal": true, - "path": "/reference/changelog", - "tags": [] - }, "/deprecated": { "id": "deprecated", "name": "Deprecated", @@ -2390,7 +5406,7 @@ "itemList": [], "isExternal": true, "path": "/reference/nx-json#workspace-layout", - "tags": ["enforce-project-boundaries"] + "tags": ["enforce-module-boundaries"] }, { "id": "nxjson-generator-defaults", @@ -2475,7 +5491,7 @@ "itemList": [], "isExternal": true, "path": "/reference/nx-json#workspace-layout", - "tags": ["enforce-project-boundaries"] + "tags": ["enforce-module-boundaries"] }, "/reference/nx-json#generators": { "id": "nxjson-generator-defaults", diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index f8117f2c9464f..0184c03194c99 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -58,6 +58,15 @@ "path": "/packages/angular/executors/package", "type": "executor" }, + "/packages/angular/executors/browser-esbuild": { + "description": "Builds your application with esbuild and adds support for incremental builds.", + "file": "generated/packages/angular/executors/browser-esbuild.json", + "hidden": false, + "name": "browser-esbuild", + "originalFilePath": "/packages/angular/src/executors/browser-esbuild/schema.json", + "path": "/packages/angular/executors/browser-esbuild", + "type": "executor" + }, "/packages/angular/executors/webpack-browser": { "description": "The `webpack-browser` executor is very similar to the standard `browser` builder provided by the Angular Devkit. It allows you to build your Angular application to a build artifact that can be hosted online. There are some key differences: \n- Supports Custom Webpack Configurations \n- Supports Incremental Building", "file": "generated/packages/angular/executors/webpack-browser.json", @@ -483,22 +492,22 @@ "path": "/packages/cypress/generators/cypress-project", "type": "generator" }, - "/packages/cypress/generators/cypress-e2e-configuration": { + "/packages/cypress/generators/configuration": { "description": "Add a Cypress E2E Configuration to an existing project.", - "file": "generated/packages/cypress/generators/cypress-e2e-configuration.json", + "file": "generated/packages/cypress/generators/configuration.json", "hidden": false, - "name": "cypress-e2e-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-e2e-configuration/schema.json", - "path": "/packages/cypress/generators/cypress-e2e-configuration", + "name": "configuration", + "originalFilePath": "/packages/cypress/src/generators/configuration/schema.json", + "path": "/packages/cypress/generators/configuration", "type": "generator" }, - "/packages/cypress/generators/cypress-component-configuration": { + "/packages/cypress/generators/component-configuration": { "description": "Set up Cypress Component Test for a project", - "file": "generated/packages/cypress/generators/cypress-component-configuration.json", + "file": "generated/packages/cypress/generators/component-configuration.json", "hidden": true, - "name": "cypress-component-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-component-configuration/schema.json", - "path": "/packages/cypress/generators/cypress-component-configuration", + "name": "component-configuration", + "originalFilePath": "/packages/cypress/src/generators/component-configuration/schema.json", + "path": "/packages/cypress/generators/component-configuration", "type": "generator" }, "/packages/cypress/generators/migrate-to-cypress-11": { @@ -651,13 +660,13 @@ "path": "/packages/esbuild/generators/init", "type": "generator" }, - "/packages/esbuild/generators/esbuild-project": { + "/packages/esbuild/generators/configuration": { "description": "Add esbuild configuration to a project.", - "file": "generated/packages/esbuild/generators/esbuild-project.json", + "file": "generated/packages/esbuild/generators/configuration.json", "hidden": true, - "name": "esbuild-project", - "originalFilePath": "/packages/esbuild/src/generators/esbuild-project/schema.json", - "path": "/packages/esbuild/generators/esbuild-project", + "name": "configuration", + "originalFilePath": "/packages/esbuild/src/generators/configuration/schema.json", + "path": "/packages/esbuild/generators/configuration", "type": "generator" } }, @@ -690,6 +699,17 @@ "path": "/packages/eslint-plugin/documents/enforce-module-boundaries", "tags": [], "originalFilePath": "shared/packages/linter/enforce-module-boundaries" + }, + "/packages/eslint-plugin/documents/dependency-checks": { + "id": "dependency-checks", + "name": "The `dependency-checks` rule", + "description": "The eslint-plugin package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called enforce-module-boundaries.", + "file": "generated/packages/eslint-plugin/documents/dependency-checks", + "itemList": [], + "isExternal": false, + "path": "/packages/eslint-plugin/documents/dependency-checks", + "tags": [], + "originalFilePath": "shared/packages/linter/dependency-checks" } }, "root": "/packages/eslint-plugin", @@ -952,13 +972,13 @@ "path": "/packages/jest/generators/init", "type": "generator" }, - "/packages/jest/generators/jest-project": { + "/packages/jest/generators/configuration": { "description": "Add Jest configuration to a project.", - "file": "generated/packages/jest/generators/jest-project.json", + "file": "generated/packages/jest/generators/configuration.json", "hidden": true, - "name": "jest-project", - "originalFilePath": "/packages/jest/src/generators/jest-project/schema.json", - "path": "/packages/jest/generators/jest-project", + "name": "configuration", + "originalFilePath": "/packages/jest/src/generators/configuration/schema.json", + "path": "/packages/jest/generators/configuration", "type": "generator" } }, @@ -1632,7 +1652,7 @@ "itemList": [], "isExternal": false, "path": "/packages/nx/documents/format-check", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "originalFilePath": "generated/cli/format-check" }, "/packages/nx/documents/format-write": { @@ -1643,7 +1663,7 @@ "itemList": [], "isExternal": false, "path": "/packages/nx/documents/format-write", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "originalFilePath": "generated/cli/format-write" }, "/packages/nx/documents/migrate": { @@ -1687,7 +1707,7 @@ "itemList": [], "isExternal": false, "path": "/packages/nx/documents/workspace-lint", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "originalFilePath": "generated/cli/workspace-lint" }, "/packages/nx/documents/workspace-generator": { @@ -1813,6 +1833,59 @@ "generators": {}, "path": "/packages/nx" }, + "playwright": { + "githubRoot": "https://github.com/nrwl/nx/blob/master", + "name": "playwright", + "packageName": "@nx/playwright", + "description": "The Nx Plugin for Playwright contains executors and generators allowing your workspace to use the powerful Playwright integration testing capabilities.", + "documents": { + "/packages/playwright/documents/overview": { + "id": "overview", + "name": "Overview", + "description": "The Nx Plugin for Playwright contains executors and generators allowing your workspace to use the powerful Playwright integration testing capabilities.", + "file": "generated/packages/playwright/documents/overview", + "itemList": [], + "isExternal": false, + "path": "/packages/playwright/documents/overview", + "tags": [], + "originalFilePath": "shared/packages/playwright/playwright-plugin" + } + }, + "root": "/packages/playwright", + "source": "/packages/playwright/src", + "executors": { + "/packages/playwright/executors/playwright": { + "description": "Run Playwright tests.", + "file": "generated/packages/playwright/executors/playwright.json", + "hidden": false, + "name": "playwright", + "originalFilePath": "/packages/playwright/src/executors/playwright/schema.json", + "path": "/packages/playwright/executors/playwright", + "type": "executor" + } + }, + "generators": { + "/packages/playwright/generators/configuration": { + "description": "Add Nx Playwright configuration to your project", + "file": "generated/packages/playwright/generators/configuration.json", + "hidden": false, + "name": "configuration", + "originalFilePath": "/packages/playwright/src/generators/configuration/schema.json", + "path": "/packages/playwright/generators/configuration", + "type": "generator" + }, + "/packages/playwright/generators/init": { + "description": "Initializes a Playwright project in the current workspace", + "file": "generated/packages/playwright/generators/init.json", + "hidden": false, + "name": "init", + "originalFilePath": "/packages/playwright/src/generators/init/schema.json", + "path": "/packages/playwright/generators/init", + "type": "generator" + } + }, + "path": "/packages/playwright" + }, "plugin": { "githubRoot": "https://github.com/nrwl/nx/blob/master", "name": "plugin", @@ -2325,13 +2398,13 @@ "path": "/packages/rollup/generators/init", "type": "generator" }, - "/packages/rollup/generators/rollup-project": { + "/packages/rollup/generators/configuration": { "description": "Add rollup configuration to a project.", - "file": "generated/packages/rollup/generators/rollup-project.json", + "file": "generated/packages/rollup/generators/configuration.json", "hidden": true, - "name": "rollup-project", - "originalFilePath": "/packages/rollup/src/generators/rollup-project/schema.json", - "path": "/packages/rollup/generators/rollup-project", + "name": "configuration", + "originalFilePath": "/packages/rollup/src/generators/configuration/schema.json", + "path": "/packages/rollup/generators/configuration", "type": "generator" } }, @@ -2420,6 +2493,17 @@ "tags": [], "originalFilePath": "shared/packages/storybook/custom-builder-configs" }, + "/packages/storybook/documents/storybook-interaction-tests": { + "id": "storybook-interaction-tests", + "name": "Setting up Storybook Interaction Tests with Nx", + "description": "This guide explains how you can set up Storybook interaction tests on your Nx workspace.", + "file": "generated/packages/storybook/documents/storybook-interaction-tests", + "itemList": [], + "isExternal": false, + "path": "/packages/storybook/documents/storybook-interaction-tests", + "tags": [], + "originalFilePath": "shared/packages/storybook/interaction-tests" + }, "/packages/storybook/documents/storybook-composition-setup": { "id": "storybook-composition-setup", "name": "Setting up Storybook Composition with Nx", @@ -2771,13 +2855,13 @@ "path": "/packages/webpack/generators/init", "type": "generator" }, - "/packages/webpack/generators/webpack-project": { + "/packages/webpack/generators/configuration": { "description": "Add webpack configuration to a project.", - "file": "generated/packages/webpack/generators/webpack-project.json", + "file": "generated/packages/webpack/generators/configuration.json", "hidden": true, - "name": "webpack-project", - "originalFilePath": "/packages/webpack/src/generators/webpack-project/schema.json", - "path": "/packages/webpack/generators/webpack-project", + "name": "configuration", + "originalFilePath": "/packages/webpack/src/generators/configuration/schema.json", + "path": "/packages/webpack/generators/configuration", "type": "generator" } }, @@ -2853,6 +2937,15 @@ "path": "/packages/workspace/generators/remove", "type": "generator" }, + "/packages/workspace/generators/convert-to-monorepo": { + "description": "Convert a Nx project to a monorepo.", + "file": "generated/packages/workspace/generators/convert-to-monorepo.json", + "hidden": false, + "name": "convert-to-monorepo", + "originalFilePath": "/packages/workspace/src/generators/convert-to-monorepo/schema.json", + "path": "/packages/workspace/generators/convert-to-monorepo", + "type": "generator" + }, "/packages/workspace/generators/new": { "description": "Create a workspace.", "file": "generated/packages/workspace/generators/new.json", diff --git a/docs/generated/manifests/recipes.json b/docs/generated/manifests/recipes.json index ce83e22146783..91c5dc895660a 100644 --- a/docs/generated/manifests/recipes.json +++ b/docs/generated/manifests/recipes.json @@ -197,6 +197,16 @@ "path": "/recipes/ci/monorepo-ci-azure", "tags": [] }, + { + "id": "azure-last-successful-commit", + "name": "Find the Last Successful Commit in Azure Pipelines", + "description": "", + "file": "shared/recipes/azure-last-successful-commit", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/azure-last-successful-commit", + "tags": [] + }, { "id": "monorepo-ci-circle-ci", "name": "Setting up CircleCI", @@ -292,6 +302,16 @@ "path": "/recipes/ci/monorepo-ci-azure", "tags": [] }, + "/recipes/ci/azure-last-successful-commit": { + "id": "azure-last-successful-commit", + "name": "Find the Last Successful Commit in Azure Pipelines", + "description": "", + "file": "shared/recipes/azure-last-successful-commit", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/azure-last-successful-commit", + "tags": [] + }, "/recipes/ci/monorepo-ci-circle-ci": { "id": "monorepo-ci-circle-ci", "name": "Setting up CircleCI", @@ -614,6 +634,37 @@ "path": "/recipes/adopting-nx-angular/angular-multiple", "tags": [] }, + "/recipes/add-stack": { + "id": "add-stack", + "name": "Add a New Project", + "description": "Instructions to add a project from a new stack to an Nx workspace", + "file": "", + "itemList": [ + { + "id": "add-qwik", + "name": "Add a Qwik Project", + "description": "Add a Qwik project to your repo", + "file": "shared/recipes/add-stack/add-qwik", + "itemList": [], + "isExternal": false, + "path": "/recipes/add-stack/add-qwik", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/add-stack", + "tags": [] + }, + "/recipes/add-stack/add-qwik": { + "id": "add-qwik", + "name": "Add a Qwik Project", + "description": "Add a Qwik project to your repo", + "file": "shared/recipes/add-stack/add-qwik", + "itemList": [], + "isExternal": false, + "path": "/recipes/add-stack/add-qwik", + "tags": [] + }, "/recipes/executors": { "id": "executors", "name": "Executors", @@ -1322,10 +1373,10 @@ "path": "/recipes/example-repos/dte", "tags": [] }, - "/recipes/other": { - "id": "other", - "name": "Other", - "description": "Other recipes you will find useful.", + "/recipes/managing-repository": { + "id": "managing-repository", + "name": "Managing Your Nx Repository", + "description": "Configuring the Repository Itself", "file": "", "itemList": [ { @@ -1335,7 +1386,7 @@ "file": "shared/recipes/root-level-scripts", "itemList": [], "isExternal": false, - "path": "/recipes/other/root-level-scripts", + "path": "/recipes/managing-repository/root-level-scripts", "tags": ["run-tasks"] }, { @@ -1345,7 +1396,7 @@ "file": "shared/recipes/analyze-source-files", "itemList": [], "isExternal": false, - "path": "/recipes/other/analyze-source-files", + "path": "/recipes/managing-repository/analyze-source-files", "tags": ["explore-graph"] }, { @@ -1355,7 +1406,7 @@ "file": "shared/recipes/workspace-watching", "itemList": [], "isExternal": false, - "path": "/recipes/other/workspace-watching", + "path": "/recipes/managing-repository/workspace-watching", "tags": ["workspace-watching"] }, { @@ -1365,9 +1416,19 @@ "file": "shared/recipes/advanced-update", "itemList": [], "isExternal": false, - "path": "/recipes/other/advanced-update", + "path": "/recipes/managing-repository/advanced-update", "tags": ["automate-updating-dependencies"] }, + { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/standalone-to-integrated", + "tags": ["repository-types"] + }, { "id": "js-and-ts", "name": "JavaScript and TypeScript", @@ -1375,9 +1436,80 @@ "file": "shared/guides/js-and-ts", "itemList": [], "isExternal": false, - "path": "/recipes/other/js-and-ts", + "path": "/recipes/managing-repository/js-and-ts", "tags": [] - }, + } + ], + "isExternal": false, + "path": "/recipes/managing-repository", + "tags": [] + }, + "/recipes/managing-repository/root-level-scripts": { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/root-level-scripts", + "tags": ["run-tasks"] + }, + "/recipes/managing-repository/analyze-source-files": { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/analyze-source-files", + "tags": ["explore-graph"] + }, + "/recipes/managing-repository/workspace-watching": { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/workspace-watching", + "tags": ["workspace-watching"] + }, + "/recipes/managing-repository/advanced-update": { + "id": "advanced-update", + "name": "Advanced Update Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + "/recipes/managing-repository/standalone-to-integrated": { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/standalone-to-integrated", + "tags": ["repository-types"] + }, + "/recipes/managing-repository/js-and-ts": { + "id": "js-and-ts", + "name": "JavaScript and TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/js-and-ts", + "tags": [] + }, + "/recipes/other": { + "id": "other", + "name": "Other", + "description": "Other recipes you will find useful.", + "file": "", + "itemList": [ { "id": "react-native", "name": "React Native with Nx", @@ -1498,16 +1630,6 @@ "path": "/recipes/other/misc-data-persistence", "tags": [] }, - { - "id": "azure-last-successful-commit", - "name": "Find the Last Successful Commit in Azure Pipelines", - "description": "", - "file": "shared/recipes/azure-last-successful-commit", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/azure-last-successful-commit", - "tags": [] - }, { "id": "troubleshoot-cache-misses", "name": "Troubleshoot Cache Misses", @@ -1587,62 +1709,22 @@ "isExternal": false, "path": "/recipes/other/standalone-ngrx-apis", "tags": [] + }, + { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/unknown-local-cache", + "tags": [] } ], "isExternal": false, "path": "/recipes/other", "tags": [] }, - "/recipes/other/root-level-scripts": { - "id": "root-level-scripts", - "name": "Run Root-Level NPM Scripts with Nx", - "description": "", - "file": "shared/recipes/root-level-scripts", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/root-level-scripts", - "tags": ["run-tasks"] - }, - "/recipes/other/analyze-source-files": { - "id": "analyze-source-files", - "name": "Disable Graph Links Created from Analyzing Source Files", - "description": "", - "file": "shared/recipes/analyze-source-files", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/analyze-source-files", - "tags": ["explore-graph"] - }, - "/recipes/other/workspace-watching": { - "id": "workspace-watching", - "name": "Workspace Watching", - "description": "", - "file": "shared/recipes/workspace-watching", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/workspace-watching", - "tags": ["workspace-watching"] - }, - "/recipes/other/advanced-update": { - "id": "advanced-update", - "name": "Advanced Update Process", - "description": "", - "file": "shared/recipes/advanced-update", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/advanced-update", - "tags": ["automate-updating-dependencies"] - }, - "/recipes/other/js-and-ts": { - "id": "js-and-ts", - "name": "JavaScript and TypeScript", - "description": "", - "file": "shared/guides/js-and-ts", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/js-and-ts", - "tags": [] - }, "/recipes/other/react-native": { "id": "react-native", "name": "React Native with Nx", @@ -1763,16 +1845,6 @@ "path": "/recipes/other/misc-data-persistence", "tags": [] }, - "/recipes/other/azure-last-successful-commit": { - "id": "azure-last-successful-commit", - "name": "Find the Last Successful Commit in Azure Pipelines", - "description": "", - "file": "shared/recipes/azure-last-successful-commit", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/azure-last-successful-commit", - "tags": [] - }, "/recipes/other/troubleshoot-cache-misses": { "id": "troubleshoot-cache-misses", "name": "Troubleshoot Cache Misses", @@ -1852,5 +1924,15 @@ "isExternal": false, "path": "/recipes/other/standalone-ngrx-apis", "tags": [] + }, + "/recipes/other/unknown-local-cache": { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/unknown-local-cache", + "tags": [] } } diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index 816c5753e50a8..66d0a1802874e 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -1,7 +1,7 @@ { "run-tasks": [ { - "description": "", + "description": "Learn about the various ways you can use Nx to run tasks in your workspace.", "file": "shared/core-features/run-tasks", "id": "run-tasks", "name": "Run Tasks", @@ -26,7 +26,7 @@ "file": "shared/recipes/root-level-scripts", "id": "root-level-scripts", "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/other/root-level-scripts" + "path": "/recipes/tips-n-tricks/root-level-scripts" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", @@ -52,7 +52,7 @@ ], "cache-task-results": [ { - "description": "", + "description": "Learn how to define cacheable tasks, how to fine-tune with inputs and outputs, where the cache is stored and much more.", "file": "shared/core-features/cache-task-results", "id": "cache-task-results", "name": "Cache Task Results", @@ -77,7 +77,14 @@ "file": "shared/concepts/customizing-inputs", "id": "customizing-inputs", "name": "Customizing Inputs", - "path": "/more-concepts/customizing-inputs" + "path": "/concepts/more-concepts/customizing-inputs" + }, + { + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses" }, { "description": "", @@ -114,13 +121,6 @@ "name": "Project Configuration reference: inputs and namedInputs", "path": "/reference/project-configuration#inputs-&-namedinputs" }, - { - "description": "", - "file": "shared/recipes/troubleshoot-cache-misses", - "id": "troubleshoot-cache-misses", - "name": "Troubleshoot Cache Misses", - "path": "/recipes/other/troubleshoot-cache-misses" - }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", "file": "generated/packages/generated/packages/nx/documents/connect-to-nx-cloud", @@ -136,69 +136,18 @@ "path": "/packages/nx/documents/reset" } ], - "share-your-cache": [ + "remote-cache": [ { - "description": "", - "file": "shared/core-features/share-your-cache", - "id": "share-your-cache", - "name": "Share Your Cache", - "path": "/core-features/share-your-cache" - } - ], - "explore-graph": [ - { - "description": "", - "file": "shared/core-features/explore-graph", - "id": "explore-graph", - "name": "Explore the Graph", - "path": "/core-features/explore-graph" - }, - { - "description": "", - "file": "shared/concepts/how-project-graph-is-built", - "id": "how-project-graph-is-built", - "name": "How the Project Graph is Built", - "path": "/more-concepts/how-project-graph-is-built" - }, - { - "description": "", - "file": "shared/recipes/analyze-source-files", - "id": "analyze-source-files", - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/other/analyze-source-files" - }, - { - "description": "", - "file": "shared/recipes/export-project-graph", - "id": "export-project-graph", - "name": "Export Project Graph", - "path": "/recipes/other/export-project-graph" - }, - { - "description": "", - "file": "shared/recipes/resolve-circular-dependencies", - "id": "resolve-circular-dependencies", - "name": "Resolve Circular Dependencies", - "path": "/recipes/other/resolve-circular-dependencies" - }, - { - "description": "", - "file": "shared/recipes/plugins/project-graph-plugins", - "id": "project-graph-plugins", - "name": "Modify the Project Graph", - "path": "/plugins/recipes/project-graph-plugins" - }, - { - "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", - "file": "generated/packages/generated/packages/nx/documents/dep-graph", - "id": "dep-graph", - "name": "graph", - "path": "/packages/nx/documents/dep-graph" + "description": "Learn how to enable remote caching s.t. you don't just benefit locally from it but also in CI.", + "file": "shared/core-features/remote-cache", + "id": "remote-cache", + "name": "Use Remote Caching", + "path": "/core-features/remote-cache" } ], "distribute-task-execution": [ { - "description": "", + "description": "Learn how to efficiently distribute tasks across machines to take full advantage of parallelization. Nx Cloud has a built-in DTE mechanism which makes this a trivial task.", "file": "shared/core-features/distribute-task-execution", "id": "distribute-task-execution", "name": "Distribute Task Execution", @@ -216,14 +165,7 @@ "file": "shared/concepts/illustrated-dte-guide", "id": "illustrated-dte", "name": "Illustrated Distributed Task Execution", - "path": "/more-concepts/illustrated-dte" - }, - { - "description": "", - "file": "", - "id": "nx-cloud-documentation", - "name": "Nx Cloud Documentation", - "path": "/nx-cloud/intro/what-is-nx-cloud" + "path": "/concepts/more-concepts/illustrated-dte" }, { "description": "", @@ -232,6 +174,13 @@ "name": "CI Setup", "path": "/recipes/ci/ci-setup" }, + { + "description": "", + "file": "", + "id": "nx-cloud-documentation", + "name": "Nx Cloud Documentation", + "path": "/nx-cloud/intro/what-is-nx-cloud" + }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", "file": "generated/packages/generated/packages/nx/documents/connect-to-nx-cloud", @@ -240,60 +189,53 @@ "path": "/packages/nx/documents/connect-to-nx-cloud" } ], - "integrate-with-editors": [ - { - "description": "", - "file": "shared/core-features/integrate-with-editors", - "id": "integrate-with-editors", - "name": "Integrate with Editors", - "path": "/core-features/integrate-with-editors" - }, + "explore-graph": [ { - "description": "", - "file": "shared/recipes/console-telemetry", - "id": "console-telemetry", - "name": "Nx Console Telemetry", - "path": "/recipes/nx-console/console-telemetry" + "description": "Nx uses a graph behind the scenes to optimize your operations. You can also visualize and use the graph to better understand your workspace structure. Learn more in this guide.", + "file": "shared/core-features/explore-graph", + "id": "explore-graph", + "name": "Explore the Graph", + "path": "/core-features/explore-graph" }, { "description": "", - "file": "shared/recipes/console-generate-command", - "id": "console-generate-command", - "name": "Nx Console Generate Command", - "path": "/recipes/nx-console/console-generate-command" + "file": "shared/concepts/how-project-graph-is-built", + "id": "how-project-graph-is-built", + "name": "How the Project Graph is Built", + "path": "/concepts/more-concepts/how-project-graph-is-built" }, { "description": "", - "file": "shared/recipes/console-run-command", - "id": "console-run-command", - "name": "Nx Console Run Command", - "path": "/recipes/nx-console/console-run-command" + "file": "shared/recipes/analyze-source-files", + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files" }, { "description": "", - "file": "shared/recipes/console-add-dependency-command", - "id": "console-add-dependency-command", - "name": "Nx Console Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command" + "file": "shared/recipes/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies" }, { "description": "", - "file": "shared/recipes/console-project-pane", - "id": "console-project-pane", - "name": "Nx Console Project Pane", - "path": "/recipes/nx-console/console-project-pane" + "file": "shared/recipes/plugins/project-graph-plugins", + "id": "project-graph-plugins", + "name": "Modify the Project Graph", + "path": "/extending-nx/recipes/project-graph-plugins" }, { - "description": "", - "file": "shared/recipes/console-shortcuts", - "id": "console-shortcuts", - "name": "Nx Console Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts" + "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", + "file": "generated/packages/generated/packages/nx/documents/dep-graph", + "id": "dep-graph", + "name": "graph", + "path": "/packages/nx/documents/dep-graph" } ], "automate-updating-dependencies": [ { - "description": "", + "description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.", "file": "shared/core-features/automate-updating-dependencies", "id": "automate-updating-dependencies", "name": "Automate Updating Dependencies", @@ -303,8 +245,8 @@ "description": "", "file": "shared/recipes/advanced-update", "id": "advanced-update", - "name": "Advanced Update Process", - "path": "/recipes/other/advanced-update" + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", @@ -314,62 +256,48 @@ "path": "/packages/nx/documents/migrate" } ], - "enforce-project-boundaries": [ + "enforce-module-boundaries": [ { - "description": "", - "file": "shared/core-features/enforce-project-boundaries", - "id": "enforce-project-boundaries", - "name": "Enforce Project Boundaries", - "path": "/core-features/enforce-project-boundaries" + "description": "Learn how to avoid dependency hell and scale a codebase by imposing constraints on your projects using the module boundary lint rule.", + "file": "shared/core-features/enforce-module-boundaries", + "id": "enforce-module-boundaries", + "name": "Enforce Module Boundaries", + "path": "/core-features/enforce-module-boundaries" }, { "description": "", "file": "shared/monorepo-nx-enterprise", "id": "monorepo-nx-enterprise", "name": "Using Nx at Enterprises", - "path": "/more-concepts/monorepo-nx-enterprise" + "path": "/concepts/more-concepts/monorepo-nx-enterprise" }, { "description": "", "file": "shared/workspace/applications-and-libraries", "id": "applications-and-libraries", "name": "Applications and Libraries", - "path": "/more-concepts/applications-and-libraries" + "path": "/concepts/more-concepts/applications-and-libraries" }, { "description": "", "file": "shared/workspace/creating-libraries", "id": "creating-libraries", "name": "Creating Libraries", - "path": "/more-concepts/creating-libraries" + "path": "/concepts/more-concepts/creating-libraries" }, { "description": "", "file": "shared/workspace/library-types", "id": "library-types", "name": "Library Types", - "path": "/more-concepts/library-types" + "path": "/concepts/more-concepts/library-types" }, { "description": "", "file": "shared/workspace/grouping-libraries", "id": "grouping-libraries", "name": "Grouping Libraries", - "path": "/more-concepts/grouping-libraries" - }, - { - "description": "", - "file": "shared/reference/nxignore", - "id": "nxignore", - "name": ".nxignore", - "path": "/reference/nxignore" - }, - { - "description": "", - "file": "", - "id": "nxjson-workspaceLayout", - "name": "nx.json workspaceLayout property", - "path": "/reference/nx-json#workspace-layout" + "path": "/concepts/more-concepts/grouping-libraries" }, { "description": "", @@ -401,10 +329,17 @@ }, { "description": "", - "file": "shared/eslint", - "id": "eslint", - "name": "Using ESLint in Nx Workspaces", - "path": "/recipes/other/eslint" + "file": "shared/reference/nxignore", + "id": "nxignore", + "name": ".nxignore", + "path": "/reference/nxignore" + }, + { + "description": "", + "file": "", + "id": "nxjson-workspaceLayout", + "name": "nx.json workspaceLayout property", + "path": "/reference/nx-json#workspace-layout" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", @@ -428,13 +363,64 @@ "path": "/packages/nx/documents/workspace-lint" } ], + "integrate-with-editors": [ + { + "description": "Learn about Nx Console, an extension for VS Code and WebStorm.", + "file": "shared/core-features/integrate-with-editors", + "id": "integrate-with-editors", + "name": "Integrate with Editors", + "path": "/core-features/integrate-with-editors" + }, + { + "description": "", + "file": "shared/recipes/console-telemetry", + "id": "console-telemetry", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry" + }, + { + "description": "", + "file": "shared/recipes/console-generate-command", + "id": "console-generate-command", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command" + }, + { + "description": "", + "file": "shared/recipes/console-run-command", + "id": "console-run-command", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command" + }, + { + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command" + }, + { + "description": "", + "file": "shared/recipes/console-project-pane", + "id": "console-project-pane", + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane" + }, + { + "description": "", + "file": "shared/recipes/console-shortcuts", + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts" + } + ], "use-task-executors": [ { "description": "", "file": "shared/plugin-features/use-task-executors", "id": "use-task-executors", "name": "Use Task Executors", - "path": "/plugin-features/use-task-executors" + "path": "/core-features/plugin-features/use-task-executors" }, { "description": "", @@ -448,70 +434,70 @@ "file": "shared/incremental-builds", "id": "incremental-builds", "name": "Incremental Builds", - "path": "/more-concepts/incremental-builds" - }, - { - "description": "", - "file": "shared/reference/project-configuration", - "id": "project-configuration", - "name": "Project Configuration", - "path": "/reference/project-configuration" - }, - { - "description": "", - "file": "shared/recipes/use-executor-configurations", - "id": "use-executor-configurations", - "name": "Use Executor Configurations", - "path": "/recipes/executors/use-executor-configurations" + "path": "/concepts/more-concepts/incremental-builds" }, { "description": "", - "file": "shared/running-custom-commands", - "id": "run-commands-executor", - "name": "Running Custom Commands", - "path": "/recipes/executors/run-commands-executor" + "file": "shared/guides/module-federation/faster-builds", + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation" }, { "description": "", - "file": "shared/guides/module-federation/faster-builds", - "id": "faster-builds", - "name": "Faster Builds with Module Federation", - "path": "/recipes/module-federation/faster-builds" + "file": "shared/recipes/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr" }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for Angular and React", - "path": "/recipes/module-federation/module-federation-with-ssr" + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr" }, { "description": "", "file": "shared/guides/module-federation/dynamic-mfe-angular", "id": "dynamic-module-federation-with-angular", "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/module-federation/dynamic-module-federation-with-angular" + "path": "/recipes/angular/dynamic-module-federation-with-angular" + }, + { + "description": "", + "file": "shared/running-custom-commands", + "id": "run-commands-executor", + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor" }, { "description": "", "file": "shared/guides/performance-profiling", "id": "performance-profiling", "name": "Profiling Build Performance", - "path": "/recipes/other/performance-profiling" + "path": "/recipes/troubleshooting/performance-profiling" + }, + { + "description": "", + "file": "shared/reference/project-configuration", + "id": "project-configuration", + "name": "Project Configuration", + "path": "/reference/project-configuration" }, { "description": "", "file": "shared/recipes/plugins/local-executors", "id": "local-executors", "name": "Write a Simple Executor", - "path": "/plugins/recipes/local-executors" + "path": "/extending-nx/recipes/local-executors" }, { "description": "", "file": "shared/recipes/plugins/compose-executors", "id": "compose-executors", "name": "Compose Executors", - "path": "/plugins/recipes/compose-executors" + "path": "/extending-nx/recipes/compose-executors" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", @@ -541,14 +527,14 @@ "file": "shared/plugin-features/use-code-generators", "id": "use-code-generators", "name": "Use Code Generators", - "path": "/plugin-features/use-code-generators" + "path": "/core-features/plugin-features/use-code-generators" }, { "description": "", "file": "shared/monorepo-nx-enterprise", "id": "monorepo-nx-enterprise", "name": "Using Nx at Enterprises", - "path": "/more-concepts/monorepo-nx-enterprise" + "path": "/concepts/more-concepts/monorepo-nx-enterprise" }, { "description": "", @@ -562,35 +548,35 @@ "file": "shared/recipes/generators/local-generators", "id": "local-generators", "name": "Write a Simple Generator", - "path": "/plugins/recipes/local-generators" + "path": "/extending-nx/recipes/local-generators" }, { "description": "", "file": "shared/recipes/generators/composing-generators", "id": "composing-generators", "name": "Compose Generators", - "path": "/plugins/recipes/composing-generators" + "path": "/extending-nx/recipes/composing-generators" }, { "description": "", "file": "shared/recipes/generators/generator-options", "id": "generator-options", "name": "Provide Options for Generators", - "path": "/plugins/recipes/generator-options" + "path": "/extending-nx/recipes/generator-options" }, { "description": "", "file": "shared/recipes/generators/creating-files", "id": "creating-files", "name": "Create Files", - "path": "/plugins/recipes/creating-files" + "path": "/extending-nx/recipes/creating-files" }, { "description": "", "file": "shared/recipes/generators/modifying-files", "id": "modifying-files", "name": "Modify Files", - "path": "/plugins/recipes/modifying-files" + "path": "/extending-nx/recipes/modifying-files" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", @@ -616,188 +602,177 @@ "path": "/concepts/mental-model" } ], + "repository-types": [ + { + "description": "", + "file": "shared/concepts/integrated-vs-package-based", + "id": "integrated-vs-package-based", + "name": "Integrated Repos vs. Package-Based Repos vs. Standalone Apps", + "path": "/concepts/integrated-vs-package-based" + }, + { + "description": "", + "file": "shared/recipes/repo-types/package-based-in-integrated", + "id": "package-based-in-integrated", + "name": "Add a Package-based Project in an Integrated Repo", + "path": "/recipes/tips-n-tricks/package-based-in-integrated" + }, + { + "description": "", + "file": "shared/recipes/repo-types/integrated-in-package-based", + "id": "integrated-in-package-based", + "name": "Add an Integrated Project in a Package-based Repo", + "path": "/recipes/tips-n-tricks/integrated-in-package-based" + }, + { + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated" + } + ], "create-your-own-plugin": [ { "description": "", "file": "shared/guides/nx-devkit-angular-devkit", "id": "nx-devkit-angular-devkit", "name": "Nx Devkit and Angular Devkit", - "path": "/more-concepts/nx-devkit-angular-devkit" - }, - { - "description": "", - "file": "", - "id": "packages-devkit", - "name": "Nx Devkit", - "path": "/packages/devkit/documents/nx_devkit" + "path": "/concepts/more-concepts/nx-devkit-angular-devkit" }, { "description": "", "file": "shared/recipes/plugins/migration-generators", "id": "migration-generators", "name": "Write a Migration", - "path": "/plugins/recipes/migration-generators" + "path": "/extending-nx/recipes/migration-generators" }, { "description": "", "file": "shared/recipes/plugins/create-preset", "id": "create-preset", "name": "Create a Preset", - "path": "/plugins/recipes/create-preset" + "path": "/extending-nx/recipes/create-preset" }, { "description": "", "file": "shared/recipes/plugins/project-graph-plugins", "id": "project-graph-plugins", "name": "Modify the Project Graph", - "path": "/plugins/recipes/project-graph-plugins" + "path": "/extending-nx/recipes/project-graph-plugins" }, { "description": "", "file": "shared/recipes/plugins/project-inference-plugins", "id": "project-inference-plugins", "name": "Identify Custom Projects", - "path": "/plugins/recipes/project-inference-plugins" - } - ], - "environment-variables": [ - { - "description": "", - "file": "shared/reference/environment-variables", - "id": "environment-variables", - "name": "Environment Variables", - "path": "/reference/environment-variables" - }, - { - "description": "", - "file": "shared/guides/define-environment-variables", - "id": "define-environment-variables", - "name": "Define Environment Variables", - "path": "/recipes/environment-variables/define-environment-variables" - }, - { - "description": "", - "file": "shared/guides/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", - "name": "Use Environment Variables in React", - "path": "/recipes/environment-variables/use-environment-variables-in-react" - }, - { - "description": "", - "file": "shared/guides/use-environment-variables-in-angular", - "id": "use-environment-variables-in-angular", - "name": "Use Environment Variables in Angular", - "path": "/recipes/environment-variables/use-environment-variables-in-angular" - }, - { - "description": "", - "file": "shared/guides/performance-profiling", - "id": "performance-profiling", - "name": "Profiling Build Performance", - "path": "/recipes/other/performance-profiling" - } - ], - "docker": [ - { - "description": "", - "file": "shared/recipes/ci-deployment", - "id": "ci-deployment", - "name": "Prepare applications for deployment via CI", - "path": "/recipes/ci/ci-deployment" - } - ], - "deploy": [ - { - "description": "", - "file": "shared/recipes/ci-deployment", - "id": "ci-deployment", - "name": "Prepare applications for deployment via CI", - "path": "/recipes/ci/ci-deployment" + "path": "/extending-nx/recipes/project-inference-plugins" } ], "module-federation": [ { "description": "", "file": "shared/guides/module-federation/faster-builds", - "id": "faster-builds", + "id": "faster-builds-with-module-federation", "name": "Faster Builds with Module Federation", - "path": "/recipes/module-federation/faster-builds" + "path": "/concepts/more-concepts/faster-builds-with-module-federation" + }, + { + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr" }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for Angular and React", - "path": "/recipes/module-federation/module-federation-with-ssr" + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr" }, { "description": "", "file": "shared/guides/module-federation/dynamic-mfe-angular", "id": "dynamic-module-federation-with-angular", "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/module-federation/dynamic-module-federation-with-angular" + "path": "/recipes/angular/dynamic-module-federation-with-angular" } ], "angular": [ { "description": "", "file": "shared/guides/module-federation/faster-builds", - "id": "faster-builds", + "id": "faster-builds-with-module-federation", "name": "Faster Builds with Module Federation", - "path": "/recipes/module-federation/faster-builds" + "path": "/concepts/more-concepts/faster-builds-with-module-federation" }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for Angular and React", - "path": "/recipes/module-federation/module-federation-with-ssr" + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr" }, { "description": "", "file": "shared/guides/module-federation/dynamic-mfe-angular", "id": "dynamic-module-federation-with-angular", "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/module-federation/dynamic-module-federation-with-angular" + "path": "/recipes/angular/dynamic-module-federation-with-angular" } ], "react": [ { "description": "", "file": "shared/guides/module-federation/faster-builds", - "id": "faster-builds", + "id": "faster-builds-with-module-federation", "name": "Faster Builds with Module Federation", - "path": "/recipes/module-federation/faster-builds" + "path": "/concepts/more-concepts/faster-builds-with-module-federation" }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for Angular and React", - "path": "/recipes/module-federation/module-federation-with-ssr" + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr" } ], - "storybook": [ + "environment-variables": [ { "description": "", - "file": "shared/recipes/one-storybook-for-all", - "id": "one-storybook-for-all", - "name": "Publishing Storybook: One main Storybook instance for all projects", - "path": "/recipes/storybook/one-storybook-for-all" + "file": "shared/guides/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react" }, { "description": "", - "file": "shared/recipes/one-storybook-per-scope", - "id": "one-storybook-per-scope", - "name": "Publishing Storybook: One Storybook instance per scope", - "path": "/recipes/storybook/one-storybook-per-scope" + "file": "shared/guides/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular" }, { "description": "", - "file": "shared/recipes/one-storybook-with-composition", - "id": "one-storybook-with-composition", - "name": "Publishing Storybook: One main Storybook instance using Storybook Composition", - "path": "/recipes/storybook/one-storybook-with-composition" + "file": "shared/guides/define-environment-variables", + "id": "define-environment-variables", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables" + }, + { + "description": "", + "file": "shared/guides/performance-profiling", + "id": "performance-profiling", + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling" + }, + { + "description": "", + "file": "shared/reference/environment-variables", + "id": "environment-variables", + "name": "Environment Variables", + "path": "/reference/environment-variables" } ], "deployment": [ @@ -806,35 +781,35 @@ "file": "shared/recipes/deployment/node-server-fly-io", "id": "node-server-fly-io", "name": "Deploying a Node App to Fly.io", - "path": "/recipes/deployment/node-server-fly-io" + "path": "/recipes/node/node-server-fly-io" }, { "description": "", "file": "shared/recipes/deployment/node-serverless-functions-netlify", "id": "node-serverless-functions-netlify", "name": "Add and Deploy Netlify Edge Functions with Node", - "path": "/recipes/deployment/node-serverless-functions-netlify" + "path": "/recipes/node/node-serverless-functions-netlify" }, { "description": "", "file": "shared/recipes/deployment/node-aws-lambda", "id": "node-aws-lambda", "name": "Deploying AWS lambda in Node.js", - "path": "/recipes/deployment/node-aws-lambda" + "path": "/recipes/node/node-aws-lambda" }, { "description": "", "file": "shared/recipes/deployment/deno-deploy", "id": "deno-deploy", "name": "Serverless deployment with Deno Deploy", - "path": "/recipes/deployment/deno-deploy" + "path": "/recipes/other/deno-deploy" }, { "description": "", "file": "shared/recipes/deployment/deno-netlify-edge-functions", "id": "deno-netlify-functions", "name": "Add and Deploy Netlify Edge Functions with Deno", - "path": "/recipes/deployment/deno-netlify-functions" + "path": "/recipes/other/deno-netlify-functions" } ], "node": [ @@ -843,56 +818,113 @@ "file": "shared/recipes/deployment/node-server-fly-io", "id": "node-server-fly-io", "name": "Deploying a Node App to Fly.io", - "path": "/recipes/deployment/node-server-fly-io" + "path": "/recipes/node/node-server-fly-io" }, { "description": "", "file": "shared/recipes/deployment/node-serverless-functions-netlify", "id": "node-serverless-functions-netlify", "name": "Add and Deploy Netlify Edge Functions with Node", - "path": "/recipes/deployment/node-serverless-functions-netlify" + "path": "/recipes/node/node-serverless-functions-netlify" }, { "description": "", "file": "shared/recipes/deployment/node-aws-lambda", "id": "node-aws-lambda", "name": "Deploying AWS lambda in Node.js", - "path": "/recipes/deployment/node-aws-lambda" + "path": "/recipes/node/node-aws-lambda" }, { "description": "", "file": "shared/recipes/database/nestjs-prisma", "id": "nestjs-prisma", "name": "Using Prisma with NestJS", - "path": "/recipes/database/nestjs-prisma" + "path": "/showcase/example-repos/nestjs-prisma" }, { "description": "", "file": "shared/recipes/database/mongo-fastify", "id": "mongo-fastify", "name": "Using Mongo with Fastify", - "path": "/recipes/database/mongo-fastify" + "path": "/showcase/example-repos/mongo-fastify" }, { "description": "", "file": "shared/recipes/database/redis-fastify", "id": "redis-fastify", "name": "Using Redis with Fastify", - "path": "/recipes/database/redis-fastify" + "path": "/showcase/example-repos/redis-fastify" }, { "description": "", "file": "shared/recipes/database/postgres-fastify", "id": "postgres-fastify", "name": "Using Postgres with Fastify", - "path": "/recipes/database/postgres-fastify" + "path": "/showcase/example-repos/postgres-fastify" }, { "description": "", "file": "shared/recipes/database/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/database/serverless-fastify-planetscale" + "path": "/showcase/example-repos/serverless-fastify-planetscale" + } + ], + "storybook": [ + { + "description": "", + "file": "shared/recipes/one-storybook-for-all", + "id": "one-storybook-for-all", + "name": "One main Storybook instance for all projects", + "path": "/recipes/storybook/one-storybook-for-all" + }, + { + "description": "", + "file": "shared/recipes/one-storybook-per-scope", + "id": "one-storybook-per-scope", + "name": "One Storybook instance per scope", + "path": "/recipes/storybook/one-storybook-per-scope" + }, + { + "description": "", + "file": "shared/recipes/one-storybook-with-composition", + "id": "one-storybook-with-composition", + "name": "One main Storybook instance using Storybook Composition", + "path": "/recipes/storybook/one-storybook-with-composition" + } + ], + "docker": [ + { + "description": "", + "file": "shared/recipes/ci-deployment", + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "path": "/recipes/ci/ci-deployment" + } + ], + "deploy": [ + { + "description": "", + "file": "shared/recipes/ci-deployment", + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "path": "/recipes/ci/ci-deployment" + } + ], + "workspace-watching": [ + { + "description": "", + "file": "shared/recipes/workspace-watching", + "id": "workspace-watching", + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching" + }, + { + "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", + "file": "generated/packages/generated/packages/nx/documents/watch", + "id": "watch", + "name": "watch", + "path": "/packages/nx/documents/watch" } ], "deno": [ @@ -901,14 +933,14 @@ "file": "shared/recipes/deployment/deno-deploy", "id": "deno-deploy", "name": "Serverless deployment with Deno Deploy", - "path": "/recipes/deployment/deno-deploy" + "path": "/recipes/other/deno-deploy" }, { "description": "", "file": "shared/recipes/deployment/deno-netlify-edge-functions", "id": "deno-netlify-functions", "name": "Add and Deploy Netlify Edge Functions with Deno", - "path": "/recipes/deployment/deno-netlify-functions" + "path": "/recipes/other/deno-netlify-functions" } ], "database": [ @@ -917,35 +949,35 @@ "file": "shared/recipes/database/nestjs-prisma", "id": "nestjs-prisma", "name": "Using Prisma with NestJS", - "path": "/recipes/database/nestjs-prisma" + "path": "/showcase/example-repos/nestjs-prisma" }, { "description": "", "file": "shared/recipes/database/mongo-fastify", "id": "mongo-fastify", "name": "Using Mongo with Fastify", - "path": "/recipes/database/mongo-fastify" + "path": "/showcase/example-repos/mongo-fastify" }, { "description": "", "file": "shared/recipes/database/redis-fastify", "id": "redis-fastify", "name": "Using Redis with Fastify", - "path": "/recipes/database/redis-fastify" + "path": "/showcase/example-repos/redis-fastify" }, { "description": "", "file": "shared/recipes/database/postgres-fastify", "id": "postgres-fastify", "name": "Using Postgres with Fastify", - "path": "/recipes/database/postgres-fastify" + "path": "/showcase/example-repos/postgres-fastify" }, { "description": "", "file": "shared/recipes/database/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/database/serverless-fastify-planetscale" + "path": "/showcase/example-repos/serverless-fastify-planetscale" } ], "serverless": [ @@ -954,23 +986,7 @@ "file": "shared/recipes/database/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/database/serverless-fastify-planetscale" - } - ], - "workspace-watching": [ - { - "description": "", - "file": "shared/recipes/workspace-watching", - "id": "workspace-watching", - "name": "Workspace Watching", - "path": "/recipes/other/workspace-watching" - }, - { - "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", - "file": "generated/packages/generated/packages/nx/documents/watch", - "id": "watch", - "name": "watch", - "path": "/packages/nx/documents/watch" + "path": "/showcase/example-repos/serverless-fastify-planetscale" } ] } diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 406d9b0d5d290..824b968d3701a 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -53,6 +53,15 @@ "path": "angular/executors/package", "type": "executor" }, + { + "description": "Builds your application with esbuild and adds support for incremental builds.", + "file": "generated/packages/angular/executors/browser-esbuild.json", + "hidden": false, + "name": "browser-esbuild", + "originalFilePath": "/packages/angular/src/executors/browser-esbuild/schema.json", + "path": "angular/executors/browser-esbuild", + "type": "executor" + }, { "description": "The `webpack-browser` executor is very similar to the standard `browser` builder provided by the Angular Devkit. It allows you to build your Angular application to a build artifact that can be hosted online. There are some key differences: \n- Supports Custom Webpack Configurations \n- Supports Incremental Building", "file": "generated/packages/angular/executors/webpack-browser.json", @@ -477,20 +486,20 @@ }, { "description": "Add a Cypress E2E Configuration to an existing project.", - "file": "generated/packages/cypress/generators/cypress-e2e-configuration.json", + "file": "generated/packages/cypress/generators/configuration.json", "hidden": false, - "name": "cypress-e2e-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-e2e-configuration/schema.json", - "path": "cypress/generators/cypress-e2e-configuration", + "name": "configuration", + "originalFilePath": "/packages/cypress/src/generators/configuration/schema.json", + "path": "cypress/generators/configuration", "type": "generator" }, { "description": "Set up Cypress Component Test for a project", - "file": "generated/packages/cypress/generators/cypress-component-configuration.json", + "file": "generated/packages/cypress/generators/component-configuration.json", "hidden": true, - "name": "cypress-component-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-component-configuration/schema.json", - "path": "cypress/generators/cypress-component-configuration", + "name": "component-configuration", + "originalFilePath": "/packages/cypress/src/generators/component-configuration/schema.json", + "path": "cypress/generators/component-configuration", "type": "generator" }, { @@ -642,11 +651,11 @@ }, { "description": "Add esbuild configuration to a project.", - "file": "generated/packages/esbuild/generators/esbuild-project.json", + "file": "generated/packages/esbuild/generators/configuration.json", "hidden": true, - "name": "esbuild-project", - "originalFilePath": "/packages/esbuild/src/generators/esbuild-project/schema.json", - "path": "esbuild/generators/esbuild-project", + "name": "configuration", + "originalFilePath": "/packages/esbuild/src/generators/configuration/schema.json", + "path": "esbuild/generators/configuration", "type": "generator" } ], @@ -680,6 +689,17 @@ "path": "eslint-plugin/documents/enforce-module-boundaries", "tags": [], "originalFilePath": "shared/packages/linter/enforce-module-boundaries" + }, + { + "id": "dependency-checks", + "name": "The `dependency-checks` rule", + "description": "The eslint-plugin package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called enforce-module-boundaries.", + "file": "generated/packages/eslint-plugin/documents/dependency-checks", + "itemList": [], + "isExternal": false, + "path": "eslint-plugin/documents/dependency-checks", + "tags": [], + "originalFilePath": "shared/packages/linter/dependency-checks" } ], "executors": [], @@ -939,11 +959,11 @@ }, { "description": "Add Jest configuration to a project.", - "file": "generated/packages/jest/generators/jest-project.json", + "file": "generated/packages/jest/generators/configuration.json", "hidden": true, - "name": "jest-project", - "originalFilePath": "/packages/jest/src/generators/jest-project/schema.json", - "path": "jest/generators/jest-project", + "name": "configuration", + "originalFilePath": "/packages/jest/src/generators/configuration/schema.json", + "path": "jest/generators/configuration", "type": "generator" } ], @@ -1613,7 +1633,7 @@ "itemList": [], "isExternal": false, "path": "nx/documents/format-check", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "originalFilePath": "generated/cli/format-check" }, { @@ -1624,7 +1644,7 @@ "itemList": [], "isExternal": false, "path": "nx/documents/format-write", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "originalFilePath": "generated/cli/format-write" }, { @@ -1668,7 +1688,7 @@ "itemList": [], "isExternal": false, "path": "nx/documents/workspace-lint", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "originalFilePath": "generated/cli/workspace-lint" }, { @@ -1796,6 +1816,58 @@ "root": "/packages/nx", "source": "/packages/nx/src" }, + { + "description": "The Nx Plugin for Playwright contains executors and generators allowing your workspace to use the powerful Playwright integration testing capabilities.", + "documents": [ + { + "id": "overview", + "name": "Overview", + "description": "The Nx Plugin for Playwright contains executors and generators allowing your workspace to use the powerful Playwright integration testing capabilities.", + "file": "generated/packages/playwright/documents/overview", + "itemList": [], + "isExternal": false, + "path": "playwright/documents/overview", + "tags": [], + "originalFilePath": "shared/packages/playwright/playwright-plugin" + } + ], + "executors": [ + { + "description": "Run Playwright tests.", + "file": "generated/packages/playwright/executors/playwright.json", + "hidden": false, + "name": "playwright", + "originalFilePath": "/packages/playwright/src/executors/playwright/schema.json", + "path": "playwright/executors/playwright", + "type": "executor" + } + ], + "generators": [ + { + "description": "Add Nx Playwright configuration to your project", + "file": "generated/packages/playwright/generators/configuration.json", + "hidden": false, + "name": "configuration", + "originalFilePath": "/packages/playwright/src/generators/configuration/schema.json", + "path": "playwright/generators/configuration", + "type": "generator" + }, + { + "description": "Initializes a Playwright project in the current workspace", + "file": "generated/packages/playwright/generators/init.json", + "hidden": false, + "name": "init", + "originalFilePath": "/packages/playwright/src/generators/init/schema.json", + "path": "playwright/generators/init", + "type": "generator" + } + ], + "githubRoot": "https://github.com/nrwl/nx/blob/master", + "name": "playwright", + "packageName": "@nx/playwright", + "root": "/packages/playwright", + "source": "/packages/playwright/src" + }, { "description": "This plugin is used to create Nx plugins! It contains generators for generating common plugin features like generators, executors, migrations and more.", "documents": [ @@ -2302,11 +2374,11 @@ }, { "description": "Add rollup configuration to a project.", - "file": "generated/packages/rollup/generators/rollup-project.json", + "file": "generated/packages/rollup/generators/configuration.json", "hidden": true, - "name": "rollup-project", - "originalFilePath": "/packages/rollup/src/generators/rollup-project/schema.json", - "path": "rollup/generators/rollup-project", + "name": "configuration", + "originalFilePath": "/packages/rollup/src/generators/configuration/schema.json", + "path": "rollup/generators/configuration", "type": "generator" } ], @@ -2396,6 +2468,17 @@ "tags": [], "originalFilePath": "shared/packages/storybook/custom-builder-configs" }, + { + "id": "storybook-interaction-tests", + "name": "Setting up Storybook Interaction Tests with Nx", + "description": "This guide explains how you can set up Storybook interaction tests on your Nx workspace.", + "file": "generated/packages/storybook/documents/storybook-interaction-tests", + "itemList": [], + "isExternal": false, + "path": "storybook/documents/storybook-interaction-tests", + "tags": [], + "originalFilePath": "shared/packages/storybook/interaction-tests" + }, { "id": "storybook-composition-setup", "name": "Setting up Storybook Composition with Nx", @@ -2743,11 +2826,11 @@ }, { "description": "Add webpack configuration to a project.", - "file": "generated/packages/webpack/generators/webpack-project.json", + "file": "generated/packages/webpack/generators/configuration.json", "hidden": true, - "name": "webpack-project", - "originalFilePath": "/packages/webpack/src/generators/webpack-project/schema.json", - "path": "webpack/generators/webpack-project", + "name": "configuration", + "originalFilePath": "/packages/webpack/src/generators/configuration/schema.json", + "path": "webpack/generators/configuration", "type": "generator" } ], @@ -2822,6 +2905,15 @@ "path": "workspace/generators/remove", "type": "generator" }, + { + "description": "Convert a Nx project to a monorepo.", + "file": "generated/packages/workspace/generators/convert-to-monorepo.json", + "hidden": false, + "name": "convert-to-monorepo", + "originalFilePath": "/packages/workspace/src/generators/convert-to-monorepo/schema.json", + "path": "workspace/generators/convert-to-monorepo", + "type": "generator" + }, { "description": "Create a workspace.", "file": "generated/packages/workspace/generators/new.json", diff --git a/docs/generated/packages/angular/documents/angular-nx-version-matrix.md b/docs/generated/packages/angular/documents/angular-nx-version-matrix.md index e6d79e4d79005..0fc34f98d2849 100644 --- a/docs/generated/packages/angular/documents/angular-nx-version-matrix.md +++ b/docs/generated/packages/angular/documents/angular-nx-version-matrix.md @@ -14,6 +14,7 @@ We provide a recommended version, and it is usually the latest minor version of | Angular Version | **Nx Version _(recommended)_** | Nx Version _(range)_ | | --------------- | ------------------------------ | --------------------------------------- | +| ~16.1.0 | **latest** | 16.4.0 <= latest | | ~16.0.0 | **latest** | 16.1.0 <= latest | | ~15.2.0 | **latest** | 15.8.0 <= latest | | ~15.1.0 | **latest** | 15.5.0 <= latest | diff --git a/docs/generated/packages/angular/documents/overview.md b/docs/generated/packages/angular/documents/overview.md index 88e1aa4d0e4ab..8883e2a5db5e3 100644 --- a/docs/generated/packages/angular/documents/overview.md +++ b/docs/generated/packages/angular/documents/overview.md @@ -12,7 +12,7 @@ within an Nx workspace. It provides: {% callout type="note" title="Currently using the Angular CLI?" %} You can easily and mostly **automatically migrate from an Angular CLI** project to Nx! Learn -more [here](/recipes/adopting-nx/migration-angular). +more [here](/recipes/angular/migration/angular). {% /callout %} ## Setting up the Angular plugin @@ -75,9 +75,9 @@ nx lint libName Read more about: -- [Creating Libraries](/more-concepts/creating-libraries) -- [Library Types](/more-concepts/library-types) -- [Buildable and Publishable Libraries](/more-concepts/buildable-and-publishable-libraries) +- [Creating Libraries](/concepts/more-concepts/creating-libraries) +- [Library Types](/concepts/more-concepts/library-types) +- [Buildable and Publishable Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) ### Fallback to `@schematics/angular` @@ -92,9 +92,7 @@ nx g @nx/angular:service my-service ## More Documentation - [Angular Nx Tutorial](/angular-tutorial/1-code-generation) -- [Migrating from the Angular CLI](/recipes/adopting-nx/migration-angular) -- [Setup Module Federation with Angular and Nx](/recipes/module-federation/faster-builds) -- [Using NgRx](/recipes/other/misc-ngrx) -- [Using Data Persistence operators](/recipes/other/misc-data-persistence) -- [Upgrading an AngularJS application to Angular](/recipes/adopting-nx/migration-angularjs) -- [Using Tailwind CSS with Angular projects](/recipes/other/using-tailwind-css-with-angular-projects) +- [Migrating from the Angular CLI](/recipes/angular/migration/angular) +- [Setup Module Federation with Angular and Nx](/concepts/more-concepts/faster-builds-with-module-federation) +- [Upgrading an AngularJS application to Angular](/recipes/angular/migration/angularjs) +- [Using Tailwind CSS with Angular projects](/recipes/angular/using-tailwind-css-with-angular-projects) diff --git a/docs/generated/packages/angular/executors/browser-esbuild.json b/docs/generated/packages/angular/executors/browser-esbuild.json new file mode 100644 index 0000000000000..242977c7b3520 --- /dev/null +++ b/docs/generated/packages/angular/executors/browser-esbuild.json @@ -0,0 +1,626 @@ +{ + "name": "browser-esbuild", + "implementation": "/packages/angular/src/executors/browser-esbuild/browser-esbuild.impl.ts", + "schema": { + "$schema": "http://json-schema.org/draft-07/schema", + "title": "Schema for Nx ESBuild Executor", + "description": "Nx ESBuild Executor supporting Incremental Builds.", + "outputCapture": "direct-nodejs", + "type": "object", + "properties": { + "assets": { + "type": "array", + "description": "List of static application assets.", + "default": [], + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "followSymlinks": { + "type": "boolean", + "default": false, + "description": "Allow glob patterns to follow symlink directories. This allows subdirectories of the symlink to be searched." + }, + "glob": { + "type": "string", + "description": "The pattern to match." + }, + "input": { + "type": "string", + "description": "The input directory path in which to apply 'glob'. Defaults to the project root." + }, + "ignore": { + "description": "An array of globs to ignore.", + "type": "array", + "items": { "type": "string" } + }, + "output": { + "type": "string", + "description": "Absolute path within the output." + } + }, + "additionalProperties": false, + "required": ["glob", "input", "output"] + }, + { "type": "string" } + ] + } + }, + "main": { + "type": "string", + "description": "The full path for the main entry point to the app, relative to the current workspace." + }, + "polyfills": { + "description": "Polyfills to be included in the build.", + "oneOf": [ + { + "type": "array", + "description": "A list of polyfills to include in the build. Can be a full path for a file, relative to the current workspace or module specifier. Example: 'zone.js'.", + "items": { "type": "string", "uniqueItems": true }, + "default": [] + }, + { + "type": "string", + "description": "The full path for the polyfills file, relative to the current workspace or a module specifier. Example: 'zone.js'." + } + ] + }, + "tsConfig": { + "type": "string", + "description": "The full path for the TypeScript configuration file, relative to the current workspace." + }, + "scripts": { + "description": "Global scripts to be included in the build.", + "type": "array", + "default": [], + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "input": { + "type": "string", + "description": "The file to include.", + "pattern": "\\.[cm]?jsx?$" + }, + "bundleName": { + "type": "string", + "pattern": "^[\\w\\-.]*$", + "description": "The bundle name for this extra entry point." + }, + "inject": { + "type": "boolean", + "description": "If the bundle will be referenced in the HTML file.", + "default": true + } + }, + "additionalProperties": false, + "required": ["input"] + }, + { + "type": "string", + "description": "The JavaScript/TypeScript file or package containing the file to include." + } + ] + } + }, + "styles": { + "description": "Global styles to be included in the build.", + "type": "array", + "default": [], + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "input": { + "type": "string", + "description": "The file to include.", + "pattern": "\\.(?:css|scss|sass|less)$" + }, + "bundleName": { + "type": "string", + "pattern": "^[\\w\\-.]*$", + "description": "The bundle name for this extra entry point." + }, + "inject": { + "type": "boolean", + "description": "If the bundle will be referenced in the HTML file.", + "default": true + } + }, + "additionalProperties": false, + "required": ["input"] + }, + { + "type": "string", + "description": "The file to include.", + "pattern": "\\.(?:css|scss|sass|less)$" + } + ] + } + }, + "inlineStyleLanguage": { + "description": "The stylesheet language to use for the application's inline component styles.", + "type": "string", + "default": "css", + "enum": ["css", "less", "sass", "scss"] + }, + "stylePreprocessorOptions": { + "description": "Options to pass to style preprocessors.", + "type": "object", + "properties": { + "includePaths": { + "description": "Paths to include. Paths will be resolved to workspace root.", + "type": "array", + "items": { "type": "string" }, + "default": [] + } + }, + "additionalProperties": false + }, + "externalDependencies": { + "description": "Exclude the listed external dependencies from being bundled into the bundle. Instead, the created bundle relies on these dependencies to be available during runtime.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "optimization": { + "description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.", + "default": true, + "x-user-analytics": "ep.ng_optimization", + "oneOf": [ + { + "type": "object", + "properties": { + "scripts": { + "type": "boolean", + "description": "Enables optimization of the scripts output.", + "default": true + }, + "styles": { + "description": "Enables optimization of the styles output.", + "default": true, + "oneOf": [ + { + "type": "object", + "properties": { + "minify": { + "type": "boolean", + "description": "Minify CSS definitions by removing extraneous whitespace and comments, merging identifiers and minimizing values.", + "default": true + }, + "inlineCritical": { + "type": "boolean", + "description": "Extract and inline critical CSS definitions to improve first paint time.", + "default": true + } + }, + "additionalProperties": false + }, + { "type": "boolean" } + ] + }, + "fonts": { + "description": "Enables optimization for fonts. This option requires internet access. `HTTPS_PROXY` environment variable can be used to specify a proxy server.", + "default": true, + "oneOf": [ + { + "type": "object", + "properties": { + "inline": { + "type": "boolean", + "description": "Reduce render blocking requests by inlining external Google Fonts and Adobe Fonts CSS definitions in the application's HTML index file. This option requires internet access. `HTTPS_PROXY` environment variable can be used to specify a proxy server.", + "default": true + } + }, + "additionalProperties": false + }, + { "type": "boolean" } + ] + } + }, + "additionalProperties": false + }, + { "type": "boolean" } + ] + }, + "fileReplacements": { + "description": "Replace compilation source files with other compilation source files in the build.", + "type": "array", + "items": { + "type": "object", + "properties": { + "replace": { + "type": "string", + "pattern": "\\.(([cm]?j|t)sx?|json)$" + }, + "with": { "type": "string", "pattern": "\\.(([cm]?j|t)sx?|json)$" } + }, + "additionalProperties": false, + "required": ["replace", "with"] + }, + "default": [] + }, + "outputPath": { + "type": "string", + "description": "The full path for the new output directory, relative to the current workspace.\nBy default, writes output to a folder named dist/ in the current project." + }, + "resourcesOutputPath": { + "type": "string", + "description": "The path where style resources will be placed, relative to outputPath." + }, + "aot": { + "type": "boolean", + "description": "Build using Ahead of Time compilation.", + "x-user-analytics": "ep.ng_aot", + "default": true + }, + "sourceMap": { + "description": "Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.", + "default": false, + "oneOf": [ + { + "type": "object", + "properties": { + "scripts": { + "type": "boolean", + "description": "Output source maps for all scripts.", + "default": true + }, + "styles": { + "type": "boolean", + "description": "Output source maps for all styles.", + "default": true + }, + "hidden": { + "type": "boolean", + "description": "Output source maps used for error reporting tools.", + "default": false + }, + "vendor": { + "type": "boolean", + "description": "Resolve vendor packages source maps.", + "default": false + } + }, + "additionalProperties": false + }, + { "type": "boolean" } + ] + }, + "vendorChunk": { + "type": "boolean", + "description": "Generate a seperate bundle containing only vendor libraries. This option should only be used for development to reduce the incremental compilation time.", + "default": false + }, + "commonChunk": { + "type": "boolean", + "description": "Generate a seperate bundle containing code used across multiple bundles.", + "default": true + }, + "baseHref": { + "type": "string", + "description": "Base url for the application being built." + }, + "deployUrl": { + "type": "string", + "description": "URL where files will be deployed.", + "x-deprecated": "Use \"baseHref\" option, \"APP_BASE_HREF\" DI token or a combination of both instead. For more information, see https://angular.io/guide/deployment#the-deploy-url." + }, + "verbose": { + "type": "boolean", + "description": "Adds more details to output logging.", + "default": false + }, + "progress": { + "type": "boolean", + "description": "Log progress to the console while building.", + "default": true + }, + "i18nMissingTranslation": { + "type": "string", + "description": "How to handle missing translations for i18n.", + "enum": ["warning", "error", "ignore"], + "default": "warning" + }, + "i18nDuplicateTranslation": { + "type": "string", + "description": "How to handle duplicate translations for i18n.", + "enum": ["warning", "error", "ignore"], + "default": "warning" + }, + "localize": { + "description": "Translate the bundles in one or more locales.", + "oneOf": [ + { "type": "boolean", "description": "Translate all locales." }, + { + "type": "array", + "description": "List of locales ID's to translate.", + "minItems": 1, + "items": { + "type": "string", + "pattern": "^[a-zA-Z]{2,3}(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?(-[a-zA-Z]{5,8})?(-x(-[a-zA-Z0-9]{1,8})+)?$" + } + } + ] + }, + "watch": { + "type": "boolean", + "description": "Run build when files change.", + "default": false + }, + "outputHashing": { + "type": "string", + "description": "Define the output filename cache-busting hashing mode.", + "default": "none", + "enum": ["none", "all", "media", "bundles"] + }, + "poll": { + "type": "number", + "description": "Enable and define the file watching poll time period in milliseconds." + }, + "deleteOutputPath": { + "type": "boolean", + "description": "Delete the output path before building.", + "default": true + }, + "preserveSymlinks": { + "type": "boolean", + "description": "Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set." + }, + "extractLicenses": { + "type": "boolean", + "description": "Extract all licenses in a separate file.", + "default": true + }, + "buildOptimizer": { + "type": "boolean", + "description": "Enables advanced build optimizations when using the 'aot' option.", + "default": true + }, + "namedChunks": { + "type": "boolean", + "description": "Use file name for lazy loaded chunks.", + "default": false + }, + "subresourceIntegrity": { + "type": "boolean", + "description": "Enables the use of subresource integrity validation.", + "default": false + }, + "serviceWorker": { + "type": "boolean", + "description": "Generates a service worker config for production builds.", + "default": false + }, + "ngswConfigPath": { + "type": "string", + "description": "Path to ngsw-config.json." + }, + "index": { + "description": "Configures the generation of the application's HTML index.", + "oneOf": [ + { + "type": "string", + "description": "The path of a file to use for the application's HTML index. The filename of the specified path will be used for the generated file and will be created in the root of the application's configured output path." + }, + { + "type": "object", + "description": "", + "properties": { + "input": { + "type": "string", + "minLength": 1, + "description": "The path of a file to use for the application's generated HTML index." + }, + "output": { + "type": "string", + "minLength": 1, + "default": "index.html", + "description": "The output path of the application's generated HTML index file. The full provided path will be used and will be considered relative to the application's configured output path." + } + }, + "required": ["input"] + }, + { + "const": false, + "description": "Does not generate an `index.html` file." + } + ] + }, + "statsJson": { + "type": "boolean", + "description": "Generates a 'stats.json' file which can be analyzed using tools such as 'webpack-bundle-analyzer'.", + "default": false + }, + "budgets": { + "description": "Budget thresholds to ensure parts of your application stay within boundaries which you set.", + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of budget.", + "enum": [ + "all", + "allScript", + "any", + "anyScript", + "anyComponentStyle", + "bundle", + "initial" + ] + }, + "name": { + "type": "string", + "description": "The name of the bundle." + }, + "baseline": { + "type": "string", + "description": "The baseline size for comparison." + }, + "maximumWarning": { + "type": "string", + "description": "The maximum threshold for warning relative to the baseline." + }, + "maximumError": { + "type": "string", + "description": "The maximum threshold for error relative to the baseline." + }, + "minimumWarning": { + "type": "string", + "description": "The minimum threshold for warning relative to the baseline." + }, + "minimumError": { + "type": "string", + "description": "The minimum threshold for error relative to the baseline." + }, + "warning": { + "type": "string", + "description": "The threshold for warning relative to the baseline (min & max)." + }, + "error": { + "type": "string", + "description": "The threshold for error relative to the baseline (min & max)." + } + }, + "additionalProperties": false, + "required": ["type"] + }, + "default": [] + }, + "webWorkerTsConfig": { + "type": "string", + "description": "TypeScript configuration for Web Worker modules." + }, + "crossOrigin": { + "type": "string", + "description": "Define the crossorigin attribute setting of elements that provide CORS support.", + "default": "none", + "enum": ["none", "anonymous", "use-credentials"] + }, + "allowedCommonJsDependencies": { + "description": "A list of CommonJS packages that are allowed to be used without a build time warning.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "buildLibsFromSource": { + "type": "boolean", + "description": "Read buildable libraries from source instead of building them separately.", + "default": true + } + }, + "additionalProperties": false, + "required": ["outputPath", "index", "main", "tsConfig"], + "definitions": { + "assetPattern": { + "oneOf": [ + { + "type": "object", + "properties": { + "followSymlinks": { + "type": "boolean", + "default": false, + "description": "Allow glob patterns to follow symlink directories. This allows subdirectories of the symlink to be searched." + }, + "glob": { + "type": "string", + "description": "The pattern to match." + }, + "input": { + "type": "string", + "description": "The input directory path in which to apply 'glob'. Defaults to the project root." + }, + "ignore": { + "description": "An array of globs to ignore.", + "type": "array", + "items": { "type": "string" } + }, + "output": { + "type": "string", + "description": "Absolute path within the output." + } + }, + "additionalProperties": false, + "required": ["glob", "input", "output"] + }, + { "type": "string" } + ] + }, + "fileReplacement": { + "type": "object", + "properties": { + "replace": { + "type": "string", + "pattern": "\\.(([cm]?j|t)sx?|json)$" + }, + "with": { "type": "string", "pattern": "\\.(([cm]?j|t)sx?|json)$" } + }, + "additionalProperties": false, + "required": ["replace", "with"] + }, + "budget": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of budget.", + "enum": [ + "all", + "allScript", + "any", + "anyScript", + "anyComponentStyle", + "bundle", + "initial" + ] + }, + "name": { + "type": "string", + "description": "The name of the bundle." + }, + "baseline": { + "type": "string", + "description": "The baseline size for comparison." + }, + "maximumWarning": { + "type": "string", + "description": "The maximum threshold for warning relative to the baseline." + }, + "maximumError": { + "type": "string", + "description": "The maximum threshold for error relative to the baseline." + }, + "minimumWarning": { + "type": "string", + "description": "The minimum threshold for warning relative to the baseline." + }, + "minimumError": { + "type": "string", + "description": "The minimum threshold for error relative to the baseline." + }, + "warning": { + "type": "string", + "description": "The threshold for warning relative to the baseline (min & max)." + }, + "error": { + "type": "string", + "description": "The threshold for error relative to the baseline (min & max)." + } + }, + "additionalProperties": false, + "required": ["type"] + } + }, + "presets": [] + }, + "description": "Builds your application with esbuild and adds support for incremental builds.", + "aliases": [], + "hidden": false, + "path": "/packages/angular/src/executors/browser-esbuild/schema.json", + "type": "executor" +} diff --git a/docs/generated/packages/angular/executors/module-federation-dev-server.json b/docs/generated/packages/angular/executors/module-federation-dev-server.json index 82305582cd68a..73ee722d00fb0 100644 --- a/docs/generated/packages/angular/executors/module-federation-dev-server.json +++ b/docs/generated/packages/angular/executors/module-federation-dev-server.json @@ -107,7 +107,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository." + "description": "List of remote applications to not automatically serve, either statically or in development mode." }, "pathToManifestFile": { "type": "string", diff --git a/docs/generated/packages/angular/executors/module-federation-dev-ssr.json b/docs/generated/packages/angular/executors/module-federation-dev-ssr.json index 362f71f47eaca..28330f038d446 100644 --- a/docs/generated/packages/angular/executors/module-federation-dev-ssr.json +++ b/docs/generated/packages/angular/executors/module-federation-dev-ssr.json @@ -72,7 +72,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository." + "description": "List of remote applications to not automatically serve, either statically or in development mode." }, "verbose": { "type": "boolean", diff --git a/docs/generated/packages/angular/executors/ng-packagr-lite.json b/docs/generated/packages/angular/executors/ng-packagr-lite.json index 5a6b2543c78dd..83213a14c759c 100644 --- a/docs/generated/packages/angular/executors/ng-packagr-lite.json +++ b/docs/generated/packages/angular/executors/ng-packagr-lite.json @@ -16,11 +16,7 @@ }, { "name": "Updating Project Dependencies for Buildable Library", - "keys": [ - "project", - "updateBuildableProjectDepsInPackageJson", - "buildableProjectDepsInPackageJsonType" - ] + "keys": ["project"] } ], "properties": { @@ -43,13 +39,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "tailwindConfig": { "type": "string", diff --git a/docs/generated/packages/angular/executors/package.json b/docs/generated/packages/angular/executors/package.json index 2efc57dc3abc4..a99e9c7cacf43 100644 --- a/docs/generated/packages/angular/executors/package.json +++ b/docs/generated/packages/angular/executors/package.json @@ -20,9 +20,7 @@ { "name": "Updating Project Dependencies for Publishable Library", "keys": [ - "project", - "updateBuildableProjectDepsInPackageJson", - "buildableProjectDepsInPackageJsonType" + "project" ] } ], @@ -46,7 +44,8 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", @@ -55,7 +54,8 @@ "dependencies", "peerDependencies" ], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "tailwindConfig": { "type": "string", diff --git a/docs/generated/packages/angular/executors/webpack-browser.json b/docs/generated/packages/angular/executors/webpack-browser.json index 1ba7e2a6db2e0..549d90b3b2d98 100644 --- a/docs/generated/packages/angular/executors/webpack-browser.json +++ b/docs/generated/packages/angular/executors/webpack-browser.json @@ -7,7 +7,7 @@ "$schema": "http://json-schema.org/draft-07/schema", "title": "Schema for Webpack Browser", "description": "The webpack-browser executor is very similar to the standard browser builder provided by the Angular Devkit. It allows you to build your Angular application to a build artifact that can be hosted online. There are some key differences: \n- Supports Custom Webpack Configurations \n- Supports Incremental Building", - "examplesFile": "##### Using a custom webpack configuration\n\nThe executor supports providing a path to a custom webpack configuration. This allows you to customize how your Angular application is built. It currently supports the following types of webpack configurations:\n\n- `object`\n- `Function`\n- `Promise`\n\nThe executor will merge the provided configuration with the webpack configuration that Angular Devkit uses. The merge order is:\n\n- Angular Devkit Configuration\n- Provided Configuration\n\nTo use a custom webpack configuration when building your Angular application, change the `build` target in your `project.json` to match the following:\n\n```typescript\n\"build\": {\n \"executor\": \"@nx/angular:webpack-browser\",\n \"options\": {\n ...\n \"customWebpackConfig\": {\n \"path\": \"apps/appName/webpack.config.js\"\n }\n }\n}\n```\n\n##### Incrementally Building your Application\n\nThe executor supports incrementally building your Angular application by building the workspace libraries it depends on _(that have been marked as buildable)_ and then building your application using the built source of the libraries.\n\nThis can improve build time as the building of the workspace libraries can be cached, meaning they only have to be rebuilt if they have changed.\n\n> Note: There may be some additional overhead in the linking of the built libraries' sources which may reduce the overall improvement in build time. Therefore this approach only benefits large applications and would likely have a negative impact on small and medium applications. \n> You can read more about when to use incremental builds [here](/more-concepts/incremental-builds#when-should-i-use-incremental-builds).\n\nTo allow your Angular application to take advantage of incremental building, change the `build` target in your `project.json` to match the following:\n\n```typescript\n\"build\": {\n \"executor\": \"@nx/angular:webpack-browser\",\n \"options\": {\n ...\n \"buildLibsFromSource\": false\n }\n}\n```\n", + "examplesFile": "##### Using a custom webpack configuration\n\nThe executor supports providing a path to a custom webpack configuration. This allows you to customize how your Angular application is built. It currently supports the following types of webpack configurations:\n\n- `object`\n- `Function`\n- `Promise`\n\nThe executor will merge the provided configuration with the webpack configuration that Angular Devkit uses. The merge order is:\n\n- Angular Devkit Configuration\n- Provided Configuration\n\nTo use a custom webpack configuration when building your Angular application, change the `build` target in your `project.json` to match the following:\n\n```typescript\n\"build\": {\n \"executor\": \"@nx/angular:webpack-browser\",\n \"options\": {\n ...\n \"customWebpackConfig\": {\n \"path\": \"apps/appName/webpack.config.js\"\n }\n }\n}\n```\n\n##### Incrementally Building your Application\n\nThe executor supports incrementally building your Angular application by building the workspace libraries it depends on _(that have been marked as buildable)_ and then building your application using the built source of the libraries.\n\nThis can improve build time as the building of the workspace libraries can be cached, meaning they only have to be rebuilt if they have changed.\n\n> Note: There may be some additional overhead in the linking of the built libraries' sources which may reduce the overall improvement in build time. Therefore this approach only benefits large applications and would likely have a negative impact on small and medium applications. \n> You can read more about when to use incremental builds [here](/concepts/more-concepts/incremental-builds#when-should-i-use-incremental-builds).\n\nTo allow your Angular application to take advantage of incremental building, change the `build` target in your `project.json` to match the following:\n\n```typescript\n\"build\": {\n \"executor\": \"@nx/angular:webpack-browser\",\n \"options\": {\n ...\n \"buildLibsFromSource\": false\n }\n}\n```\n", "type": "object", "presets": [ { diff --git a/docs/generated/packages/angular/generators/component-story.json b/docs/generated/packages/angular/generators/component-story.json index 5b82d4749c871..9332a52382030 100644 --- a/docs/generated/packages/angular/generators/component-story.json +++ b/docs/generated/packages/angular/generators/component-story.json @@ -32,6 +32,13 @@ "examples": ["awesome.component"], "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "default": true + }, "skipFormat": { "description": "Skip formatting files.", "type": "boolean", diff --git a/docs/generated/packages/angular/generators/stories.json b/docs/generated/packages/angular/generators/stories.json index bd89a9bbee66e..60b86a13beebf 100644 --- a/docs/generated/packages/angular/generators/stories.json +++ b/docs/generated/packages/angular/generators/stories.json @@ -18,11 +18,16 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "default": true + }, "generateCypressSpecs": { "type": "boolean", - "description": "Specifies whether to automatically generate `*.spec.ts` files in the Cypress e2e app generated by the `cypress-configure` generator.", - "x-prompt": "Do you want to generate Cypress specs as well?", - "x-priority": "important" + "description": "Specifies whether to automatically generate `*.spec.ts` files in the Cypress e2e app generated by the `cypress-configure` generator." }, "cypressProject": { "type": "string", @@ -49,7 +54,7 @@ }, "additionalProperties": false, "required": ["name"], - "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/angular:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:stories ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n", + "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/angular:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:stories ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n", "presets": [] }, "description": "Creates stories/specs for all components declared in a project.", diff --git a/docs/generated/packages/angular/generators/storybook-configuration.json b/docs/generated/packages/angular/generators/storybook-configuration.json index 81f3b4f30f0f1..485de50efcbed 100644 --- a/docs/generated/packages/angular/generators/storybook-configuration.json +++ b/docs/generated/packages/angular/generators/storybook-configuration.json @@ -18,12 +18,17 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "x-priority": "important", + "default": true + }, "configureCypress": { "type": "boolean", - "description": "Specifies whether to configure Cypress or not.", - "x-prompt": "Configure a Cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "description": "Specifies whether to configure Cypress or not." }, "generateStories": { "type": "boolean", @@ -34,10 +39,7 @@ }, "generateCypressSpecs": { "type": "boolean", - "description": "Specifies whether to automatically generate test files in the generated Cypress e2e app.", - "x-prompt": "Automatically generate test files in the generated Cypress e2e app?", - "default": true, - "x-priority": "important" + "description": "Specifies whether to automatically generate test files in the generated Cypress e2e app." }, "configureStaticServe": { "type": "boolean", @@ -59,7 +61,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false, + "default": true, "x-priority": "important" }, "skipFormat": { @@ -79,15 +81,11 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "additionalProperties": false, "required": ["name"], - "examplesFile": "This generator will set up Storybook for your **Angular** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/angular:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#generate-storybook-configuration-for-an-angular-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance. You can read more about this in the [Storybook for Angular - Cypress section](/packages/storybook/documents/overview-angular#cypress-tests-for-stories).\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner).\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/angular:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project.\n\n### Generate Storybook configuration using TypeScript\n\n```bash\nnx g @nx/angular:storybook-configuration ui --tsConfiguration=true\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n", + "examplesFile": "This generator will set up Storybook for your **Angular** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/angular:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#generate-storybook-configuration-for-an-angular-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/angular/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/angular:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/angular:storybook-configuration ui --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", "presets": [] }, "description": "Adds Storybook configuration to a project.", diff --git a/docs/generated/packages/cypress/documents/overview.md b/docs/generated/packages/cypress/documents/overview.md index 694532c7e2eb0..52868da3b9504 100644 --- a/docs/generated/packages/cypress/documents/overview.md +++ b/docs/generated/packages/cypress/documents/overview.md @@ -51,7 +51,7 @@ Replace `your-app-name` with the app's name as defined in your `tsconfig.base.js Run `nx e2e frontend-e2e` to execute e2e tests with Cypress. -You can run your e2e test against a production build by using the `production` [configuration](https://nx.dev/recipes/executors/use-executor-configurations#use-executor-configurations) +You can run your e2e test against a production build by using the `production` [configuration](https://nx.dev/plugin-features/use-task-executors#use-executor-configurations) ```shell nx e2e frontend-e2e --configuration=production diff --git a/docs/generated/packages/cypress/generators/component-configuration.json b/docs/generated/packages/cypress/generators/component-configuration.json new file mode 100644 index 0000000000000..6fc62deecec01 --- /dev/null +++ b/docs/generated/packages/cypress/generators/component-configuration.json @@ -0,0 +1,47 @@ +{ + "name": "component-configuration", + "aliases": ["cypress-component-configuration"], + "factory": "./src/generators/component-configuration/component-configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxCypressComponentConfiguration", + "cli": "nx", + "title": "Set up Cypress component testing for a project", + "description": "Set up Cypress component test for a project.", + "type": "object", + "examples": [ + { + "command": "nx g @nx/cypress:component-configuration --project=my-cool-lib ", + "description": "Add cypress component testing to an existing project named my-cool-lib" + } + ], + "properties": { + "project": { + "type": "string", + "description": "The name of the project to add cypress component testing to", + "$default": { "$source": "projectName" }, + "x-prompt": "What project should we add Cypress component testing to?" + }, + "bundler": { + "description": "The Cypress bundler to use.", + "type": "string", + "enum": ["vite", "webpack"], + "x-prompt": "Which Cypress bundler do you want to use for the dev-server?", + "default": "webpack" + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed relative from the project root", + "default": "cypress" + } + }, + "required": ["project"], + "examplesFile": "This is a framework-agnostic generator for adding component testing to a project.\n\n```bash\nnx g cypress-component-configuration --project=my-cool-project\n```\n\nRunning this generator, adds the required files to the specified project without any configurations for Cypress. It's best to use the framework specific generator, instead `cypress-component-configuration` directly\n\n- [React component testing](/packages/react/generators/cypress-component-configuration)\n- [Angular component testing](/packages/angular/generators/cypress-component-configuration)\n\nA new `component-test` target will be added to the specified project.\n\n```bash\nnx g component-test my-cool-project\n```\n\nRead more about [Cypress Component Testing](/cypress/cypress-component-testing)\n", + "presets": [] + }, + "description": "Set up Cypress Component Test for a project", + "hidden": true, + "implementation": "/packages/cypress/src/generators/component-configuration/component-configuration.ts", + "path": "/packages/cypress/src/generators/component-configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/cypress/generators/configuration.json b/docs/generated/packages/cypress/generators/configuration.json new file mode 100644 index 0000000000000..d9b209b8a9398 --- /dev/null +++ b/docs/generated/packages/cypress/generators/configuration.json @@ -0,0 +1,95 @@ +{ + "name": "configuration", + "aliases": ["cypress-e2e-configuration", "e2e", "e2e-config"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxCypressE2EConfigGenerator", + "cli": "nx", + "title": "Add a Cypress Configuration.", + "description": "Add a Cypress configuration to an existing project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The project to add a Cypress configuration to", + "$default": { "$source": "projectName" }, + "x-priority": "important", + "x-prompt": "What project do you want to add Cypress to?" + }, + "devServerTarget": { + "type": "string", + "description": "A devServerTarget,':[:], that will be used to run tests against. This is usually the app this project will be used in. Pass --baseUrl if you wish to not use a devServerTarget.", + "x-priority": "important" + }, + "port": { + "oneOf": [ + { "type": "string", "enum": ["cypress-auto"] }, + { "type": "number" } + ], + "description": "Set the 'port' option on the e2e target. It's recommend to set a different port so you can run tests e2e targets in parallel. Most dev servers support using '0' to automatically find a free port. The value 'cypress-auto' can be used if the underlying dev server does not support automatically finding a free port.", + "x-priority": "important" + }, + "baseUrl": { + "type": "string", + "description": "The address (with the port) which your application is running on. If you wish to start your application when running the e2e target, then use --devServerTarget instead." + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed relative from the project root", + "x-priority": "important", + "default": "cypress" + }, + "linter": { + "description": "The tool to use for running lint checks.", + "type": "string", + "enum": ["eslint", "none"], + "default": "eslint" + }, + "js": { + "description": "Generate JavaScript files rather than TypeScript files.", + "type": "boolean", + "default": false + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "setParserOptionsProject": { + "type": "boolean", + "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.", + "default": false + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "rootProject": { + "description": "Create a application at the root of the workspace", + "type": "boolean", + "default": false, + "hidden": true, + "x-priority": "internal" + }, + "bundler": { + "description": "The Cypress bundler to use.", + "type": "string", + "enum": ["vite", "webpack", "none"], + "x-prompt": "Which Cypress bundler do you want to use?", + "default": "webpack" + } + }, + "required": ["project"], + "examplesFile": "This is a generator to add a cypress e2e configuration to an existing project.\n\n```bash\nnx g @nx/cypress:configuration --project=my-cool-project --devServerTarget=some-app:serve\n```\n\nRunning this generator, adds the required files to run cypress tests for a project,\nMainly a `cypress.config.ts` file and default files in the `/cypress/` directory.\nTests will be located in `/cypress/e2e/*` by default.\n\nYou can customize the directory used via the `--directory` flag, the value is relative to the project root.\n\nFor example if you wanted to place the files inside an `e2e` folder\n\n```bash\nnx g @nx/cypress:configuration --project=my-cool-project --devServerTarget=some-app:serve --directory=e2e\n```\n\nProviding a `--devServerTarget` is optional if you provide a `--baseUrl` or the project you're adding the configuration to has a `serve` target already.\nOtherwise, a `--devServerTarget` is recommend for the `@nx/cypress:cypress` executor to spin up the dev server for you automatically when needed.\n\n## Feature Based Testing\n\nThis generator helps in creating feature based e2e/integration testing setups where you can place the feature tests in the same project as the feature library.\nThis differs from creating a separate e2e project that contained all tests for an application which can easily cause more tests to run than is strictly necessary.\n\nTake the following workspace where the `feature-cart` project is affected.\n\n{% graph height=\"450px\" %}\n\n```json\n{\n \"projects\": [\n {\n \"type\": \"app\",\n \"name\": \"fancy-app\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"app\",\n \"name\": \"fancy-app-e2e\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"lib\",\n \"name\": \"feature-user\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"lib\",\n \"name\": \"feature-dashboard\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"lib\",\n \"name\": \"feature-cart\",\n \"data\": {\n \"tags\": []\n }\n }\n ],\n \"groupByFolder\": false,\n \"workspaceLayout\": {\n \"appsDir\": \"apps\",\n \"libsDir\": \"libs\"\n },\n \"dependencies\": {\n \"fancy-app\": [\n {\n \"target\": \"feature-user\",\n \"source\": \"fancy-app\",\n \"type\": \"static\"\n },\n {\n \"target\": \"feature-cart\",\n \"source\": \"fancy-app\",\n \"type\": \"static\"\n }\n ],\n \"fancy-app-e2e\": [\n {\n \"target\": \"fancy-app\",\n \"source\": \"fancy-app-e2e\",\n \"type\": \"implicit\"\n }\n ],\n \"feature-user\": [\n {\n \"target\": \"feature-dashboard\",\n \"source\": \"feature-user\",\n \"type\": \"direct\"\n }\n ],\n \"feature-cart\": [],\n \"feature-dashboard\": []\n },\n \"affectedProjectIds\": [\"feature-cart\", \"fancy-app\", \"fancy-app-e2e\"]\n}\n```\n\n{% /graph %}\n\nIn this case, if tests for the all the `feature-*` projects where contained in the `fancy-app-e2e` project, then all of those features will be tested in the app, when only the `feature-cart` tests need to run.\n\nRunning these e2e/integration tests more often than they should results in longer CI times.\n\nBrining those e2e test closer to each feature can result is lowering CI times since we don't need to test those features if they did not change.\n\nBuilding this way leaves the `fancy-app-e2e` for mostly smoke type testing instead of more in-depth feature testing.\n\nUsing the `@nx/cypress:configuration` generator can help you accomplish this in your workspace.\n\n```bash\nnx g @nx/cypress:configuration --project=feature-cart --devServerTarget=fancy-app:serve\nnx g @nx/cypress:configuration --project=feature-user --devServerTarget=fancy-app:serve\nnx g @nx/cypress:configuration --project=feature-dashboard --devServerTarget=fancy-app:serve\n```\n\nEach project will now get their own `e2e` target, where the feature project is only concerned with itself. This allows for more focused tests without worrying about forcing unrelated tests to also run.\n\nIt's important to remember that these feature tests are still going to be leveraging the same app to run the tests against so if you plan to run in parallel, you can leverage using a file server and the ability for `@nx/cypress:cypress` executor to pass through a port or find a free port to allow running tests in parallel. Read more [about the --port flag](/packages/cypress/executors/cypress#port)\n", + "presets": [] + }, + "description": "Add a Cypress E2E Configuration to an existing project.", + "implementation": "/packages/cypress/src/generators/configuration/configuration.ts", + "hidden": false, + "path": "/packages/cypress/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/devkit/documents/nx_devkit.md b/docs/generated/packages/devkit/documents/nx_devkit.md index 463df7413aef4..d288ca40288b7 100644 --- a/docs/generated/packages/devkit/documents/nx_devkit.md +++ b/docs/generated/packages/devkit/documents/nx_devkit.md @@ -1397,7 +1397,7 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); ### getPackageManagerVersion -▸ **getPackageManagerVersion**(`packageManager?`): `string` +▸ **getPackageManagerVersion**(`packageManager?`, `cwd?`): `string` Returns the version of the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1408,6 +1408,7 @@ but it can also be passed in explicitly. | Name | Type | | :--------------- | :------------------------------------------------------------------ | | `packageManager` | [`PackageManager`](../../devkit/documents/nx_devkit#packagemanager) | +| `cwd` | `string` | #### Returns diff --git a/docs/generated/packages/esbuild/documents/overview.md b/docs/generated/packages/esbuild/documents/overview.md index 5dba8a19770a4..e080e503494fc 100644 --- a/docs/generated/packages/esbuild/documents/overview.md +++ b/docs/generated/packages/esbuild/documents/overview.md @@ -45,13 +45,13 @@ This command will install the esbuild plugin if needed, and set `@nx/esbuild:esb If you already have a JS project that you want to use esbuild for, run this command: ```shell -nx g esbuild-project mylib +nx g @nx/esbuild:configuration mylib ``` This generator validates there isn't an existing `build` target. If you want to overwrite the existing target you can pass the `--skipValidation` option. ```shell -nx g esbuild-project mylib --skipValidation +nx g @nx/esbuild:configuration mylib --skipValidation ``` ## Using esbuild diff --git a/docs/generated/packages/esbuild/executors/esbuild.json b/docs/generated/packages/esbuild/executors/esbuild.json index 67783d869a46c..fc93bfb457729 100644 --- a/docs/generated/packages/esbuild/executors/esbuild.json +++ b/docs/generated/packages/esbuild/executors/esbuild.json @@ -206,7 +206,7 @@ } }, "additionalProperties": true, - "examplesFile": "`/project.json`:\n\n```json\n{\n //...\n \"targets\": {\n //...\n \"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\"\n }\n }\n }\n}\n```\n\n```bash\nnx build \n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"CommonJS output\" %}\n\nThe CommonJS format is required in some environments, such as Electron applications. By default, `esbuild` will use the ESM format, which is recommended for Web and Node applications. You may also output to multiple formats.\n\n```bash\nnx build --format=cjs\nnx build --format=esm,cjs\nnx build # defaults to es# defaults to esm\n```\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"format\": [\"esm\", \"cjs\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"External packages\" %}\n\nYou can avoid packages from being bundled by providing the `external` option with a list of packages to skip.\n\nYou can also use `*` wildcard to match assets.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"external\": [\"lodash\", \"*.png\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"Skip type checking\" %}\n\nType checking is the slowest part of the build. You may want to skip type checking during build and run it as another job in CI.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"skipTypeCheck\": true\n}\n```\n\n{% /tab %}\n{% tab label=\"Additional esbuild options\" %}\n\nAdditional [esbuild options](https://esbuild.github.io/api/) can be passed using `esbuildOptions` in your project configuration.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"esbuildOptions\": {\n \"legalComments\": \"inline\"\n \"banner\": {\n \".js\": \"// banner\"\n },\n \"footer\": {\n \".js\": \"// footer\"\n }\n }\n}\n```\n\n{% /tab %}\n{% tabs %}\n", + "examplesFile": "`/project.json`:\n\n```jsonc\n{\n //...\n \"targets\": {\n //...\n \"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\"\n }\n }\n }\n}\n```\n\n```bash\nnx build \n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"CommonJS output\" %}\n\nThe CommonJS format is required in some environments, such as Electron applications. By default, `esbuild` will use the ESM format, which is recommended for Web and Node applications. You may also output to multiple formats.\n\n```bash\nnx build --format=cjs\nnx build --format=esm,cjs\nnx build # defaults to es# defaults to esm\n```\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"format\": [\"esm\", \"cjs\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"External packages\" %}\n\nYou can avoid packages from being bundled by providing the `external` option with a list of packages to skip.\n\nYou can also use `*` wildcard to match assets.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"external\": [\"lodash\", \"*.png\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"Skip type checking\" %}\n\nType checking is the slowest part of the build. You may want to skip type checking during build and run it as another job in CI.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"skipTypeCheck\": true\n}\n```\n\n{% /tab %}\n{% tab label=\"Additional esbuild options\" %}\n\nAdditional [esbuild options](https://esbuild.github.io/api/) can be passed using `esbuildOptions` in your project configuration.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"esbuildOptions\": {\n \"legalComments\": \"inline\"\n \"banner\": {\n \".js\": \"// banner\"\n },\n \"footer\": {\n \".js\": \"// footer\"\n }\n }\n}\n```\n\n{% /tab %}\n{% tabs %}\n", "presets": [] }, "description": "Bundle a package using EsBuild.", diff --git a/docs/generated/packages/esbuild/generators/configuration.json b/docs/generated/packages/esbuild/generators/configuration.json new file mode 100644 index 0000000000000..0dd6daf91f77e --- /dev/null +++ b/docs/generated/packages/esbuild/generators/configuration.json @@ -0,0 +1,75 @@ +{ + "name": "configuration", + "aliases": ["esbuild-project"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxEsBuildProject", + "cli": "nx", + "title": "Add esbuild configuration to a project", + "description": "Add esbuild configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "argv", "index": 0 }, + "x-dropdown": "project", + "x-prompt": "What is the name of the project to set up a esbuild for?", + "x-priority": "important" + }, + "main": { + "type": "string", + "description": "Path relative to the workspace root for the main entry file. Defaults to `/src/main.ts` or `src/index.ts`, whichever is found.", + "alias": "entryFile", + "x-priority": "important" + }, + "tsConfig": { + "type": "string", + "description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to `/tsconfig.app.json` or `/tsconfig.lib.json`, whichever is found.", + "x-priority": "important" + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "skipValidation": { + "type": "boolean", + "default": false, + "description": "Do not perform any validation on existing project.", + "x-priority": "internal" + }, + "importPath": { + "type": "string", + "description": "The library name used to import it, like `@myorg/my-awesome-lib`." + }, + "platform": { + "type": "string", + "description": "Platform target for outputs.", + "enum": ["browser", "node", "neutral"], + "default": "node" + }, + "buildTarget": { + "description": "The build target to add.", + "type": "string", + "default": "build" + } + }, + "required": [], + "examplesFile": "```bash\nnx g @nx/esbuild:configuration my-package\n```\n\n{% callout type=\"note\" title=\"Overwriting existing build option\" %}\nThe `configuration` generator validates that an existing `build` target isn't already defined for the project. If you are adding esbuild to a project with an existing `build` target, pass the `--skipValidation` option.\n{% /callout %}\n\nYou may also provide a custom main entry file, or a custom tsconfig file if the defaults don't work. By default, the generator will look for a main file matching `src/index.ts` or `src/main.ts`, and a tsconfig file matching `tsconfig.app.json` or `tsconfig.lib.json`.\n\n```bash\nnx g @nx/esbuild:configuration my-package \\\n--main=packages/my-package/src/entry.ts \\\n--tsConfig=packages/my-package/tsconfig.custom.json\n```\n", + "presets": [] + }, + "description": "Add esbuild configuration to a project.", + "hidden": true, + "implementation": "/packages/esbuild/src/generators/configuration/configuration.ts", + "path": "/packages/esbuild/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/eslint-plugin/documents/dependency-checks.md b/docs/generated/packages/eslint-plugin/documents/dependency-checks.md new file mode 100644 index 0000000000000..10733d0326170 --- /dev/null +++ b/docs/generated/packages/eslint-plugin/documents/dependency-checks.md @@ -0,0 +1,81 @@ +# Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project depends on. If your project is using, for example, the `axios`, but the `package.json` does not specify it as a dependency, your library might not work correctly. This rule helps catch these problems before your users do. + +The rule uses the project graph to collect all the dependencies of your project, based on the input of your `build` target. It will filter out all the dependencies marked as `devDependencies` in your root `package.json` to ensure dependencies of your compilation pipelines (e.g. dependencies of `webpack.config` or `vite.config`) or test setups are not included in the expected list. + +We use the version numbers of the installed packages when checking whether the version specifier in `package.json` is correct. We do this because this is the only version for which we can "guarantee" that things work and were tested. If you specify a range outside of that version, that would mean that you are shipping potentially untested code. + +## Usage + +Library generators from `@nx` packages will configure this rule automatically when you opt-in for bundler/build setup. This rule is intended for publishable/buildable libraries, so it will only run if a `build` target is detected in the configuration (this name can be modified - see [options](#options)). + +### Manual setup + +To set it up manually for existing libraries, you need to add the `dependency-checks` rule to your project's ESLint configuration: + +```jsonc {% fileName="/.eslintrc.json" %} +{ + // ... more ESLint config here + "overrides": [ + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/dependency-checks": "error" + } + } + // ... more ESLint overrides here + ] +} +``` + +Additionally, you need to adjust your `lintFilePatterns` to include the project's `package.json` file:: + +```jsonc {% fileName="/project.json" %} +{ + // ... project.json config + "targets": { + // ... more targets + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": [ + "libs/my-lib/**/*.{ts,tsx,js,jsx}", + "libs/my-lib/package.json" // add this line + ] + } + } + } +} +``` + +### Overriding defaults + +Sometimes we intentionally want to add or remove a dependency from our `package.json` despite what the rule suggests. We can use the rule's options to override default behavior: + +```jsonc {% fileName=".eslintrc.json" %} +{ + "@nx/dependency-checks": [ + "error", + { + "buildTargets": ["build", "custom-build"], // add non standard build target names + "ignoredDependencies": ["lodash"], // these libs will be omitted from checks + "checkMissingDependencies": true, // toggle to disable + "checkObsoleteDependencies": true, // toggle to disable + "checkVersionMismatches": true // toggle to disable + } + ] +} +``` + +## Options + +| Property | Type | Default | Description | +| ------------------------- | --------------- | ----------- | ----------------------------------------------------------------------- | +| buildTargets | _Array_ | _["build"]_ | List of build target names | +| ignoredDependencies | _Array_ | _[]_ | List of dependencies to ignore for checks | +| checkMissingDependencies | _boolean_ | _true_ | Disable to skip checking for missing dependencies | +| checkObsoleteDependencies | _boolean_ | _true_ | Disable to skip checking for unused dependencies | +| checkVersionMismatches | _boolean_ | _true_ | Disable to skip checking if version specifier matches installed version | diff --git a/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md b/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md index 17df00f19fed5..3601b6a11b30a 100644 --- a/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md +++ b/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md @@ -1,3 +1,5 @@ +# Enforce module boundaries rule + The `@nx/enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps to prevent unplanned cross-dependencies. ## Usage @@ -51,7 +53,7 @@ The `depConstraints` is an array of objects representing the constraints defined Read more about the proper usage of this rule: -- [Enforce Project Boundaries](/core-features/enforce-project-boundaries) +- [Enforce Module Boundaries](/core-features/enforce-module-boundaries) - [Ban Dependencies with Certain Tags](/recipes/enforce-module-boundaries/ban-dependencies-with-tags) - [Tag in Multiple Dimensions](/recipes/enforce-module-boundaries/tag-multiple-dimensions) - [Ban External Imports](/recipes/enforce-module-boundaries/ban-external-imports) diff --git a/docs/generated/packages/eslint-plugin/documents/overview.md b/docs/generated/packages/eslint-plugin/documents/overview.md index 7c966c2c24aba..7b00732054f64 100644 --- a/docs/generated/packages/eslint-plugin/documents/overview.md +++ b/docs/generated/packages/eslint-plugin/documents/overview.md @@ -1,4 +1,7 @@ -The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called [enforce-module-boundaries](#enforce-module-boundaries-rule). +The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as the following Nx-specific ESLint rules: + +- [enforce-module-boundaries](#enforce-module-boundaries-rule) +- [dependency-checks](#dependency-checks-rule) ## Setting Up ESLint Plugin @@ -54,4 +57,8 @@ You can also use `@nx/react` which includes all three `@nx/react-*` plugins ### Enforce Module Boundaries rule -The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps keep prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries) +The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries). + +### Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project actually depends on. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/dependency-checks). diff --git a/docs/generated/packages/expo/documents/overview.md b/docs/generated/packages/expo/documents/overview.md index 2bd3082683376..b7b9e37ba971a 100644 --- a/docs/generated/packages/expo/documents/overview.md +++ b/docs/generated/packages/expo/documents/overview.md @@ -50,7 +50,7 @@ nx start my-app To generate a new library run: ```shell -npx nx g @nx/react-native:lib your-lib-name +npx nx g @nx/expo:lib your-lib-name ``` ### Generating Components @@ -58,7 +58,7 @@ npx nx g @nx/react-native:lib your-lib-name To generate a new component inside library run: ```shell -npx nx g @nx/react-native:component your-component-name --project=your-lib-name --export +npx nx g @nx/expo:component your-component-name --project=your-lib-name --export ``` Replace `your-lib-name` with the app's name as defined in your `tsconfig.base.json` file or the `name` property of your `package.json` @@ -247,6 +247,28 @@ To check the details of your build status, run: nx build-list ``` +### Submit an EAS Build + +EAS Submit is a hosted service for uploading and submitting your app binaries to the app stores. Since it's a hosted service, you can submit your app to both stores as long as you can run EAS CLI on your machine. + +To submit an EAS build: + +```shell +nx submit +``` + +### Update an EAS Build + +EAS Update is a hosted service that serves updates for projects using the `expo-updates` library. + +EAS Update makes fixing small bugs and pushing quick fixes a snap in between app store submissions. It accomplishes this by allowing an end-user's app to swap out the non-native parts of their app (for example, JS, styling, and image changes) with a new update that contains bug fixes and other updates. + +To update an EAS build: + +```shell +nx update +``` + ### Testing Projects You can run unit tests with: @@ -269,6 +291,8 @@ Below table is a map between expo commands and Nx commands: | `expo install` | `nx install ` | | `eas build` | `nx build ` | | `eas build:list` | `nx build-list ` | +| `eas update` | `nx update ` | +| `eas submit` | `nx submit ` | ## More Documentation diff --git a/docs/generated/packages/expo/executors/build.json b/docs/generated/packages/expo/executors/build.json index c1bc9395e445f..7d5fc37afc68f 100644 --- a/docs/generated/packages/expo/executors/build.json +++ b/docs/generated/packages/expo/executors/build.json @@ -46,7 +46,8 @@ }, "output": { "type": "string", - "description": "Output path for local build" + "description": "Output path for local build", + "examples": ["../../dist/MyApp.tar.gz", "../../dist"] }, "wait": { "type": "boolean", diff --git a/docs/generated/packages/expo/executors/export.json b/docs/generated/packages/expo/executors/export.json index c0f3b59dad77c..0c751fa7f57d2 100644 --- a/docs/generated/packages/expo/executors/export.json +++ b/docs/generated/packages/expo/executors/export.json @@ -34,11 +34,11 @@ "description": "Maximum number of tasks to allow Metro to spawn" }, "dumpAssetmap": { - "type": "string", + "type": "boolean", "description": "Dump the asset map for further processing" }, "dumpSourcemap": { - "type": "string", + "type": "boolean", "description": "Dump the source map for debugging the JS bundle" }, "bundler": { diff --git a/docs/generated/packages/expo/executors/run.json b/docs/generated/packages/expo/executors/run.json index 668255c4e7e2f..2e93f59d43d55 100644 --- a/docs/generated/packages/expo/executors/run.json +++ b/docs/generated/packages/expo/executors/run.json @@ -42,6 +42,7 @@ "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", "default": true, + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "x-priority": "internal" }, "port": { diff --git a/docs/generated/packages/expo/executors/start.json b/docs/generated/packages/expo/executors/start.json index 5a1de553705ec..681aa875edc0e 100644 --- a/docs/generated/packages/expo/executors/start.json +++ b/docs/generated/packages/expo/executors/start.json @@ -88,6 +88,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true } }, diff --git a/docs/generated/packages/jest/generators/configuration.json b/docs/generated/packages/jest/generators/configuration.json new file mode 100644 index 0000000000000..db31c454178e0 --- /dev/null +++ b/docs/generated/packages/jest/generators/configuration.json @@ -0,0 +1,89 @@ +{ + "name": "configuration", + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxJestProject", + "cli": "nx", + "title": "Add Jest Configuration to a project", + "description": "Add Jest Configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "projectName" }, + "x-priority": "important" + }, + "skipSetupFile": { + "type": "boolean", + "description": "Skips the setup file required for angular.", + "default": false, + "x-deprecated": "Use `--setup-file` instead." + }, + "setupFile": { + "type": "string", + "enum": ["none", "angular", "web-components"], + "description": "The setup file to be generated.", + "default": "none", + "x-priority": "important" + }, + "skipSerializers": { + "type": "boolean", + "description": "Skips the serializers required to snapshot angular templates.", + "default": false + }, + "supportTsx": { + "type": "boolean", + "description": "Setup `tsx` support.", + "default": false, + "x-priority": "important" + }, + "testEnvironment": { + "type": "string", + "enum": ["jsdom", "node", "none"], + "description": "The test environment for jest.", + "default": "jsdom", + "x-priority": "important" + }, + "compiler": { + "type": "string", + "enum": ["tsc", "babel", "swc"], + "description": "The compiler to use for source and tests.", + "default": "tsc" + }, + "babelJest": { + "type": "boolean", + "alias": "babel-jest", + "description": "Use `babel-jest` instead of `ts-jest`.", + "x-deprecated": "Use `--compiler=babel` instead.", + "default": false + }, + "skipFormat": { + "description": "Skip formatting files", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "js": { + "type": "boolean", + "default": false, + "description": "Use JavaScript instead of TypeScript for config files" + } + }, + "required": [], + "presets": [] + }, + "description": "Add Jest configuration to a project.", + "hidden": true, + "implementation": "/packages/jest/src/generators/configuration/configuration.ts", + "aliases": [], + "path": "/packages/jest/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/js/executors/node.json b/docs/generated/packages/js/executors/node.json index 57200acfaabcc..b93476e9bf59c 100644 --- a/docs/generated/packages/js/executors/node.json +++ b/docs/generated/packages/js/executors/node.json @@ -28,12 +28,14 @@ "host": { "type": "string", "default": "localhost", - "description": "The host to inspect the process on." + "description": "The host to inspect the process on.", + "x-priority": "important" }, "port": { "type": "number", "default": 9229, - "description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes." + "description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes.", + "x-priority": "important" }, "inspect": { "oneOf": [ @@ -41,33 +43,44 @@ { "type": "boolean" } ], "description": "Ensures the app is starting with debugging.", - "default": "inspect" + "default": "inspect", + "x-priority": "important" }, "runtimeArgs": { "type": "array", "description": "Extra args passed to the node process.", "default": [], - "items": { "type": "string" } + "items": { "type": "string" }, + "x-priority": "important" }, "args": { "type": "array", "description": "Extra args when starting the app.", "default": [], - "items": { "type": "string" } + "items": { "type": "string" }, + "x-priority": "important" }, "watch": { "type": "boolean", "description": "Enable re-building when files change.", - "default": true + "default": true, + "x-priority": "important" }, "debounce": { "type": "number", "description": "Delay in milliseconds to wait before restarting. Useful to batch multiple file changes events together. Set to zero (0) to disable.", - "default": 500 + "default": 500, + "x-priority": "important" + }, + "runBuildTargetDependencies": { + "type": "boolean", + "description": "Whether to run dependencies before running the build. Set this to true if the project does not build libraries from source (e.g. 'buildLibsFromSource: false').", + "default": false } }, "additionalProperties": false, "required": ["buildTarget"], + "examplesFile": "---\ntitle: JS Node executor examples\ndescription: This page contains examples for the @nx/js:node executor.\n---\n\nThe `@nx/js:node` executor runs the output of a build target. For example, an application uses esbuild ([`@nx/esbuild:esbuild`](/packages/esbuild/executors/esbuild)) to output the bundle to `dist/my-app` folder, which can then be executed by `@nx/js:node`.\n\n`project.json`:\n\n```json\n\"my-app\": {\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/js:node\",\n \"options\": {\n \"buildTarget\": \"my-app:build\"\n }\n },\n \"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"my-app/src/main.ts\",\n \"output\": [\"dist/my-app\"],\n //...\n }\n },\n }\n}\n```\n\n```bash\nnpx nx serve my-app\n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Pass extra Node CLI arguments\" %}\n\nUsing `runtimeArgs`, you can pass arguments to the underlying `node` command. For example, if you want to set [`--no-warnings`](https://nodejs.org/api/cli.html#--no-warnings) to silence all Node warnings, then add the following to the `project.json` file.\n\n```json\n\"my-app\": {\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/js:node\",\n \"options\": {\n \"runtimeArgs\": [\"--no-warnings\"],\n //...\n },\n },\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Run all task dependencies\" %}\n\nIf your application build depends on other tasks, and you want those tasks to also be executed, then set the `runBuildTargetDependencies` to `true`. For example, a library may have a task to generate GraphQL schemas, which is consume by the application. In this case, you want to run the generate task before building and running the application.\n\nThis option is also useful when the build consumes a library from its output, not its source. For example, if an executor that supports `buildLibsFromSource` option has it set to `false` (e.g. [`@nx/webpack:webpack`](/packages/webpack/executors/webpack)).\n\nNote that this option will increase the build time, so use it only when necessary.\n\n```json\n\"my-app\": {\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/js:node\",\n \"options\": {\n \"runBuildTargetDependencies\": true,\n //...\n },\n },\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n", "presets": [] }, "description": "Execute a Node application.", diff --git a/docs/generated/packages/js/executors/swc.json b/docs/generated/packages/js/executors/swc.json index 48bec366c3f6f..a64ff99c5c489 100644 --- a/docs/generated/packages/js/executors/swc.json +++ b/docs/generated/packages/js/executors/swc.json @@ -14,18 +14,34 @@ "type": "string", "description": "The name of the main entry-point file.", "x-completion-type": "file", - "x-completion-glob": "main@(.js|.ts|.tsx)" + "x-completion-glob": "main@(.js|.ts|.tsx)", + "x-priority": "important" + }, + "generateExportsField": { + "type": "boolean", + "alias": "exports", + "description": "Update the output package.json file's 'exports' field. This field is used by Node and bundles.", + "x-priority": "important", + "default": false + }, + "additionalEntryPoints": { + "type": "array", + "description": "Additional entry-points to add to exports field in the package.json file.", + "items": { "type": "string" }, + "x-priority": "important" }, "outputPath": { "type": "string", "description": "The output path of the generated files.", - "x-completion-type": "directory" + "x-completion-type": "directory", + "x-priority": "important" }, "tsConfig": { "type": "string", "description": "The path to the Typescript configuration file.", "x-completion-type": "file", - "x-completion-glob": "tsconfig.*.json" + "x-completion-glob": "tsconfig.*.json", + "x-priority": "important" }, "swcrc": { "type": "string", @@ -98,13 +114,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "external": { "description": "A list projects to be treated as external. This feature is experimental", diff --git a/docs/generated/packages/js/executors/tsc.json b/docs/generated/packages/js/executors/tsc.json index a0f26a4878d02..ea97b20122c7d 100644 --- a/docs/generated/packages/js/executors/tsc.json +++ b/docs/generated/packages/js/executors/tsc.json @@ -14,7 +14,21 @@ "type": "string", "description": "The name of the main entry-point file.", "x-completion-type": "file", - "x-completion-glob": "main@(.js|.ts|.jsx|.tsx)" + "x-completion-glob": "main@(.js|.ts|.jsx|.tsx)", + "x-priority": "important" + }, + "generateExportsField": { + "type": "boolean", + "alias": "exports", + "description": "Update the output package.json file's 'exports' field. This field is used by Node and bundles.", + "default": false, + "x-priority": "important" + }, + "additionalEntryPoints": { + "type": "array", + "description": "Additional entry-points to add to exports field in the package.json file.", + "items": { "type": "string" }, + "x-priority": "important" }, "rootDir": { "type": "string", @@ -23,13 +37,15 @@ "outputPath": { "type": "string", "description": "The output path of the generated files.", - "x-completion-type": "directory" + "x-completion-type": "directory", + "x-priority": "important" }, "tsConfig": { "type": "string", "description": "The path to the Typescript configuration file.", "x-completion-type": "file", - "x-completion-glob": "tsconfig.*.json" + "x-completion-glob": "tsconfig.*.json", + "x-priority": "important" }, "assets": { "type": "array", @@ -98,13 +114,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "external": { "description": "A list projects to be treated as external. This feature is experimental", @@ -172,7 +190,7 @@ ] } }, - "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Using TypeScript Transformer Plugins\" %}\n\n`@nx/js:tsc` can run the [TypeScript Transformers](https://github.com/madou/typescript-transformer-handbook) by using the `transformers` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"transformers\": [\n \"@nestjs/swagger/plugin\",\n {\n \"name\": \"@automapper/classes/transformer-plugin\",\n \"options\": {}\n }\n ]\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Inline libraries\" %}\n\n`@nx/js:tsc` can inline non-buildable libraries by opt-in to **Inlining** mode with `external` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"all\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=all\n```\n\n`@nx/js:tsc` can also inline buildable libraries by setting `external: 'none'`\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"none\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=none\n```\n\n{% /tab %}\n{% /tabs %}\n", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Using TypeScript Transformer Plugins\" %}\n\n`@nx/js:tsc` can run the [TypeScript Transformers](https://github.com/madou/typescript-transformer-handbook) by using the `transformers` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"transformers\": [\n \"@nestjs/swagger/plugin\",\n {\n \"name\": \"@automapper/classes/transformer-plugin\",\n \"options\": {}\n }\n ]\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Inline libraries\" %}\n\n`@nx/js:tsc` can inline non-buildable libraries by opt-in to **Inlining** mode with `external` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"all\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=all\n```\n\n`@nx/js:tsc` can also inline buildable libraries by setting `external: 'none'`\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"none\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=none\n```\n\n{% /tab %}\n{% tab label=\"Batch mode execution\" %}\n\nThe `@nx/js:tsc` executor supports running multiple tasks in a single process. When running in batch mode, the executor uses the [TypeScript APIs for incremental builds](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript). This results in a much faster build time when compared to the default implementation (the bigger the task graph to run, the more the performance improvements).\n\n{% callout type=\"warning\" title=\"Experimental feature\" %}\nExecuting tasks in batch mode is an experimental feature.\n{% /callout %}\n\n{% callout type=\"info\" title=\"Requirements\" %}\nBuilding a project with the `@nx/js:tsc` executor in batch mode requires all dependent projects to be buildable and built using the `@nx/js:tsc` executor.\n{% /callout %}\n\nTo run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`:\n\n```shell\nNX_BATCH_MODE=true nx build ts-lib\n```\n\nFor optimal performance, you could set the `clean` option to `false`. Otherwise, the executor cleans the output folder before running the build, which results in the loss of the [`.tsbuildinfo` file](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile) and, consequently, the loss of important optimizations performed by TypeScript. This is not a requirement. Even if the `clean` option is not set to `false` there are other important optimizations that are performed by the batch implementation.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"clean\": false\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n", "presets": [] }, "description": "Build a project using TypeScript.", diff --git a/docs/generated/packages/linter/executors/eslint.json b/docs/generated/packages/linter/executors/eslint.json index 55c5c268f4f12..82d84942d39d5 100644 --- a/docs/generated/packages/linter/executors/eslint.json +++ b/docs/generated/packages/linter/executors/eslint.json @@ -128,6 +128,11 @@ "type": "string", "enum": ["off", "warn", "error"], "description": "The equivalent of the `--report-unused-disable-directives` flag on the ESLint CLI." + }, + "printConfig": { + "type": "string", + "description": "The equivalent of the `--print-config` flag on the ESLint CLI.", + "x-completion-type": "file" } }, "required": ["lintFilePatterns"], diff --git a/docs/generated/packages/nest/documents/overview.md b/docs/generated/packages/nest/documents/overview.md index c9d5662de20da..76f73a9778576 100644 --- a/docs/generated/packages/nest/documents/overview.md +++ b/docs/generated/packages/nest/documents/overview.md @@ -67,7 +67,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 ``` -> Read more about [building and publishing libraries here](/more-concepts/buildable-and-publishable-libraries). +> Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). ### Nest Generators diff --git a/docs/generated/packages/next/documents/overview.md b/docs/generated/packages/next/documents/overview.md index 9670ebee10f12..a5c8681e00892 100644 --- a/docs/generated/packages/next/documents/overview.md +++ b/docs/generated/packages/next/documents/overview.md @@ -38,8 +38,8 @@ Nx allows you to create libraries with just one command. Some reasons you might - Publish a package to be used outside the monorepo - Better visualize the architecture using `nx graph` -For more information on Nx libraries, see our documentation on [Creating Libraries](/more-concepts/creating-libraries) -and [Library Types](/more-concepts/library-types). +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: @@ -161,7 +161,7 @@ nx export my-new-app Once you are ready to deploy your Next.js application, you have absolute freedom to choose any hosting provider that fits your needs. -You may know that the company behind Next.js, Vercel, has a great hosting platform offering that is developed in tandem with Next.js itself to offer a great overall developer and user experience. We have detailed [how to deploy your Next.js application to Vercel in a separate guide](/recipes/deployment/deploy-nextjs-to-vercel). +You may know that the company behind Next.js, Vercel, has a great hosting platform offering that is developed in tandem with Next.js itself to offer a great overall developer and user experience. We have detailed [how to deploy your Next.js application to Vercel in a separate guide](/recipes/react/deploy-nextjs-to-vercel). ## More Documentation diff --git a/docs/generated/packages/next/generators/application.json b/docs/generated/packages/next/generators/application.json index f5531bc6db6ab..594c4d7df9eb6 100644 --- a/docs/generated/packages/next/generators/application.json +++ b/docs/generated/packages/next/generators/application.json @@ -81,8 +81,9 @@ }, "e2eTestRunner": { "type": "string", - "enum": ["cypress", "none"], + "enum": ["cypress", "playwright", "none"], "description": "Test runner to use for end to end (E2E) tests.", + "x-prompt": "Which E2E test runner would you like to use?", "default": "cypress" }, "tags": { diff --git a/docs/generated/packages/nx/documents/show.md b/docs/generated/packages/nx/documents/show.md index 7e293151ed8f5..0c22a989345c8 100644 --- a/docs/generated/packages/nx/documents/show.md +++ b/docs/generated/packages/nx/documents/show.md @@ -159,7 +159,7 @@ Show only projects that have a specific target ### project -Show a list of targets in the workspace. +Shows resolved project configuration for a given project. ```shell nx show project @@ -177,7 +177,7 @@ Show help Type: `string` -Show targets for the given project +Which project should be viewed? ##### version diff --git a/docs/generated/packages/playwright/documents/overview.md b/docs/generated/packages/playwright/documents/overview.md new file mode 100644 index 0000000000000..a80a585d40542 --- /dev/null +++ b/docs/generated/packages/playwright/documents/overview.md @@ -0,0 +1,209 @@ +Playwright is a modern web test runner. With included features such as: + +- Cross browser support, including mobile browsers +- Multi tab, origin, and user support +- Automatic waiting +- Test generation +- Screenshots and videos + +## Setting Up Playwright + +If the `@nx/playwright` package is not installed, install the version that matches your `nx` package version. + +{% tabs %} +{% tab label="npm" %} + +```shell +npm install --save-dev @nx/playwright +``` + +{% /tab %} +{% tab label="yarn" %} + +```shell +yarn add --dev @nx/playwright +``` + +{% /tab %} +{% tab label="pnpm" %} + +```shell +pnpm i -D @nx/playwright +``` + +{% /tab %} +{% /tabs %} + +## E2E Testing + +By default, when creating a new frontend application, Nx will prompt for which e2e test runner to use. Select `playwright` or pass in the arg `--e2eTestRunner=playwright` + +```shell +nx g @nx/web:app frontend --e2eTestRunner=playwright +``` + +### Add Playwright e2e to an existing project + +To generate an E2E project for an existing project, run the following generator + +```shell +nx g @nx/playwright:configuration --project=your-app-name --project=your-app-name +``` + +Optionally, you can use the `--webServerCommand` and `--webServerAddress` option, to auto setup the [web server option](https://playwright.dev/docs/test-webserver) in the playwright config + +```shell +nx g @nx/playwright:configuration --project=your-app-name --webServerCommand="npx serve your-project-name" --webServerAddress="http://localhost:4200" +``` + +### Testing Applications + +Run `nx e2e ` to execute e2e tests with Playwright + +{% callout type="note" title="Selecting Specific Specs" %} + +You can use the `--grep/-g` flag to glob for test files. +You can use the `--grepInvert/-gv` flag to glob for files to _not_ run. + +```bash +# run the tests in the feat-a/ directory +nx e2e frontend-e2e --grep="**feat-a/**" + +# run everything except feat-a/ directory +nx e2e frontend-e2e --grepInvert=**feat-a/** +``` + +{% /callout %} + +By default, Playwright will run in headless mode. You will have the result of all the tests and errors (if any) in your +terminal. Test output such as reports, screenshots and videos, will be accessible in `dist/.playwright/apps//`. This can be configured with the `outputDir` configuration options. + +{% callout type="note" title="Output Caching" %} +If changing the output directory or report output, make sure to update the [target outputs](/concepts/how-caching-works#what-is-cached) so the artifacts are correctly cached +{% /callout %} + +### Watching for Changes + +With, `nx e2e frontend-e2e --ui` Playwright will start in headed mode where you can see your application being tested. + +From, there you can toggle on the watch icon which will rerun the tests when the spec file updates. + +```shell +nx e2e --ui +``` + +You can also use `--headed` flag to run Playwright where the browser can be seen without using the [Playwright UI](https://playwright.dev/docs/test-ui-mode) + +### Specifying a Base Url + +The `baseURL` property within the Playwright configuration can control where the tests visit by default. + +```ts +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + // Rest of your config... + + // Run your local dev server before starting the tests + webServer: { + command: 'npx serve ', + url: 'http://localhost:4200', + reuseExistingServer: !process.env.CI, + }, + use: { + baseURL: 'http://localhost:4200', // url playwright visits with `await page.goto('/')`; + }, +}); +``` + +In order to set different `baseURL` values for different environments you can pass them via the [environment variables and nx configurations](/recipes/tips-n-tricks/define-environment-variables) or optionally via setting them per the environment they are needed in such as `CI` + +```ts +import { defineConfig } from '@playwright/test'; + +const baseUrl = + process.env.BASE_URL ?? process.env.CI + ? 'https://some-staging-url.example.com' + : 'http://localhost:4200'; + +export default defineConfig({ + // Rest of your config... + + // Run your local dev server before starting the tests + webServer: { + command: 'npx serve ', + url: baseUrl, + reuseExistingServer: !process.env.CI, + }, + use: { + baseURL: baseUrl, // url playwright visits with `await page.goto('/')`; + }, +}); +``` + +By default Nx, provides a `nxE2EPreset` with predefined configuration for Playwright. + +```ts +import { defineConfig } from '@playwright/test'; +import { nxE2EPreset } from '@nx/playwright/preset'; +import { workspaceRoot } from '@nx/devkit'; + +// For CI, you may want to set BASE_URL to the deployed application. +const baseURL = process.env['BASE_URL'] || 'http://localhost:4200'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + ...nxE2EPreset(__filename, { testDir: './e2e' }), + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + baseURL, + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npx nx serve ', + url: baseURL, + reuseExistingServer: !process.env.CI, + cwd: workspaceRoot, + }, +}); +``` + +This preset sets up the `outputDir` and [HTML reporter](https://playwright.dev/docs/test-reporters#html-reporter) to output in `dist/.playwright/` and sets up chromium, firefox, webkit browsers to be used a browser targets. If you want to use mobile and/or branded browsers you can pass those options into the preset function + +```ts +export default defineConfig({ + ...nxE2EPreset(__filename, { + testDir: './e2e', + includeMobileBrowsers: true, // includes mobile Chrome and Safari + includeBrandedBrowsers: true, // includes Google Chrome and Microsoft Edge + }), + // other settings +}); +``` + +If you want to override any settings within the `nxE2EPreset`, You can define them after the preset like so + +```ts +const config = nxE2EPreset(__filename, { + testDir: './e2e', + includeMobileBrowsers: true, // includes mobile Chrome and Safari + includeBrandedBrowsers: true, // includes Google Chrome and Microsoft Edge +}); +export default defineConfig({ + ...config + retries: 3, + reporters: [...config.reporters, /* other reporter settings */], +}); +``` + +See the [Playwright configuration docs](https://playwright.dev/docs/test-configuration) for more options for Playwright. diff --git a/docs/generated/packages/playwright/executors/playwright.json b/docs/generated/packages/playwright/executors/playwright.json new file mode 100644 index 0000000000000..3d629fe8d9d7d --- /dev/null +++ b/docs/generated/packages/playwright/executors/playwright.json @@ -0,0 +1,163 @@ +{ + "name": "playwright", + "implementation": "/packages/playwright/src/executors/playwright/playwright.ts", + "schema": { + "$schema": "http://json-schema.org/schema", + "version": 2, + "title": "Playwright executor", + "description": "Run Playwright tests.", + "type": "object", + "properties": { + "browser": { + "type": "string", + "description": "Browser to use for tests, one of 'all', 'chromium', 'firefox' or 'webkit'. If a playwright config is provided/discovered then the browserName value is expected from the configured 'projects'", + "x-priority": "important" + }, + "config": { + "type": "string", + "description": "Configuration file, or a test directory with optional", + "x-completion-type": "file", + "x-completion-glob": "playwright?(*)@(.js|.cjs|.mjs|.ts|.cts|.mtx)", + "x-priority": "important" + }, + "debug": { + "type": "boolean", + "description": "Run tests with Playwright Inspector. Shortcut for 'PWDEBUG=1' environment variable and '--timeout=0',--max-failures=1 --headed --workers=1' options" + }, + "forbidOnly": { + "type": "boolean", + "description": "Fail if test.only is called" + }, + "fullyParallel": { + "type": "boolean", + "description": "Run all tests in parallel" + }, + "grep": { + "alias": "g", + "type": "string", + "description": "Only run tests matching this regular expression" + }, + "globalTimeout": { + "type": "number", + "description": "Maximum time this test suite can run in milliseconds" + }, + "grepInvert": { + "alias": "gv", + "type": "string", + "description": "Only run tests that do not match this regular expression" + }, + "headed": { + "type": "boolean", + "description": "Run tests in headed browsers", + "x-priority": "important" + }, + "ignoreSnapshots": { + "type": "boolean", + "description": "Ignore screenshot and snapshot expectations" + }, + "workers": { + "alias": "j", + "type": "string", + "description": "Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker" + }, + "list": { + "type": "boolean", + "description": "Collect all the tests and report them, but do not run" + }, + "maxFailures": { + "alias": "x", + "oneOf": [{ "type": "number" }, { "type": "boolean" }], + "description": "Stop after the first N failures" + }, + "noDeps": { + "type": "boolean", + "description": "Do not run project dependencies" + }, + "output": { + "type": "string", + "description": "Folder for output artifacts" + }, + "passWithNoTests": { + "type": "boolean", + "description": "Makes test run succeed even if no tests were found", + "default": true + }, + "project": { + "description": "Only run tests from the specified list of projects", + "type": "array", + "items": { "type": "string" } + }, + "quiet": { + "alias": "q", + "type": "boolean", + "description": "Suppress stdio" + }, + "repeatEach": { + "type": "number", + "description": "Run each test N times" + }, + "reporter": { + "type": "string", + "enum": [ + "list", + "line", + "dot", + "json", + "junit", + "null", + "github", + "html", + "blob" + ], + "description": "Reporter to use, comma-separated, can be 'list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html', 'blob'. To configure reporter options, use the playwright configuration." + }, + "retries": { + "type": "number", + "description": "Maximum retry count for flaky tests, zero for no retries" + }, + "shard": { + "type": "string", + "description": "Shard tests and execute only the selected shard, specify in the form 'current/all', 1-based, for example '3/5'" + }, + "timeout": { + "type": "number", + "description": "Specify test timeout threshold in milliseconds, zero for unlimited" + }, + "trace": { + "type": "string", + "enum": [ + "on", + "off", + "on-first-retry", + "on-all-retries", + "retain-on-failure" + ], + "description": "Force tracing mode, can be 'on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure'" + }, + "updateSnapshots": { + "alias": "u", + "type": "boolean", + "description": "Update snapshots with actual results. Snapshots will be created if missing." + }, + "ui": { + "type": "boolean", + "description": "Run tests in interactive UI mode" + }, + "uiHost": { + "type": "string", + "description": "Host to serve UI on; specifying this option opens UI in a browser tab" + }, + "uiPort": { + "type": "string", + "description": "Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab" + } + }, + "required": [], + "presets": [] + }, + "description": "Run Playwright tests.", + "aliases": [], + "hidden": false, + "path": "/packages/playwright/src/executors/playwright/schema.json", + "type": "executor" +} diff --git a/docs/generated/packages/playwright/generators/configuration.json b/docs/generated/packages/playwright/generators/configuration.json new file mode 100644 index 0000000000000..432fa5c2a578c --- /dev/null +++ b/docs/generated/packages/playwright/generators/configuration.json @@ -0,0 +1,70 @@ +{ + "name": "configuration", + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxPlaywrightConfiguration", + "description": "Add a Playwright configuration.", + "title": "Add a Playwright configuration", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The project to add a Playwright configuration to", + "$default": { "$source": "projectName" }, + "x-priority": "important", + "x-prompt": "What is the name of the project to set up Playwright for?" + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed relative from the project root", + "x-priority": "important", + "default": "playwright" + }, + "js": { + "type": "boolean", + "description": "Generate JavaScript files rather than TypeScript files.", + "default": false + }, + "webServerCommand": { + "type": "string", + "description": "The command to start the web server." + }, + "webServerAddress": { + "type": "string", + "description": "The address of the web server." + }, + "linter": { + "description": "The tool to use for running lint checks.", + "type": "string", + "enum": ["eslint", "none"], + "default": "eslint" + }, + "setParserOptionsProject": { + "type": "boolean", + "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.", + "default": false + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + } + }, + "required": ["project"], + "presets": [] + }, + "description": "Add Nx Playwright configuration to your project", + "implementation": "/packages/playwright/src/generators/configuration/configuration.ts", + "aliases": [], + "hidden": false, + "path": "/packages/playwright/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/playwright/generators/init.json b/docs/generated/packages/playwright/generators/init.json new file mode 100644 index 0000000000000..d658115c08499 --- /dev/null +++ b/docs/generated/packages/playwright/generators/init.json @@ -0,0 +1,33 @@ +{ + "name": "init", + "factory": "./src/generators/init/init", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxPlaywrightInit", + "title": "Playwright Init Generator", + "description": "Initializes a Playwright project in the current workspace.", + "type": "object", + "properties": { + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + } + }, + "required": [], + "presets": [] + }, + "description": "Initializes a Playwright project in the current workspace", + "implementation": "/packages/playwright/src/generators/init/init.ts", + "aliases": [], + "hidden": false, + "path": "/packages/playwright/src/generators/init/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/plugin/documents/overview.md b/docs/generated/packages/plugin/documents/overview.md index cb5ca805971fc..459807ba2e2ef 100644 --- a/docs/generated/packages/plugin/documents/overview.md +++ b/docs/generated/packages/plugin/documents/overview.md @@ -1,5 +1,5 @@ -Nx plugins are npm packages that contain [generators](/plugin-features/use-code-generators) and [executors](/plugin-features/use-task-executors) to extend a Nx workspace. +Nx plugins are npm packages that contain [generators](/core-features/plugin-features/use-code-generators) and [executors](/core-features/plugin-features/use-task-executors) to extend a Nx workspace. This package contains tooling to help plugin authors create and maintain plugins. -For more information, see the [plugins](/plugins/intro/getting-started) section of docs. +For more information, see the [plugins](/extending-nx/intro/getting-started) section of docs. diff --git a/docs/generated/packages/plugin/generators/create-package.json b/docs/generated/packages/plugin/generators/create-package.json index 31d0171dbde33..81a8d5f1d63b7 100644 --- a/docs/generated/packages/plugin/generators/create-package.json +++ b/docs/generated/packages/plugin/generators/create-package.json @@ -7,6 +7,7 @@ "$id": "NxPluginCreatePackage", "title": "Create a framework package", "description": "Create a framework package that uses Nx CLI.", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Basic executable\" %}\n\nCreate an executable that initializes an Nx workspace with {my-plugin}'s preset:\n\n```bash\nnx g @nx/plugin:create-package create-my-plugin --project my-plugin\n```\n\n{% /tab %}\n{% /tabs %}\n", "type": "object", "properties": { "name": { diff --git a/docs/generated/packages/plugin/generators/e2e-project.json b/docs/generated/packages/plugin/generators/e2e-project.json index 67f305138cc11..3f6aff6b7f07c 100644 --- a/docs/generated/packages/plugin/generators/e2e-project.json +++ b/docs/generated/packages/plugin/generators/e2e-project.json @@ -7,6 +7,7 @@ "$id": "NxPluginE2E", "title": "Create an E2E app for a Nx Plugin", "description": "Create an E2E app for a Nx Plugin.", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"E2E Project\" %}\n\nScaffolds an E2E project for the plugin `my-plugin`.\n\n```bash\nnx g @nx/plugin:e2e-project --pluginName my-plugin --npmPackageName my-plugin --pluginOutputPath dist/my-plugin\n```\n\n{% /tab %}\n{% /tabs %}\n", "type": "object", "properties": { "pluginName": { @@ -29,12 +30,6 @@ "x-priority": "important" }, "jestConfig": { "type": "string", "description": "Jest config file." }, - "standaloneConfig": { - "description": "Split the project configuration into `/project.json` rather than including it inside `workspace.json`.", - "type": "boolean", - "default": true, - "x-deprecated": "Nx only supports standaloneConfig" - }, "linter": { "description": "The tool to use for running lint checks.", "type": "string", diff --git a/docs/generated/packages/plugin/generators/executor.json b/docs/generated/packages/plugin/generators/executor.json index 2c3d9d58361f1..c051d667f6d52 100644 --- a/docs/generated/packages/plugin/generators/executor.json +++ b/docs/generated/packages/plugin/generators/executor.json @@ -7,6 +7,7 @@ "$id": "NxPluginExecutor", "title": "Create an Executor for an Nx Plugin", "description": "Create an Executor for an Nx Plugin.", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Basic executor\" %}\n\nCreate a new executor called `build` inside the plugin `my-plugin`:\n\n```bash\nnx g @nx/plugin:executor build --project my-plugin\n```\n\n{% /tab %}\n{% tab label=\"With custom hashing\" %}\n\nCreate a new executor called `build` inside the plugin `my-plugin`, that uses a custom hashing function:\n\n```bash\nnx g @nx/plugin:executor build --project my-plugin --includeHasher\n```\n\n{% /tab %}\n{% /tabs %}\n", "type": "object", "examples": [ { diff --git a/docs/generated/packages/plugin/generators/migration.json b/docs/generated/packages/plugin/generators/migration.json index 86b39acba2130..10ba13c23bf8e 100644 --- a/docs/generated/packages/plugin/generators/migration.json +++ b/docs/generated/packages/plugin/generators/migration.json @@ -11,7 +11,7 @@ "examples": [ { "command": "nx g migration my-migration --project=my-plugin --version=1.0.0", - "description": "Generate `libs/my-plugin/src/migrations/my-migration`" + "description": "Adds a new migration to the project `my-plugin`, which will be triggered when migrating to version 1.0.0 or above from a previous version." } ], "properties": { diff --git a/docs/generated/packages/plugin/generators/plugin-lint-checks.json b/docs/generated/packages/plugin/generators/plugin-lint-checks.json index 3139aae60e97d..bdf4a50fe7c0b 100644 --- a/docs/generated/packages/plugin/generators/plugin-lint-checks.json +++ b/docs/generated/packages/plugin/generators/plugin-lint-checks.json @@ -8,6 +8,12 @@ "title": "", "type": "object", "description": "Adds linting configuration to validate common json files for nx plugins.", + "examples": [ + { + "command": "nx g @nx/plugin:lint-checks", + "description": "Sets up linting configuration to validate common json files for an nx plugin project." + } + ], "properties": { "projectName": { "type": "string", diff --git a/docs/generated/packages/plugin/generators/plugin.json b/docs/generated/packages/plugin/generators/plugin.json index d0fa0cbfbbae7..08671955a574c 100644 --- a/docs/generated/packages/plugin/generators/plugin.json +++ b/docs/generated/packages/plugin/generators/plugin.json @@ -11,7 +11,7 @@ "examples": [ { "command": "nx g plugin my-plugin --directory=plugins --importPath=@myorg/my-plugin", - "description": "Generate `libs/plugins/my-plugin`" + "description": "Generates an Nx plugin project called `plugins-my-plugin` at `libs/plugins/my-plugin`. The project will have an npm package name and import path of `@myorg/my-plugin`." } ], "properties": { diff --git a/docs/generated/packages/plugin/generators/preset.json b/docs/generated/packages/plugin/generators/preset.json index ba1a0769f05d0..4a0ba2b843cba 100644 --- a/docs/generated/packages/plugin/generators/preset.json +++ b/docs/generated/packages/plugin/generators/preset.json @@ -7,6 +7,16 @@ "$id": "NxPluginPreset", "title": "Generator ran by create-nx-plugin", "description": "Initializes a workspace with an nx-plugin inside of it. Use as: `create-nx-plugin` or `create-nx-workspace --preset @nx/nx-plugin`.", + "examples": [ + { + "command": "npx create-nx-plugin", + "description": "Creates a new Nx workspace containing an Nx plugin." + }, + { + "command": "npx create-nx-workspace --preset @nx/plugin", + "description": "Creates a new Nx workspace containing an Nx plugin." + } + ], "type": "object", "properties": { "pluginName": { diff --git a/docs/generated/packages/react-native/executors/build-android.json b/docs/generated/packages/react-native/executors/build-android.json index cdac5b307debc..565bd793d24a0 100644 --- a/docs/generated/packages/react-native/executors/build-android.json +++ b/docs/generated/packages/react-native/executors/build-android.json @@ -45,7 +45,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." }, "port": { "type": "number", @@ -53,8 +54,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { "type": "string" }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -71,8 +74,12 @@ "default": false }, "extraParams": { - "type": "string", - "description": "Custom params passed to gradle build command" + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], + "description": "Custom params passed to gradle build command", + "examples": ["-x lint -x test"] }, "interactive": { "type": "boolean", @@ -81,7 +88,8 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", - "default": true + "default": true, + "x-deprecated": "Add sync-deps to dependsOn instead" }, "resetCache": { "type": "boolean", diff --git a/docs/generated/packages/react-native/executors/build-ios.json b/docs/generated/packages/react-native/executors/build-ios.json index 9f1d67083d601..861bd13c03539 100644 --- a/docs/generated/packages/react-native/executors/build-ios.json +++ b/docs/generated/packages/react-native/executors/build-ios.json @@ -11,11 +11,7 @@ "presets": [ { "name": "Build iOS for a simulator", "keys": ["simulator"] }, { "name": "Build iOS for a device", "keys": ["device"] }, - { "name": "Build iOS for a device with udid", "keys": ["udid"] }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] - } + { "name": "Build iOS for a device with udid", "keys": ["udid"] } ], "properties": { "simulator": { @@ -72,17 +68,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", + "x-deprecated": "Add pod-install to dependsOn in project.json for this target instead", "default": true }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true }, "resetCache": { @@ -93,7 +94,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." } }, "required": [], diff --git a/docs/generated/packages/react-native/executors/pod-install.json b/docs/generated/packages/react-native/executors/pod-install.json index da7c4b7f32ed1..2e4f9beae6847 100644 --- a/docs/generated/packages/react-native/executors/pod-install.json +++ b/docs/generated/packages/react-native/executors/pod-install.json @@ -12,9 +12,19 @@ "type": "object", "properties": { "buildFolder": { - "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory", + "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory.", "type": "string", "default": "./build" + }, + "repoUpdate": { + "description": "Force running `pod repo update` before install.", + "type": "boolean", + "default": false + }, + "deployment": { + "description": "Disallow any changes to the Podfile or the Podfile.lock during installation.", + "type": "boolean", + "default": false } }, "required": ["buildFolder"], diff --git a/docs/generated/packages/react-native/executors/run-android.json b/docs/generated/packages/react-native/executors/run-android.json index 1f64e92ced64d..cf0a67aa56360 100644 --- a/docs/generated/packages/react-native/executors/run-android.json +++ b/docs/generated/packages/react-native/executors/run-android.json @@ -77,8 +77,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { "type": "string" }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -95,7 +97,10 @@ "default": false }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params passed to gradle build command" }, "interactive": { @@ -105,6 +110,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn for this target in project.json instead", "default": true }, "resetCache": { diff --git a/docs/generated/packages/react-native/executors/run-ios.json b/docs/generated/packages/react-native/executors/run-ios.json index 58f619d5169ac..387f44a2b52c1 100644 --- a/docs/generated/packages/react-native/executors/run-ios.json +++ b/docs/generated/packages/react-native/executors/run-ios.json @@ -13,11 +13,7 @@ "presets": [ { "name": "Run iOS on a simulator", "keys": ["simulator"] }, { "name": "Run iOS on a device", "keys": ["device"] }, - { "name": "Run iOS on a device with udid", "keys": ["udid"] }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] - } + { "name": "Run iOS on a device with udid", "keys": ["udid"] } ], "properties": { "xcodeConfiguration": { @@ -81,17 +77,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", - "default": true + "default": true, + "x-deprecated": "Add `pod-install` to dependsOn for this target in project.json instead." }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add `sync-deps` to dependsOn for this target in project.json instead.", "default": true }, "resetCache": { diff --git a/docs/generated/packages/react-native/generators/storybook-configuration.json b/docs/generated/packages/react-native/generators/storybook-configuration.json index 8accbc33edd95..9293ae7b46e3e 100644 --- a/docs/generated/packages/react-native/generators/storybook-configuration.json +++ b/docs/generated/packages/react-native/generators/storybook-configuration.json @@ -32,7 +32,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", diff --git a/docs/generated/packages/react/documents/overview.md b/docs/generated/packages/react/documents/overview.md index ef171ef6a4fcc..1953591a95d38 100644 --- a/docs/generated/packages/react/documents/overview.md +++ b/docs/generated/packages/react/documents/overview.md @@ -43,7 +43,7 @@ nx g @nx/react:lib my-new-lib \ --importPath=@myorg/my-new-lib ``` -Read more about [building and publishing libraries here](/more-concepts/buildable-and-publishable-libraries). +Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). ### Creating Components diff --git a/docs/generated/packages/react/executors/module-federation-dev-server.json b/docs/generated/packages/react/executors/module-federation-dev-server.json index b962cf3a45323..7a346ba1dd993 100644 --- a/docs/generated/packages/react/executors/module-federation-dev-server.json +++ b/docs/generated/packages/react/executors/module-federation-dev-server.json @@ -18,7 +18,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository.", + "description": "List of remote applications to not automatically serve, either statically or in development mode.", "x-priority": "important" }, "buildTarget": { diff --git a/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json b/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json index bdca395348390..fb5b3ec88d0c4 100644 --- a/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json +++ b/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json @@ -34,7 +34,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository.", + "description": "List of remote applications to not automatically serve, either statically or in development mode.", "x-priority": "important" }, "host": { diff --git a/docs/generated/packages/react/generators/component-story.json b/docs/generated/packages/react/generators/component-story.json index 1a959e4cac315..5122138cb60da 100644 --- a/docs/generated/packages/react/generators/component-story.json +++ b/docs/generated/packages/react/generators/component-story.json @@ -30,6 +30,12 @@ "type": "boolean", "default": false, "x-priority": "internal" + }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "default": true, + "x-priority": "important" } }, "required": ["project", "componentPath"], diff --git a/docs/generated/packages/react/generators/stories.json b/docs/generated/packages/react/generators/stories.json index 76138b57a15aa..3fe7c00699952 100644 --- a/docs/generated/packages/react/generators/stories.json +++ b/docs/generated/packages/react/generators/stories.json @@ -19,14 +19,19 @@ }, "generateCypressSpecs": { "type": "boolean", - "description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.", - "x-prompt": "Do you want to generate Cypress specs as well?", - "x-priority": "important" + "description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator." }, "cypressProject": { "type": "string", "description": "The Cypress project to generate the stories under. This is inferred from `project` by default." }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "default": true + }, "js": { "type": "boolean", "description": "Generate JavaScript files rather than TypeScript files.", @@ -52,7 +57,7 @@ } }, "required": ["project"], - "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/react:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:stories --name=ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:stories --name=ui --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", + "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/react:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:stories --name=ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:stories --name=ui --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", "presets": [] }, "description": "Create stories/specs for all components declared in an app or library.", diff --git a/docs/generated/packages/react/generators/storybook-configuration.json b/docs/generated/packages/react/generators/storybook-configuration.json index 02e15b30e1d18..bae3614598e5c 100644 --- a/docs/generated/packages/react/generators/storybook-configuration.json +++ b/docs/generated/packages/react/generators/storybook-configuration.json @@ -18,12 +18,17 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", - "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "description": "Run the cypress-configure generator." }, "generateStories": { "type": "boolean", @@ -34,10 +39,7 @@ }, "generateCypressSpecs": { "type": "boolean", - "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.", - "x-prompt": "Automatically generate test files in the Cypress E2E app generated by the cypress-configure generator?", - "default": true, - "x-priority": "important" + "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator." }, "configureStaticServe": { "type": "boolean", @@ -58,7 +60,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", @@ -77,14 +79,10 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "required": ["name"], - "examplesFile": "This generator will set up Storybook for your **React** project. You can also use this generator to generate Storybook configuration for your **Next.js** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/react:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#generate-storybook-configuration-for-an-react-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance. You can read more about this in the [Storybook for React - Cypress section](/packages/storybook/documents/overview-react#cypress-tests-for-stories).\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner).\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/react:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project.\n\n### Generate Storybook configuration using TypeScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --tsConfiguration=true\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", + "examplesFile": "This generator will set up Storybook for your **React** project. You can also use this generator to generate Storybook configuration for your **Next.js** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/react:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#generate-storybook-configuration-for-an-react-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/react:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", "presets": [] }, "description": "Set up storybook for a React app or library.", diff --git a/docs/generated/packages/rollup/executors/rollup.json b/docs/generated/packages/rollup/executors/rollup.json index 1db6a873ceb85..9c19c745f5bcb 100644 --- a/docs/generated/packages/rollup/executors/rollup.json +++ b/docs/generated/packages/rollup/executors/rollup.json @@ -8,19 +8,6 @@ "description": "Packages a library for different web usages (ESM, CommonJS).", "cli": "nx", "type": "object", - "presets": [ - { - "name": "Including Dependencies in package.json", - "keys": [ - "main", - "outputPath", - "project", - "tsConfig", - "buildableProjectDepsInPackageJsonType", - "updateBuildableProjectDepsInPackageJson" - ] - } - ], "properties": { "project": { "type": "string", @@ -84,13 +71,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Update buildable project dependencies in `package.json`.", - "default": true + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "rollupConfig": { "oneOf": [ @@ -162,8 +151,16 @@ }, "generateExportsField": { "type": "boolean", - "description": "Generate package.json with 'exports' field. This field defines entry points in the package and is used by Node and the TypeScript compiler.", - "default": false + "alias": "exports", + "description": "Update the output package.json file's 'exports' field. This field is used by Node and bundles.", + "default": false, + "x-priority": "important" + }, + "additionalEntryPoints": { + "type": "array", + "description": "Additional entry-points to add to exports field in the package.json file.", + "items": { "type": "string" }, + "x-priority": "important" }, "skipTypeCheck": { "type": "boolean", @@ -203,7 +200,8 @@ ] } }, - "examplesFile": "{% tabs %}\n{% tab label=\"Including Dependencies\" %}\nTo include dependencies in the output `package.json`, the dependencies must be installed as a **dependencies** in the root `package.json`\n\n```json {% fileName=\"package.json\" %}\n{\n \"dependencies\": {\n \"some-dependency\": \"^1.0.0\"\n }\n}\n```\n\nTo have dependencies in the be listed in the final `package.json` of your project, set the `updateBuildableProjectDepsInPackageJson` option to `true`. After than dependencies will be added to the `peerDependencies` field of the output `package.json`. You can use `buildableProjectDepsInPackageJsonType` option to change which field the dependencies are output to.\n\n```json {% fileName=\"project.json\" %}\n{\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"buildableProjectDepsInPackageJsonType\": \"dependencies\",\n \"updateBuildableProjectDepsInPackageJson\": true\n }\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Using `babelUpwardRootMode`\" %}\n\nCopying from the [Babel documentation](https://babeljs.io/docs/config-files#root-babelconfigjson-file):\n\n> [...] if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the \"rootMode\" option with \"upward\", which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the \"root\" value.\n\nSetting `babelUpwardRootMode` to `true` in your `project.json` will set `rootMode` option to `upward` in the Babel config. You may want the `upward` mode in a monorepo when projects must apply their individual `.babelrc` file. We recommend that you don't set it at all, so it will use the default to `false` as the `upward` mode brings additional complexity to the build process.\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"babelUpwardRootMode\": true,\n //...\n },\n //...\n },\n //...\n },\n //...\n}\n```\n\nWhen `babelUpwardRootMode` is `true`, Babel will look for a root `babel.config.json` at the root of the workspace, which should look something like this to include all packages:\n\n```json\n{ \"babelrcRoots\": [\"*\"] }\n```\n\nThen for each package, you must have a `.babelrc` file that will be applied to that package. For example:\n\n```json\n{\n \"presets\": [\"@babel/preset-env\", \"@babel/preset-typescript\"]\n}\n```\n\nAll packages will use its own `.babelrc` file, thus you must ensure the right presets and plugins are set in each config file. This behavior can lead to build discrepancies between packages, so we recommend that you don't set `babelUpwardRootMode` at all.\n\n```treeview\n├── packages\n│ ├── a\n│ │ └── .babelrc\n│ └── b\n│ └── .babelrc\n└── babel.config.json\n```\n\nIn workspace above, if `a` imports `b`, it will apply the config `packages/b/.babelrc` and not apply its own `packages/a/.babelrc` to `b`. Anything in `babel.config.json` will apply to all packages.\n\n{% /tab %}\n\n{% /tabs %}\n" + "examplesFile": "{% tabs %}\n{% tab label=\"Including Dependencies\" %}\nTo include dependencies in the output `package.json`, the dependencies must be installed as a **dependencies** in the root `package.json`\n\n```json {% fileName=\"package.json\" %}\n{\n \"dependencies\": {\n \"some-dependency\": \"^1.0.0\"\n }\n}\n```\n\nTo have dependencies in the be listed in the final `package.json` of your project, set the `updateBuildableProjectDepsInPackageJson` option to `true`. After than dependencies will be added to the `peerDependencies` field of the output `package.json`. You can use `buildableProjectDepsInPackageJsonType` option to change which field the dependencies are output to.\n\n```json {% fileName=\"project.json\" %}\n{\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"buildableProjectDepsInPackageJsonType\": \"dependencies\",\n \"updateBuildableProjectDepsInPackageJson\": true\n }\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Using `babelUpwardRootMode`\" %}\n\nCopying from the [Babel documentation](https://babeljs.io/docs/config-files#root-babelconfigjson-file):\n\n> [...] if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the \"rootMode\" option with \"upward\", which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the \"root\" value.\n\nSetting `babelUpwardRootMode` to `true` in your `project.json` will set `rootMode` option to `upward` in the Babel config. You may want the `upward` mode in a monorepo when projects must apply their individual `.babelrc` file. We recommend that you don't set it at all, so it will use the default to `false` as the `upward` mode brings additional complexity to the build process.\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"babelUpwardRootMode\": true,\n //...\n },\n //...\n },\n //...\n },\n //...\n}\n```\n\nWhen `babelUpwardRootMode` is `true`, Babel will look for a root `babel.config.json` at the root of the workspace, which should look something like this to include all packages:\n\n```json\n{ \"babelrcRoots\": [\"*\"] }\n```\n\nThen for each package, you must have a `.babelrc` file that will be applied to that package. For example:\n\n```json\n{\n \"presets\": [\"@babel/preset-env\", \"@babel/preset-typescript\"]\n}\n```\n\nAll packages will use its own `.babelrc` file, thus you must ensure the right presets and plugins are set in each config file. This behavior can lead to build discrepancies between packages, so we recommend that you don't set `babelUpwardRootMode` at all.\n\n```treeview\n├── packages\n│ ├── a\n│ │ └── .babelrc\n│ └── b\n│ └── .babelrc\n└── babel.config.json\n```\n\nIn workspace above, if `a` imports `b`, it will apply the config `packages/b/.babelrc` and not apply its own `packages/a/.babelrc` to `b`. Anything in `babel.config.json` will apply to all packages.\n\n{% /tab %}\n\n{% /tabs %}\n", + "presets": [] }, "description": "Bundle a package using Rollup.", "aliases": [], diff --git a/docs/generated/packages/rollup/generators/configuration.json b/docs/generated/packages/rollup/generators/configuration.json new file mode 100644 index 0000000000000..e17a829963cb2 --- /dev/null +++ b/docs/generated/packages/rollup/generators/configuration.json @@ -0,0 +1,83 @@ +{ + "name": "configuration", + "aliases": ["rollup-project"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxRollupProject", + "cli": "nx", + "title": "Add Rollup Configuration to a project", + "description": "Add Rollup Configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "argv", "index": 0 }, + "x-dropdown": "project", + "x-prompt": "What is the name of the project to set up a rollup for?", + "x-priority": "important" + }, + "compiler": { + "type": "string", + "enum": ["babel", "swc", "tsc"], + "description": "The compiler to use to build source.", + "default": "babel" + }, + "main": { + "type": "string", + "description": "Path relative to the workspace root for the main entry file. Defaults to '/src/main.ts'.", + "alias": "entryFile", + "x-priority": "important" + }, + "tsConfig": { + "type": "string", + "description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to '/tsconfig.app.json'.", + "x-priority": "important" + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "skipValidation": { + "type": "boolean", + "default": false, + "description": "Do not perform any validation on existing project.", + "x-priority": "internal" + }, + "importPath": { + "type": "string", + "description": "The library name used to import it, like `@myorg/my-awesome-lib`." + }, + "external": { + "type": "array", + "description": "A list of external modules that will not be bundled (`react`, `react-dom`, etc.).", + "items": { "type": "string" } + }, + "rollupConfig": { + "type": "string", + "description": "Path relative to workspace root to a custom rollup file that takes a config object and returns an updated config." + }, + "buildTarget": { + "description": "The build target to add.", + "type": "string", + "default": "build" + } + }, + "required": [], + "presets": [] + }, + "description": "Add rollup configuration to a project.", + "hidden": true, + "implementation": "/packages/rollup/src/generators/configuration/configuration.ts", + "path": "/packages/rollup/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/storybook/documents/best-practices.md b/docs/generated/packages/storybook/documents/best-practices.md index 07e5ffa035d92..c4c3ba91fdbb5 100644 --- a/docs/generated/packages/storybook/documents/best-practices.md +++ b/docs/generated/packages/storybook/documents/best-practices.md @@ -91,7 +91,7 @@ In the following section, we are going to see how to set up Storybook in these c ### 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](/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. Let’s see this in more detail. +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. Let’s see this in more detail. #### Local development and testing @@ -121,7 +121,7 @@ Since each Storybook, in this case, is attached to a project, so is the serving #### Publishing -When you are publishing your Storybook, you can follow the same principles described in the [Applications and Libraries Mental Model](/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/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. 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. @@ -131,7 +131,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](/packages/storybook/documents/storybook-composition-setup). However, in this case, you would still need to build each project’s Storybook individually, and also deploy it individually. So in the cases where you have multiple projects, Storybook Composition would not be very efficient. {% /callout %} -Before moving on to the examples section, it could be useful to read the [Library Types](/more-concepts/library-types) documentation page and the [Grouping libraries](/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/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. ## Examples / Use cases diff --git a/docs/generated/packages/storybook/documents/custom-builder-configs.md b/docs/generated/packages/storybook/documents/custom-builder-configs.md index d9012829bdf7b..34886558ae898 100644 --- a/docs/generated/packages/storybook/documents/custom-builder-configs.md +++ b/docs/generated/packages/storybook/documents/custom-builder-configs.md @@ -47,7 +47,7 @@ async viteFinal(config, { configType }) { In the `viteFinal` case, you would have to import the `mergeConfig` function from `vite`. So, on the top of your root `.storybook/main.js|ts` file, you would have to add: ```ts {% fileName=".storybook/main.js" %} -const { mergeConfig } = require('vite'); +import { mergeConfig } from 'vite'; ``` ## Project-specific configuration @@ -57,7 +57,7 @@ const { mergeConfig } = require('vite'); You can customize the `webpack` configuration for a specific project by adding a `webpackFinal` field in your project-specific `.storybok/main.js|ts` file, like this: ```ts {% fileName="apps/my-react-webpack-app/.storybook/main.js" %} -module.exports = { +export default { ... webpackFinal: async (config, { configType }) => { @@ -71,9 +71,9 @@ module.exports = { If you are using a global, root-level, `webpack` configuration in your project, you can customize or extend that for a specific project like this: ```ts {% fileName="apps/my-react-webpack-app/.storybook/main.js" %} -const rootMain = require('../../../.storybook/main'); +import rootMain from '../../../.storybook/main'; -module.exports = { +export default { ...rootMain, ... webpackFinal: async (config, { configType }) => { @@ -96,10 +96,10 @@ Take note how, in this case, we are first applying the global `webpack` configur You can customize the `vite` configuration for a specific project by adding a `viteFinal` field in your project-specific `.storybok/main.js|ts` file, like this: ```ts {% fileName="apps/my-react-vite-app/.storybook/main.js" %} -const { mergeConfig } = require('vite'); -const viteTsConfigPaths = require('vite-tsconfig-paths').default; +import { mergeConfig } from 'vite'; +import viteTsConfigPaths from 'vite-tsconfig-paths'; -module.exports = { +export default { ... async viteFinal(config, { configType }) { return mergeConfig(config, { @@ -112,10 +112,10 @@ module.exports = { If you are using a global, root-level, `vite` configuration in your workspace, you can customize or extend that for a specific project like this: ```ts {% fileName="apps/my-react-vite-app/.storybook/main.js" %} -const { mergeConfig } = require('vite'); -const rootMain = require('../../../.storybook/main'); +import { mergeConfig } from 'vite'; +import rootMain from '../../../.storybook/main'; -module.exports = { +export default { ... async viteFinal(config, { configType }) { return mergeConfig(config, { @@ -128,9 +128,9 @@ module.exports = { So, a full project-level `.storybook/main.js|ts` file for a Vite.js project would look like this: ```ts {% fileName="apps/my-react-vite-app/.storybook/main.js" %} -const { mergeConfig } = require('vite'); +import { mergeConfig } from 'vite'; -module.exports = { +export default { stories: ['../src/app/**/*.stories.@(mdx|js|jsx|ts|tsx)'], addons: ['@storybook/addon-essentials'], framework: { diff --git a/docs/generated/packages/storybook/documents/migrate-webpack-final-react.md b/docs/generated/packages/storybook/documents/migrate-webpack-final-react.md index de4ebf8e763e1..53600951a1e60 100644 --- a/docs/generated/packages/storybook/documents/migrate-webpack-final-react.md +++ b/docs/generated/packages/storybook/documents/migrate-webpack-final-react.md @@ -14,7 +14,7 @@ Nx 12.7 comes with a dedicated Storybook addon for React which dramatically simp {% youtube src="https://www.youtube.com/embed/oUE74McS_NY" title="New in Nx 12.7: React Storybook Preset" -width="100%" /%} +/%} Here are the main differences to the previous versions of Nx: diff --git a/docs/generated/packages/storybook/documents/storybook-interaction-tests.md b/docs/generated/packages/storybook/documents/storybook-interaction-tests.md new file mode 100644 index 0000000000000..b09cbe9ea2421 --- /dev/null +++ b/docs/generated/packages/storybook/documents/storybook-interaction-tests.md @@ -0,0 +1,138 @@ +--- +title: Setting up Storybook Interaction Tests with Nx +description: This guide explains how you can set up Storybook interaction tests on your Nx workspace. +--- + +# Setting up Storybook Interaction Tests with Nx + +[Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing) allow you to test user interactions within your Storybook stories. It enhances your [Storybook](https://storybook.js.org/) setup, ensuring that not only do your components look right, but they also work correctly when interacted with. + +You can read more about Storybook interaction tests in the following sections of the Storybook documentation: + +- [Storybook interaction tests for React](https://storybook.js.org/docs/react/writing-tests/interaction-testing) +- [Storybook interaction tests for Angular](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) +- [Storybook test runner](https://storybook.js.org/docs/react/writing-tests/test-runner) +- [The `play` function](https://storybook.js.org/docs/react/writing-stories/play-function) + +{% callout type="warning" title="Set up Storybook in your workspace" %} +You first need to set up Storybook for your Nx workspace, if you haven't already. You can read the [Storybook plugin overview guide](/packages/storybook) to get started. +{% /callout %} + +## Setup Storybook Interaction Tests + +During the setup, you'll be prompted about setting up interaction tests. Choose `yes` when asked if you want to set up Storybook interaction tests. + +The `--interactionTests` flag is true by default, so when you're setting up Storybook, you can just press enter to accept the default value, or even pass the flag directly. Make sure to use the framework-specific generators, so that you also get your stories set up correctly: + +{% tabs %} +{% tab label="Angular" %} + +```shell +nx g @nx/angular:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="React" %} + +```shell +nx g @nx/react:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="No framework" %} + +```shell +nx g @nx/storybook:configuration project-name --interactionTests=true +``` + +{% /tab %} +{% /tabs %} + +This command will: + +- [Set up Storybook for your project](/packages/storybook) - including the `@storybook/addon-interactions` addon. +- Add a `play` function to your stories. +- Install the necessary dependencies. +- Generate a `test-storybook` target in your project's `project.json`, which has a command to invoke the Storybook test runner. + +## Writing an Interaction Test + +The Nx generator will create a very simple interaction test for you. You can find it in the `.stories.ts` file for your component. This test will only be asserting if some text exists in your component. +You can modify it to suit your needs. + +Let's take an example of a simple React component for a button: + +```typescript +import React, { useState } from 'react'; + +export function Button() { + const [count, setCount] = useState(0); + + const handleClick = () => { + setCount(count + 1); + }; + + return ( + + ); +} + +export default Button; +``` + +In your `.stories.ts` file for that component, you can use the play function to simulate interactions. For example: + +```typescript +export const ButtonClicked: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const button = canvas.getByRole('button'); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 1 times" + ); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 2 times" + ); + }, +}; +``` + +Here, the play function is simulating a click on the button using the `userEvent.click` method. It is then asserting that the button's text has changed to reflect the number of times it has been clicked. + +You can read more about how to write interaction tests in the [Storybook documentation](https://storybook.js.org/docs/react/writing-tests/interaction-testing). + +## Running Interaction Tests + +To run the interaction tests, you can use the `test-storybook` target that was generated for your project: + +```bash +nx test-storybook project-name +``` + +Make sure you have Storybook running in another tab, so that the test runner can connect to it: + +```bash +nx storybook project-name +``` + +## Interaction Tests vs. Cypress E2E Tests + +As the landscape of testing has evolves, we are also adjusting our approach to testing in Nx, and the Storybook generators. Nx has been consistently suggesting the use of Cypress for e2e tests in conjunction with Storybook. This approach, while effective, had its own challenges. A new, separate e2e project would be generated, and setup specifically to work with Storybook, leading to a bifurcated setup: your component stories in one place, and the e2e tests that validated them in another. + +However, with the introduction of Storybook Interaction Tests, this approach can be simplified. This new feature allows developers to integrate tests directly within the stories they are already creating, making the development and testing process more straightforward. Why maintain two separate projects or setups when you can do everything in one place? + +Choosing to promote Storybook Interaction Tests over the previous Cypress e2e setup was not a decision made lightly. Here's why we believe it's a beneficial shift: + +- **Unified Workflow:** Interaction tests allow developers to keep their focus on one tool. Instead of juggling between Storybook and a separate e2e project, everything is integrated. This means quicker iterations and a simplified dev experience. + +- **Leaner Project Structure:** Avoiding the need to generate a separate e2e project means fewer files, less configuration, and a more straightforward project structure. This can make onboarding new developers or navigating the codebase simpler. + +- **Optimized Performance:** Interaction tests are lightweight and quick to execute compared to traditional e2e tests. They run directly in the context of the component story, ensuring that tests are precise and fast. + +- **Consistency:** Keeping the stories and their associated tests together ensures a tighter bond between what's developed and what's tested. It reduces the chances of tests becoming outdated or misaligned with the component's actual behavior. + +Because of these benefits, it made sense for our Storybook configuration generator to switch from the Cypress e2e + Storybook combination to the integrated approach of Storybook Interaction Tests. By integrating e2e-like tests into the existing Storybook setup, we offer developers a smoother, more efficient, and simpler setup and testing experience. diff --git a/docs/generated/packages/storybook/executors/storybook.json b/docs/generated/packages/storybook/executors/storybook.json index 776ac9b04d293..eb83f4d79524f 100644 --- a/docs/generated/packages/storybook/executors/storybook.json +++ b/docs/generated/packages/storybook/executors/storybook.json @@ -18,11 +18,7 @@ "default": 9009 }, "previewUrl": { "type": "string", "description": "Preview URL." }, - "host": { - "type": "string", - "description": "Host to listen on.", - "default": "localhost" - }, + "host": { "type": "string", "description": "Host to listen on." }, "staticDir": { "type": "array", "description": "Directory where to load static files from, array of strings.", diff --git a/docs/generated/packages/storybook/generators/configuration.json b/docs/generated/packages/storybook/generators/configuration.json index a3223720d7820..c36a985add65f 100644 --- a/docs/generated/packages/storybook/generators/configuration.json +++ b/docs/generated/packages/storybook/generators/configuration.json @@ -18,15 +18,22 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "x-priority": "important" + "x-deprecated": "Use interactionTests instead. This option will be removed in v18." }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Added at root by default." + "description": "A directory where the Cypress project will be placed. Added at root by default.", + "x-deprecated": "Use interactionTests instead. This option will be removed in v18." }, "linter": { "description": "The tool to use for running lint checks.", @@ -56,10 +63,6 @@ "description": "Add a static-storybook to serve the static storybook built files.", "default": false }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." - }, "bundler": { "description": "The Storybook builder to use.", "type": "string", @@ -101,7 +104,7 @@ } }, "required": ["name", "uiFramework"], - "examplesFile": "---\ntitle: Storybook configuration generator examples\ndescription: This page contains examples for the @nx/storybook:configuration generator.\n---\n\nThis is a framework-agnostic generator for setting up Storybook configuration for a project.\n\n```bash\nnx g @nx/storybook:configuration\n```\n\nStarting Nx 16, Nx does not support Storybook v6 any more. So, Nx will configure your project to use Storybook v7. If you are not on Storybook 7 yet, please migrate. You can read more about how to migrate to Storybook 7 in our [Storybook 7 migration generator](/packages/storybook/generators/migrate-7) guide.\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are:\n - `@storybook/angular`\n - `@storybook/html-webpack5`\n - `@storybook/nextjs`\n - `@storybook/preact-webpack5`\n - `@storybook/react-webpack5`\n - `@storybook/react-vite`\n - `@storybook/server-webpack5`\n - `@storybook/svelte-webpack5`\n - `@storybook/svelte-vite`\n - `@storybook/sveltekit`\n - `@storybook/vue-webpack5`\n - `@storybook/vue-vite`\n - `@storybook/vue3-webpack5`\n - `@storybook/vue3-vite`\n - `@storybook/web-components-webpack5`\n - `@storybook/web-components-vite`\n- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance.\n- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner).\n\nYou must provide a `name` and a `uiFramework` for the generator to work.\n\nYou can read more about how this generator works, in the [Storybook package overview page](/packages/storybook#generating-storybook-configuration).\n\nIf you are using Angular, React, React Native or Next.js in your project, it's best to use the framework specific generator:\n\n- [React Storybook Configuration Generator](/packages/react/generators/storybook-configuration) (React and Next.js projects)\n\n- [Angular Storybook Configuration Generator](/packages/angular/generators/storybook-configuration)\n\n- [React Native Storybook Configuration Generator](/packages/react-native/generators/storybook-configuration)\n\n## Examples\n\n### Generate Storybook configuration using TypeScript\n\n```bash\nnx g @nx/storybook:configuration ui --uiFramework=@storybook/web-components-vite --tsConfiguration=true\n```\n\nThis will generate a Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory).\n", + "examplesFile": "---\ntitle: Storybook configuration generator examples\ndescription: This page contains examples for the @nx/storybook:configuration generator.\n---\n\nThis is a framework-agnostic generator for setting up Storybook configuration for a project.\n\n```bash\nnx g @nx/storybook:configuration\n```\n\nStarting Nx 16, Nx does not support Storybook v6 any more. So, Nx will configure your project to use Storybook v7. If you are not on Storybook 7 yet, please migrate. You can read more about how to migrate to Storybook 7 in our [Storybook 7 migration generator](/packages/storybook/generators/migrate-7) guide.\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are:\n - `@storybook/angular`\n - `@storybook/html-webpack5`\n - `@storybook/nextjs`\n - `@storybook/preact-webpack5`\n - `@storybook/react-webpack5`\n - `@storybook/react-vite`\n - `@storybook/server-webpack5`\n - `@storybook/svelte-webpack5`\n - `@storybook/svelte-vite`\n - `@storybook/sveltekit`\n - `@storybook/vue-webpack5`\n - `@storybook/vue-vite`\n - `@storybook/vue3-webpack5`\n - `@storybook/vue3-vite`\n - `@storybook/web-components-webpack5`\n - `@storybook/web-components-vite`\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/angular/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).\n\nYou must provide a `name` and a `uiFramework` for the generator to work.\n\nYou can read more about how this generator works, in the [Storybook package overview page](/packages/storybook#generating-storybook-configuration).\n\nIf you are using Angular, React, React Native or Next.js in your project, it's best to use the framework specific generator:\n\n- [React Storybook Configuration Generator](/packages/react/generators/storybook-configuration) (React and Next.js projects)\n\n- [Angular Storybook Configuration Generator](/packages/angular/generators/storybook-configuration)\n\n- [React Native Storybook Configuration Generator](/packages/react-native/generators/storybook-configuration)\n\n## Examples\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/storybook:configuration ui --uiFramework=@storybook/web-components-vite --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", "presets": [] }, "description": "Add Storybook configuration to a UI library or an application.", diff --git a/docs/generated/packages/vite/executors/dev-server.json b/docs/generated/packages/vite/executors/dev-server.json index 3c8f4707a752c..9c25f72d7e9af 100644 --- a/docs/generated/packages/vite/executors/dev-server.json +++ b/docs/generated/packages/vite/executors/dev-server.json @@ -37,7 +37,10 @@ "description": "Specify which IP addresses the server should listen on.", "oneOf": [{ "type": "boolean" }, { "type": "string" }] }, - "https": { "type": "boolean", "description": "Serve using HTTPS." }, + "https": { + "oneOf": [{ "type": "boolean" }, { "type": "object" }], + "description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https" + }, "hmr": { "description": "Enable hot module replacement. For more options, use the 'hmr' option in the Vite configuration file.", "type": "boolean" diff --git a/docs/generated/packages/vite/executors/preview-server.json b/docs/generated/packages/vite/executors/preview-server.json index e52f409a5af9f..00eb6fcbd30be 100644 --- a/docs/generated/packages/vite/executors/preview-server.json +++ b/docs/generated/packages/vite/executors/preview-server.json @@ -27,7 +27,10 @@ "description": "Specify which IP addresses the server should listen on.", "oneOf": [{ "type": "boolean" }, { "type": "string" }] }, - "https": { "type": "boolean", "description": "Serve using HTTPS." }, + "https": { + "oneOf": [{ "type": "boolean" }, { "type": "object" }], + "description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https" + }, "open": { "description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.", "oneOf": [{ "type": "boolean" }, { "type": "string" }] diff --git a/docs/generated/packages/vite/generators/vitest.json b/docs/generated/packages/vite/generators/vitest.json index a4d5b38584f73..f9b72140e3a37 100644 --- a/docs/generated/packages/vite/generators/vitest.json +++ b/docs/generated/packages/vite/generators/vitest.json @@ -32,8 +32,8 @@ }, "coverageProvider": { "type": "string", - "enum": ["c8", "istanbul"], - "default": "c8", + "enum": ["v8", "c8", "istanbul"], + "default": "v8", "description": "Coverage provider to use." }, "testTarget": { diff --git a/docs/generated/packages/web/generators/application.json b/docs/generated/packages/web/generators/application.json index 74f90cd73df60..dbc224acfd5b6 100644 --- a/docs/generated/packages/web/generators/application.json +++ b/docs/generated/packages/web/generators/application.json @@ -79,7 +79,8 @@ }, "e2eTestRunner": { "type": "string", - "enum": ["cypress", "none"], + "enum": ["cypress", "playwright", "none"], + "x-prompt": "Which E2E test runner would you like to use?", "description": "Test runner to use for end to end (e2e) tests", "default": "cypress" }, diff --git a/docs/generated/packages/web/generators/init.json b/docs/generated/packages/web/generators/init.json index 438efd9633fa1..008ed6a67afd5 100644 --- a/docs/generated/packages/web/generators/init.json +++ b/docs/generated/packages/web/generators/init.json @@ -24,7 +24,8 @@ "e2eTestRunner": { "description": "Adds the specified e2e test runner", "type": "string", - "enum": ["cypress", "none"], + "enum": ["cypress", "playwright", "none"], + "x-prompt": "Which E2E test runner would you like to use?", "default": "cypress" }, "skipFormat": { diff --git a/docs/generated/packages/webpack/documents/webpack-config-setup.md b/docs/generated/packages/webpack/documents/webpack-config-setup.md index 322cd684703d1..cd48bc0403e8e 100644 --- a/docs/generated/packages/webpack/documents/webpack-config-setup.md +++ b/docs/generated/packages/webpack/documents/webpack-config-setup.md @@ -157,7 +157,7 @@ module.exports = composePlugins(withNx(), (config, { options, context }) => { ### Configure webpack for Module Federation -If you use the [Module Federation](/recipes/module-federation/faster-builds) support from `@nx/angular` or `@nx/react` then +If you use the [Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) support from `@nx/angular` or `@nx/react` then you can customize your webpack configuration as follows. ```js {% fileName="apps/my-app/webpack.config.js" %} diff --git a/docs/generated/packages/webpack/documents/webpack-plugins.md b/docs/generated/packages/webpack/documents/webpack-plugins.md index 90897910400a3..7d34a3dda3182 100644 --- a/docs/generated/packages/webpack/documents/webpack-plugins.md +++ b/docs/generated/packages/webpack/documents/webpack-plugins.md @@ -165,7 +165,7 @@ module.exports = composePlugins( The `withModuleFederation` and `withModuleFederationForSSR` plugins add module federation support to the webpack build. These plugins use [`ModuleFederationPlugin`](https://webpack.js.org/concepts/module-federation/) and provide a simpler API through Nx. -For more information, refer to the [Module Federation recipe](/recipes/module-federation/faster-builds). +For more information, refer to the [Module Federation recipe](/concepts/more-concepts/faster-builds-with-module-federation). ### Options diff --git a/docs/generated/packages/webpack/generators/configuration.json b/docs/generated/packages/webpack/generators/configuration.json new file mode 100644 index 0000000000000..508705b601e49 --- /dev/null +++ b/docs/generated/packages/webpack/generators/configuration.json @@ -0,0 +1,85 @@ +{ + "name": "configuration", + "aliases": ["webpack-project"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxWebpackProject", + "cli": "nx", + "title": "Add Webpack Configuration to a project", + "description": "Add Webpack Configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "argv", "index": 0 }, + "x-dropdown": "project", + "x-prompt": "What is the name of the project to set up a webpack for?", + "x-priority": "important" + }, + "compiler": { + "type": "string", + "enum": ["babel", "swc", "tsc"], + "description": "The compiler to use to build source.", + "default": "swc" + }, + "main": { + "type": "string", + "description": "Path relative to the workspace root for the main entry file. Defaults to '/src/main.ts'.", + "x-priority": "important" + }, + "tsConfig": { + "type": "string", + "description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to '/tsconfig.app.json'.", + "x-priority": "important" + }, + "target": { + "type": "string", + "description": "Target platform for the build, same as the Webpack config option.", + "enum": ["node", "web", "webworker"], + "default": "web" + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "skipValidation": { + "type": "boolean", + "default": false, + "description": "Do not perform any validation on existing project.", + "x-priority": "internal" + }, + "devServer": { + "type": "boolean", + "description": "Add a serve target to run a local webpack dev-server", + "default": false + }, + "webpackConfig": { + "type": "string", + "description": "Path relative to workspace root to a custom webpack file that takes a config object and returns an updated config.", + "x-priority": "internal" + }, + "babelConfig": { + "type": "string", + "description": "Optionally specify a path relative to workspace root to the babel configuration file of your project.", + "x-completion-type": "file" + } + }, + "required": [], + "presets": [] + }, + "description": "Add webpack configuration to a project.", + "hidden": true, + "implementation": "/packages/webpack/src/generators/configuration/configuration.ts", + "path": "/packages/webpack/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/workspace/documents/overview.md b/docs/generated/packages/workspace/documents/overview.md index f4eada5dfb589..84518542c6663 100644 --- a/docs/generated/packages/workspace/documents/overview.md +++ b/docs/generated/packages/workspace/documents/overview.md @@ -4,7 +4,7 @@ The workspace plugin contains executors and generators that are useful for any N Codifying your organization's best practices into local generators is a great way to ensure that the best practices are easy to follow and implement. Running `nx g @nx/plugin:plugin feature` will create a local plugin with a generator which is written the same way generators are written for Nx plugins. -> See more about [local generators](/plugins/recipes/local-generators) +> See more about [local generators](/extending-nx/recipes/local-generators) ## Reorganizing Projects diff --git a/docs/generated/packages/workspace/generators/convert-to-monorepo.json b/docs/generated/packages/workspace/generators/convert-to-monorepo.json new file mode 100644 index 0000000000000..6e5b31d954ee6 --- /dev/null +++ b/docs/generated/packages/workspace/generators/convert-to-monorepo.json @@ -0,0 +1,27 @@ +{ + "name": "convert-to-monorepo", + "factory": "./src/generators/convert-to-monorepo/convert-to-monorepo", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxWorkspaceConvertToMonorepo", + "cli": "nx", + "title": "Nx Convert to Monorepo", + "description": "Convert an Nx project to a monorepo.", + "type": "object", + "examples": [ + { + "command": "nx g @nx/workspace:monorepo", + "description": "Convert an Nx standalone project to a monorepo." + } + ], + "properties": {}, + "required": [], + "presets": [] + }, + "description": "Convert a Nx project to a monorepo.", + "implementation": "/packages/workspace/src/generators/convert-to-monorepo/convert-to-monorepo.ts", + "aliases": [], + "hidden": false, + "path": "/packages/workspace/src/generators/convert-to-monorepo/schema.json", + "type": "generator" +} diff --git a/docs/map.json b/docs/map.json index b3b6ccb843e72..33efc85103dfa 100644 --- a/docs/map.json +++ b/docs/map.json @@ -4,7 +4,7 @@ "description": "This is used to create documentation routing and hierarchy on the nx.dev website.", "content": [ { - "name": "Nx docs", + "name": "Nx", "id": "nx-documentation", "description": "Nx documentation for you to discover!", "itemList": [ @@ -271,70 +271,78 @@ "itemList": [ { "name": "Run Tasks", + "description": "Learn about the various ways you can use Nx to run tasks in your workspace.", "tags": ["run-tasks"], "id": "run-tasks", "file": "shared/core-features/run-tasks" }, { "name": "Cache Task Results", + "description": "Learn how to define cacheable tasks, how to fine-tune with inputs and outputs, where the cache is stored and much more.", "id": "cache-task-results", "tags": ["cache-task-results"], "file": "shared/core-features/cache-task-results" }, { - "name": "Share Your Cache", - "id": "share-your-cache", - "tags": ["share-your-cache"], - "file": "shared/core-features/share-your-cache" - }, - { - "name": "Explore the Graph", - "id": "explore-graph", - "tags": ["explore-graph"], - "file": "shared/core-features/explore-graph" + "name": "Use Remote Caching", + "description": "Learn how to enable remote caching s.t. you don't just benefit locally from it but also in CI.", + "id": "remote-cache", + "tags": ["remote-cache"], + "file": "shared/core-features/remote-cache" }, { "name": "Distribute Task Execution", + "description": "Learn how to efficiently distribute tasks across machines to take full advantage of parallelization. Nx Cloud has a built-in DTE mechanism which makes this a trivial task.", "id": "distribute-task-execution", "tags": ["distribute-task-execution"], "file": "shared/core-features/distribute-task-execution" }, { - "name": "Integrate with Editors", - "id": "integrate-with-editors", - "tags": ["integrate-with-editors"], - "file": "shared/core-features/integrate-with-editors" + "name": "Explore the Graph", + "id": "explore-graph", + "description": "Nx uses a graph behind the scenes to optimize your operations. You can also visualize and use the graph to better understand your workspace structure. Learn more in this guide.", + "tags": ["explore-graph"], + "file": "shared/core-features/explore-graph" }, { "name": "Automate Updating Dependencies", + "description": "Learn how Nx provides automated update scripts to help you keep your workspace, tooling and framework dependencies up to date.", "id": "automate-updating-dependencies", "tags": ["automate-updating-dependencies"], "file": "shared/core-features/automate-updating-dependencies" }, { - "name": "Enforce Project Boundaries", - "id": "enforce-project-boundaries", - "tags": ["enforce-project-boundaries"], - "file": "shared/core-features/enforce-project-boundaries" - } - ] - }, - { - "name": "Plugin Features", - "id": "plugin-features", - "description": "Learn what is a plugin, the different type of plugins and how to create one.", - "itemList": [ + "name": "Enforce Module Boundaries", + "description": "Learn how to avoid dependency hell and scale a codebase by imposing constraints on your projects using the module boundary lint rule.", + "id": "enforce-module-boundaries", + "tags": ["enforce-module-boundaries"], + "file": "shared/core-features/enforce-module-boundaries" + }, { - "name": "Use Task Executors", - "id": "use-task-executors", - "tags": ["use-task-executors"], - "file": "shared/plugin-features/use-task-executors" + "name": "Integrate with Editors", + "description": "Learn about Nx Console, an extension for VS Code and WebStorm.", + "id": "integrate-with-editors", + "tags": ["integrate-with-editors"], + "file": "shared/core-features/integrate-with-editors" }, { - "name": "Use Code Generators", - "id": "use-code-generators", - "tags": ["use-code-generators"], - "file": "shared/plugin-features/use-code-generators" + "name": "Plugin Features", + "id": "plugin-features", + "description": "Learn what is a plugin, the different type of plugins and how to create one.", + "itemList": [ + { + "name": "Use Task Executors", + "id": "use-task-executors", + "tags": ["use-task-executors"], + "file": "shared/plugin-features/use-task-executors" + }, + { + "name": "Use Code Generators", + "id": "use-code-generators", + "tags": ["use-code-generators"], + "file": "shared/plugin-features/use-code-generators" + } + ] } ] }, @@ -345,7 +353,7 @@ "itemList": [ { "name": "Integrated Repos vs. Package-Based Repos vs. Standalone Apps", - "tags": ["intro"], + "tags": ["intro", "repository-types"], "id": "integrated-vs-package-based", "file": "shared/concepts/integrated-vs-package-based" }, @@ -380,153 +388,714 @@ "file": "shared/using-nx/affected" }, { - "name": "More Concept Guides »", - "id": "more-concept-guides", - "path": "/more-concepts" + "name": "More Concepts", + "id": "more-concepts", + "description": "Get deeper into how Nx works and its different aspects.", + "itemList": [ + { + "name": "Customizing Inputs", + "id": "customizing-inputs", + "tags": ["cache-task-results"], + "file": "shared/concepts/customizing-inputs" + }, + { + "name": "Incremental Builds", + "id": "incremental-builds", + "tags": ["use-task-executors"], + "file": "shared/incremental-builds" + }, + { + "name": "Illustrated Distributed Task Execution", + "tags": ["distribute-task-execution"], + "id": "illustrated-dte", + "file": "shared/concepts/illustrated-dte-guide" + }, + { + "name": "Nx and Turborepo", + "id": "turbo-and-nx", + "file": "shared/guides/turbo-and-nx" + }, + { + "name": "Monorepos", + "id": "why-monorepos", + "file": "shared/guides/why-monorepos" + }, + { + "name": "Dependency Management", + "id": "dependency-management", + "file": "shared/concepts/dependency-management" + }, + { + "name": "Code Sharing", + "id": "code-sharing", + "file": "shared/concepts/code-sharing" + }, + { + "name": "Using Nx at Enterprises", + "id": "monorepo-nx-enterprise", + "tags": ["enforce-module-boundaries", "use-code-generators"], + "file": "shared/monorepo-nx-enterprise" + }, + { + "name": "Nx Daemon", + "id": "nx-daemon", + "file": "shared/daemon" + }, + { + "name": "Nx and the Angular CLI", + "id": "nx-and-angular", + "file": "shared/guides/nx-and-angular-cli" + }, + { + "name": "Folder Structure", + "id": "folder-structure", + "file": "shared/guides/integrated-repo-folder-structure" + }, + { + "name": "Nx Devkit and Angular Devkit", + "id": "nx-devkit-angular-devkit", + "tags": ["create-your-own-plugin"], + "file": "shared/guides/nx-devkit-angular-devkit" + }, + { + "name": "Micro Frontend Architecture", + "id": "micro-frontend-architecture", + "file": "shared/guides/module-federation/micro-frontend-architecture" + }, + { + "name": "Faster Builds with Module Federation", + "id": "faster-builds-with-module-federation", + "tags": [ + "use-task-executors", + "module-federation", + "angular", + "react" + ], + "file": "shared/guides/module-federation/faster-builds" + }, + { + "name": "Applications and Libraries", + "id": "applications-and-libraries", + "tags": ["enforce-module-boundaries"], + "file": "shared/workspace/applications-and-libraries" + }, + { + "name": "Creating Libraries", + "id": "creating-libraries", + "tags": ["enforce-module-boundaries"], + "file": "shared/workspace/creating-libraries" + }, + { + "name": "Library Types", + "id": "library-types", + "tags": ["enforce-module-boundaries"], + "file": "shared/workspace/library-types" + }, + { + "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" + }, + { + "name": "How the Project Graph is Built", + "id": "how-project-graph-is-built", + "tags": ["explore-graph"], + "file": "shared/concepts/how-project-graph-is-built" + }, + { + "name": "Nx and the Nx Wrapper", + "id": "nx-and-the-wrapper", + "file": "shared/guides/nx-and-the-wrapper" + }, + { + "name": "Managing your Global Nx Installation", + "id": "global-nx", + "file": "shared/guides/global-nx" + } + ] } ] }, { - "name": "More Concepts", - "id": "more-concepts", - "description": "Get deeper into how Nx works and its different aspects.", + "name": "Recipes", + "id": "recipes", + "description": "In depth recipes for common tasks", "itemList": [ { - "name": "Customizing Inputs", - "id": "customizing-inputs", - "tags": ["cache-task-results"], - "file": "shared/concepts/customizing-inputs" - }, - { - "name": "Incremental Builds", - "id": "incremental-builds", - "tags": ["use-task-executors"], - "file": "shared/incremental-builds" - }, - { - "name": "Illustrated Distributed Task Execution", - "tags": ["distribute-task-execution"], - "id": "illustrated-dte", - "file": "shared/concepts/illustrated-dte-guide" + "name": "Adopting Nx", + "id": "adopting-nx", + "description": "Adopting Nx incrementally, on existing project or from scratch.", + "itemList": [ + { + "name": "NPM/Yarn/PNPM workspaces", + "id": "adding-to-monorepo", + "file": "shared/migration/adding-to-monorepo" + }, + { + "name": "Add to any Project", + "id": "adding-to-existing-project", + "file": "shared/migration/adding-to-existing-project" + }, + { + "name": "Nx and Lerna", + "id": "lerna-and-nx", + "file": "shared/migration/lerna-and-nx" + }, + { + "name": "Preserving Git Histories", + "id": "preserving-git-histories", + "file": "shared/migration/preserving-git-histories" + }, + { + "name": "Manual migration", + "id": "manual", + "file": "shared/migration/manual" + } + ] }, { - "name": "Nx and Turborepo", - "id": "turbo-and-nx", - "file": "shared/guides/turbo-and-nx" + "name": "React", + "id": "react", + "description": "Advanced guides to adopt Nx in React.", + "itemList": [ + { + "name": "Migrating from CRA", + "id": "migration-cra", + "file": "shared/migration/migration-cra" + }, + { + "name": "React 18 Migration", + "id": "react-18", + "file": "shared/guides/react-18" + }, + { + "name": "React Native with Nx", + "id": "react-native", + "file": "shared/guides/react-native" + }, + { + "name": "Remix with Nx", + "id": "remix", + "file": "shared/guides/remix" + }, + { + "name": "Use Environment Variables in React", + "id": "use-environment-variables-in-react", + "tags": ["environment-variables"], + "file": "shared/guides/use-environment-variables-in-react" + }, + { + "name": "Using Tailwind CSS in React", + "id": "using-tailwind-css-in-react", + "file": "shared/guides/using-tailwind-css-in-react" + }, + { + "name": "Adding Images, Fonts, and Files", + "id": "adding-assets-react", + "file": "shared/guides/adding-assets" + }, + { + "name": "Setup Module Federation with SSR for React", + "id": "module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"], + "file": "shared/recipes/module-federation-with-ssr" + }, + { + "name": "Deploying Next.js applications to Vercel", + "id": "deploy-nextjs-to-vercel", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel" + } + ] }, { - "name": "Monorepos", - "id": "why-monorepos", - "file": "shared/guides/why-monorepos" + "name": "Angular", + "id": "angular", + "description": "Advanced guides to adopt Nx in Angular.", + "itemList": [ + { + "name": "Migration", + "id": "migration", + "itemList": [ + { + "name": "Migrating from Angular CLI", + "id": "angular", + "file": "shared/migration/migration-angular" + }, + { + "name": "Migrating From Multiple Angular CLI Repos", + "id": "angular-multiple", + "file": "shared/migration/angular-multiple" + }, + { + "name": "Migrating Angular Application manually", + "id": "angular-manual", + "file": "shared/migration/angular-manual" + }, + { + "name": "Migrating from AngularJS", + "id": "angularjs", + "file": "shared/migration/migration-angularjs" + } + ] + }, + { + "name": "Use Environment Variables in Angular", + "id": "use-environment-variables-in-angular", + "tags": ["environment-variables"], + "file": "shared/guides/use-environment-variables-in-angular" + }, + { + "name": "Using Tailwind CSS with Angular projects", + "id": "using-tailwind-css-with-angular-projects", + "file": "shared/guides/using-tailwind-css-with-angular-projects" + }, + { + "name": "Setup Module Federation with SSR for Angular", + "id": "module-federation-with-ssr", + "tags": [ + "use-task-executors", + "module-federation", + "angular" + ], + "file": "shared/recipes/module-federation-with-ssr" + }, + { + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "id": "dynamic-module-federation-with-angular", + "tags": [ + "use-task-executors", + "module-federation", + "angular" + ], + "file": "shared/guides/module-federation/dynamic-mfe-angular" + }, + { + "name": "Setup incremental builds for Angular applications", + "id": "setup-incremental-builds-angular", + "file": "shared/guides/setup-incremental-builds-angular" + } + ] }, { - "name": "Dependency Management", - "id": "dependency-management", - "file": "shared/concepts/dependency-management" + "name": "Node", + "id": "node", + "description": "Set of Node related recipes.", + "itemList": [ + { + "name": "Deploying a Node App to Fly.io", + "id": "node-server-fly-io", + "tags": ["deployment", "node"], + "file": "shared/recipes/deployment/node-server-fly-io" + }, + { + "name": "Add and Deploy Netlify Edge Functions with Node", + "id": "node-serverless-functions-netlify", + "tags": ["deployment", "node"], + "file": "shared/recipes/deployment/node-serverless-functions-netlify" + }, + { + "name": "Deploying AWS lambda in Node.js", + "id": "node-aws-lambda", + "tags": ["deployment", "node"], + "file": "shared/recipes/deployment/node-aws-lambda" + } + ] }, { - "name": "Code Sharing", - "id": "code-sharing", - "file": "shared/concepts/code-sharing" + "name": "Storybook", + "id": "storybook", + "description": "Storybook how tos.", + "itemList": [ + { + "name": "One main Storybook instance for all projects", + "id": "one-storybook-for-all", + "tags": ["storybook"], + "file": "shared/recipes/one-storybook-for-all" + }, + { + "name": "One Storybook instance per scope", + "id": "one-storybook-per-scope", + "tags": ["storybook"], + "file": "shared/recipes/one-storybook-per-scope" + }, + { + "name": "One main Storybook instance using Storybook Composition", + "id": "one-storybook-with-composition", + "tags": ["storybook"], + "file": "shared/recipes/one-storybook-with-composition" + } + ] }, { - "name": "Using Nx at Enterprises", - "id": "monorepo-nx-enterprise", - "tags": ["enforce-project-boundaries", "use-code-generators"], - "file": "shared/monorepo-nx-enterprise" + "name": "Enforce Module Boundaries", + "id": "enforce-module-boundaries", + "description": "Configuring the enforce module boundaries rule", + "itemList": [ + { + "name": "Ban Dependencies with Certain Tags", + "id": "ban-dependencies-with-tags", + "tags": ["enforce-module-boundaries"], + "file": "shared/recipes/ban-dependencies-with-tags" + }, + { + "name": "Tag in Multiple Dimensions", + "id": "tag-multiple-dimensions", + "tags": ["enforce-module-boundaries"], + "file": "shared/recipes/tag-multiple-dimensions" + }, + { + "name": "Ban External Imports", + "id": "ban-external-imports", + "tags": ["enforce-module-boundaries"], + "file": "shared/recipes/ban-external-imports" + }, + { + "name": "Tags Allow List", + "id": "tags-allow-list", + "tags": ["enforce-module-boundaries"], + "file": "shared/recipes/tags-allow-list" + } + ] }, { - "name": "Nx Daemon", - "id": "nx-daemon", - "file": "shared/daemon" + "name": "CI", + "id": "ci", + "description": "All recipes about how to use Nx to make your CI faster.", + "itemList": [ + { + "name": "CI Setup", + "id": "ci-setup", + "tags": ["distribute-task-execution"], + "file": "shared/ci-overview" + }, + { + "name": "Prepare applications for deployment via CI", + "id": "ci-deployment", + "tags": ["docker", "deploy"], + "file": "shared/recipes/ci-deployment" + }, + { + "name": "Setting up Azure Pipelines", + "id": "monorepo-ci-azure", + "file": "shared/monorepo-ci-azure" + }, + { + "name": "Setting up CircleCI", + "id": "monorepo-ci-circle-ci", + "file": "shared/monorepo-ci-circle-ci" + }, + { + "name": "Setting up GitHub Actions", + "id": "monorepo-ci-github-actions", + "file": "shared/monorepo-ci-github-actions" + }, + { + "name": "Setting up Jenkins", + "id": "monorepo-ci-jenkins", + "file": "shared/monorepo-ci-jenkins" + }, + { + "name": "Setting up GitLab", + "id": "monorepo-ci-gitlab", + "file": "shared/monorepo-ci-gitlab" + }, + { + "name": "Setting up Bitbucket", + "id": "monorepo-ci-bitbucket-pipelines", + "file": "shared/monorepo-ci-bitbucket-pipelines" + } + ] }, { - "name": "Nx and the Angular CLI", - "id": "nx-and-angular", - "file": "shared/guides/nx-and-angular-cli" + "name": "Tips and tricks", + "id": "tips-n-tricks", + "description": "Various tips and tricks for using Nx.", + "itemList": [ + { + "name": "Add a Package-based Project in an Integrated Repo", + "id": "package-based-in-integrated", + "tags": ["repository-types"], + "file": "shared/recipes/repo-types/package-based-in-integrated" + }, + { + "name": "Add an Integrated Project in a Package-based Repo", + "id": "integrated-in-package-based", + "tags": ["repository-types"], + "file": "shared/recipes/repo-types/integrated-in-package-based" + }, + { + "name": "Configuring ESLint with Typescript", + "id": "eslint", + "file": "shared/eslint" + }, + { + "name": "Define Environment Variables", + "id": "define-environment-variables", + "tags": ["environment-variables"], + "file": "shared/guides/define-environment-variables" + }, + { + "name": "Configuring Browser Support", + "id": "browser-support", + "file": "shared/guides/browser-support" + }, + { + "name": "Include Assets in Build", + "id": "include-assets-in-build", + "tags": [], + "file": "shared/recipes/include-assets-in-build" + }, + { + "name": "Include All package.json Files as Projects", + "id": "include-all-packagejson", + "tags": [], + "file": "shared/recipes/include-all-packagejson" + }, + { + "name": "Identify Dependencies Between Folders", + "id": "identify-dependencies-between-folders", + "tags": [], + "file": "shared/recipes/identify-dependencies-between-folders" + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "id": "root-level-scripts", + "tags": ["run-tasks"], + "file": "shared/recipes/root-level-scripts" + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "id": "analyze-source-files", + "tags": ["explore-graph"], + "file": "shared/recipes/analyze-source-files" + }, + { + "name": "Workspace Watching", + "id": "workspace-watching", + "tags": ["workspace-watching"], + "file": "shared/recipes/workspace-watching" + }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "id": "standalone-to-integrated", + "tags": ["repository-types"], + "file": "shared/recipes/repo-types/standalone-to-integrated" + }, + { + "name": "Use JavaScript instead TypeScript", + "id": "js-and-ts", + "file": "shared/guides/js-and-ts" + }, + { + "name": "Altering Migration Process", + "id": "advanced-update", + "tags": ["automate-updating-dependencies"], + "file": "shared/recipes/advanced-update" + }, + { + "name": "Running Custom Commands", + "id": "run-commands-executor", + "tags": ["use-task-executors"], + "file": "shared/running-custom-commands" + } + ] }, { - "name": "Folder Structure", - "id": "folder-structure", - "file": "shared/guides/integrated-repo-folder-structure" + "name": "Troubleshooting", + "id": "troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "itemList": [ + { + "name": "Resolve Circular Dependencies", + "id": "resolve-circular-dependencies", + "tags": ["explore-graph"], + "file": "shared/recipes/resolve-circular-dependencies" + }, + { + "name": "Troubleshooting Nx Install Issues", + "id": "troubleshoot-nx-install-issues", + "file": "shared/installation/troubleshoot-installation" + }, + { + "name": "Troubleshoot Cache Misses", + "id": "troubleshoot-cache-misses", + "tags": ["cache-task-results"], + "file": "shared/recipes/troubleshoot-cache-misses" + }, + { + "name": "Unknown Local Cache Error", + "id": "unknown-local-cache", + "tags": [], + "file": "shared/guides/unknown-local-cache" + }, + { + "name": "Profiling Build Performance", + "id": "performance-profiling", + "tags": ["use-task-executors", "environment-variables"], + "file": "shared/guides/performance-profiling" + } + ] }, { - "name": "Nx Devkit and Angular Devkit", - "id": "nx-devkit-angular-devkit", - "tags": ["create-your-own-plugin"], - "file": "shared/guides/nx-devkit-angular-devkit" + "name": "Nx Console", + "id": "nx-console", + "description": "Checkout all the recipes related to Nx Console.", + "itemList": [ + { + "name": "Telemetry", + "id": "console-telemetry", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-telemetry" + }, + { + "name": "Generate Command", + "id": "console-generate-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-generate-command" + }, + { + "name": "Run Command", + "id": "console-run-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-run-command" + }, + { + "name": "Add Dependency Command", + "id": "console-add-dependency-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-add-dependency-command" + }, + { + "name": "Project Pane", + "id": "console-project-pane", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-project-pane" + }, + { + "name": "Keyboard Shortcuts", + "id": "console-shortcuts", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-shortcuts" + } + ] }, { - "name": "Micro Frontend Architecture", - "id": "micro-frontend-architecture", - "file": "shared/guides/module-federation/micro-frontend-architecture" - }, + "name": "Other", + "id": "other", + "description": "Other recipes you will find useful.", + "itemList": [ + { + "name": "Serverless deployment with Deno Deploy", + "id": "deno-deploy", + "tags": ["deployment", "deno"], + "file": "shared/recipes/deployment/deno-deploy" + }, + { + "name": "Add and Deploy Netlify Edge Functions with Deno", + "id": "deno-netlify-functions", + "tags": ["deployment", "deno"], + "file": "shared/recipes/deployment/deno-netlify-edge-functions" + }, + { + "name": "Rescope Packages from @nrwl to @nx", + "id": "rescope", + "tags": [], + "file": "shared/recipes/rescope" + } + ] + } + ] + }, + { + "name": "Showcase", + "id": "showcase", + "description": "Discover our selection of examples and benchmarks.", + "itemList": [ { - "name": "Applications and Libraries", - "id": "applications-and-libraries", - "tags": ["enforce-project-boundaries"], - "file": "shared/workspace/applications-and-libraries" - }, - { - "name": "Creating Libraries", - "id": "creating-libraries", - "tags": ["enforce-project-boundaries"], - "file": "shared/workspace/creating-libraries" - }, - { - "name": "Library Types", - "id": "library-types", - "tags": ["enforce-project-boundaries"], - "file": "shared/workspace/library-types" - }, - { - "name": "Grouping Libraries", - "id": "grouping-libraries", - "tags": ["enforce-project-boundaries"], - "file": "shared/workspace/grouping-libraries" - }, - { - "name": "Buildable and Publishable Libraries", - "id": "buildable-and-publishable-libraries", - "file": "shared/workspace/buildable-and-publishable-libraries" - }, - { - "name": "How the Project Graph is Built", - "id": "how-project-graph-is-built", - "tags": ["explore-graph"], - "file": "shared/concepts/how-project-graph-is-built" - }, - { - "name": "Nx and the Nx Wrapper", - "id": "nx-and-the-wrapper", - "file": "shared/guides/nx-and-the-wrapper" - }, - { - "name": "Managing your Global Nx Installation", - "id": "global-nx", - "file": "shared/guides/global-nx" - } - ] - }, - { - "name": "Recipes", - "id": "recipes", - "description": "Learn quickly how to do things with Nx.", - "itemList": [ - { - "name": "CI Setup", - "id": "ci-setup", - "path": "/recipes/ci/ci-setup" - }, - { - "name": "Adopting Nx", - "id": "adopting-nx", - "path": "/recipes/adopting-nx" - }, - { - "name": "All Recipes »", - "id": "all", - "path": "/recipes" + "name": "Example Repos", + "id": "example-repos", + "description": "Examples of different ways to use Nx", + "itemList": [ + { + "name": "Add a Lit Project", + "id": "add-lit", + "description": "Add a Lit project to your repo", + "file": "shared/recipes/add-stack/add-lit" + }, + { + "name": "Add a Solid Project", + "id": "add-solid", + "description": "Add a Solid project to your repo", + "file": "shared/recipes/add-stack/add-solid" + }, + { + "name": "Add a Qwik Project", + "id": "add-qwik", + "description": "Add a Qwik project to your repo", + "file": "shared/recipes/add-stack/add-qwik" + }, + { + "name": "Powering Up React Development With Nx", + "id": "react-nx", + "file": "shared/examples/react-nx" + }, + { + "name": "Using Apollo GraphQL", + "id": "apollo-react", + "file": "shared/examples/apollo-react" + }, + { + "name": "Using Prisma with NestJS", + "id": "nestjs-prisma", + "tags": ["database", "node"], + "file": "shared/recipes/database/nestjs-prisma" + }, + { + "name": "Using Mongo with Fastify", + "id": "mongo-fastify", + "tags": ["database", "node"], + "file": "shared/recipes/database/mongo-fastify" + }, + { + "name": "Using Redis with Fastify", + "id": "redis-fastify", + "tags": ["database", "node"], + "file": "shared/recipes/database/redis-fastify" + }, + { + "name": "Using Postgres with Fastify", + "id": "postgres-fastify", + "tags": ["database", "node"], + "file": "shared/recipes/database/postgres-fastify" + }, + { + "name": "Using PlanetScale with Serverless Fastify", + "id": "serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"], + "file": "shared/recipes/database/serverless-fastify-planetscale" + }, + { + "name": "Large Repo and Caching", + "id": "caching", + "file": "shared/examples/caching" + }, + { + "name": "Large Repo and DTE", + "id": "dte", + "file": "shared/examples/dte" + }, + { + "name": "Nx Micro-Frontend Example", + "id": "mfe", + "file": "shared/examples/nx-examples" + } + ] } ] }, @@ -536,12 +1105,7 @@ "description": "Understand how to use Nx functionalities, what arguments and options are available for each component.", "itemList": [ { - "name": "Commands", - "id": "commands", - "file": "shared/reference/commands" - }, - { - "name": "nx.json", + "name": "Nx Configuration", "id": "nx-json", "file": "shared/reference/nx-json" }, @@ -554,7 +1118,7 @@ { "name": ".nxignore", "id": "nxignore", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "file": "shared/reference/nxignore" }, { @@ -563,908 +1127,298 @@ "tags": ["environment-variables"], "file": "shared/reference/environment-variables" }, - { - "name": "Packages", - "id": "packages", - "file": "", - "path": "/packages", - "isExternal": true - }, - { - "name": "Nx Devkit", - "id": "packages-devkit", - "tags": ["create-your-own-plugin"], - "file": "", - "path": "/packages/devkit/documents/nx_devkit", - "isExternal": true - }, { "name": "Glossary", "id": "glossary", - "tags": [], - "file": "shared/reference/glossary" - }, - { - "name": "Changelog", - "id": "changelog", - "file": "", - "path": "/reference/changelog", - "isExternal": true - } - ] - }, - { - "name": "Deprecated", - "id": "deprecated", - "description": "Functionality that has been superseded in the current version of Nx. Listed here for those running older versions.", - "itemList": [ - { - "name": "workspace.json", - "id": "workspace-json", - "file": "shared/deprecated/workspace-json" - }, - { - "name": "workspace-lint", - "id": "workspace-lint", - "file": "shared/deprecated/workspace-lint" - }, - { - "name": "Workspace Generators", - "id": "workspace-generators", - "file": "shared/deprecated/workspace-generators" - }, - { - "name": "Workspace Executors", - "id": "workspace-executors", - "file": "shared/deprecated/workspace-executors" - }, - { - "name": "defaultCollection", - "id": "default-collection", - "file": "shared/deprecated/default-collection" - }, - { - "name": "runtimeCacheInputs", - "id": "runtime-cache-inputs", - "file": "shared/deprecated/runtime-cache-inputs" - }, - { - "name": "globalImplicitDependencies", - "id": "global-implicit-dependencies", - "file": "shared/deprecated/global-implicit-dependencies" - }, - { - "name": "Storybook deprecated docs", - "id": "storybook", - "description": "Deprecated @nx/storybook package documentation and guides.", - "itemList": [ - { - "id": "angular-storybook-targets", - "name": "Angular: Information about the Storybook targets", - "description": "This document explains the role of the storybook and build-storybook targets in Angular projects with a Storybook configuration, and specifically which executors are used for them.", - "file": "shared/deprecated/storybook/angular-storybook-targets" - }, - { - "id": "angular-browser-target", - "name": "Angular: The browserTarget", - "description": "This document explains the role of the browserTarget in Angular projects with a Storybook configuration, and how the Storybook executors use it.", - "file": "shared/deprecated/storybook/angular-browser-target" - }, - { - "id": "migrate-webpack-final-angular", - "name": "Angular: Storybook Migration to webpackFinal", - "description": "This guide explains how migrate from older versions of Storybook which used a custom webpack.config.js to the new Storybook 6.3+ which uses the webpackFinal property in the main configuration.", - "file": "shared/deprecated/storybook/migrate-webpack-final-angular" - }, - { - "id": "upgrade-storybook-v6-angular", - "name": "Angular: Upgrading to Storybook 6", - "description": "This guide explains how you can upgrade your Storybook from versions 5.3 and below to Storybook 6, for Angular projects.", - "file": "shared/deprecated/storybook/storybook-v6-angular" - }, - { - "id": "migrate-webpack-final-react", - "name": "React: Storybook Migration to webpackFinal and the Nx Addon", - "description": "This guide explains how migrate from older versions of Storybook which used a custom webpack.config.js to the new Storybook 6.3+ which uses the webpackFinal property in the main configuration and the Nx React Addon.", - "file": "shared/deprecated/storybook/migrate-webpack-final-react" - }, - { - "id": "upgrade-storybook-v6-react", - "name": "React: Upgrading to Storybook 6", - "description": "This guide explains how you can upgrade your Storybook from versions 5.3 and below to Storybook 6, for React projects.", - "file": "shared/deprecated/storybook/storybook-v6-react" - } - ] - } - ] - }, - { - "name": "See Also", - "id": "see-also", - "description": "Links to other pieces of documentation", - "itemList": [ - { - "name": "Nx Cloud Documentation", - "id": "nx-cloud-documentation", - "file": "", - "tags": ["cache-task-results", "distribute-task-execution"], - "path": "/nx-cloud/intro/what-is-nx-cloud", - "isExternal": true - }, - { - "name": "Nx Cloud Main Site", - "id": "nx-cloud-main-site", - "file": "", - "tags": ["cache-task-results", "distribute-task-execution"], - "path": "https://nx.app", - "isExternal": true - }, - { - "name": "--skip-nx-cache flag", - "id": "skip-nx-cache-flag", - "file": "", - "tags": ["cache-task-results"], - "path": "/packages/nx/documents/affected#skip-nx-cache", - "isExternal": true - }, - { - "name": "tasks-runner-options property", - "id": "tasks-runner-options-property", - "file": "", - "tags": ["cache-task-results"], - "path": "/reference/nx-json#tasks-runner-options", - "isExternal": true - }, - { - "name": "nx.json reference: inputs and namedInputs", - "id": "nxjson-inputs", - "file": "", - "tags": ["cache-task-results"], - "path": "/reference/nx-json#inputs-&-namedinputs", - "isExternal": true - }, - { - "name": "Project Configuration reference: inputs and namedInputs", - "id": "project-config-inputs", - "file": "", - "tags": ["cache-task-results"], - "path": "/reference/project-configuration#inputs-&-namedinputs", - "isExternal": true - }, - { - "name": "nx.json workspaceLayout property", - "id": "nxjson-workspaceLayout", - "file": "", - "tags": ["enforce-project-boundaries"], - "path": "/reference/nx-json#workspace-layout", - "isExternal": true - }, - { - "name": "nx.json generator defaults", - "id": "nxjson-generator-defaults", - "file": "", - "tags": ["use-code-generators"], - "path": "/reference/nx-json#generators", - "isExternal": true - }, - { - "name": "Site Map", - "id": "sitemap", - "tags": [], - "file": "shared/reference/sitemap" - } - ] - } - ] - }, - { - "name": "Plugins", - "id": "plugins", - "description": "Learn more about creating your own plugin, extending Nx.", - "itemList": [ - { - "name": "Intro", - "id": "intro", - "description": "Learn about plugins.", - "itemList": [ - { - "name": "Getting Started with Plugins", - "id": "getting-started", - "description": "Learn how to extend Nx by creating and releasing your own Nx plugin.", - "file": "shared/plugins/intro" - }, - { - "name": "Plugin Registry", - "description": "Browse official and community plugins", - "id": "registry", - "file": "", - "path": "/plugins/registry", - "isExternal": false - } - ] - }, - { - "name": "5 Min Tutorials", - "id": "tutorials", - "description": "Get started with plugins", - "itemList": [ - { - "name": "Create a Local Plugin", - "id": "create-plugin", - "file": "shared/plugins/create-plugin" - }, - { - "name": "Maintain a Published Plugin", - "id": "publish-plugin", - "file": "shared/plugins/maintain-published-plugin" - } - ] - }, - { - "name": "Recipes", - "id": "recipes", - "description": "Focused instructions to complete a specific task", - "itemList": [ - { - "name": "Write a Simple Executor", - "id": "local-executors", - "tags": ["use-task-executors"], - "file": "shared/recipes/plugins/local-executors" - }, - { - "name": "Compose Executors", - "id": "compose-executors", - "tags": ["use-task-executors"], - "file": "shared/recipes/plugins/compose-executors" - }, - { - "name": "Write a Simple Generator", - "id": "local-generators", - "tags": ["use-code-generators"], - "file": "shared/recipes/generators/local-generators" - }, - { - "name": "Compose Generators", - "id": "composing-generators", - "tags": ["use-code-generators"], - "file": "shared/recipes/generators/composing-generators" - }, - { - "name": "Provide Options for Generators", - "id": "generator-options", - "tags": ["use-code-generators"], - "file": "shared/recipes/generators/generator-options" - }, - { - "name": "Create Files", - "id": "creating-files", - "tags": ["use-code-generators"], - "file": "shared/recipes/generators/creating-files" - }, - { - "name": "Modify Files", - "id": "modifying-files", - "tags": ["use-code-generators"], - "file": "shared/recipes/generators/modifying-files" - }, - { - "name": "Write a Migration", - "id": "migration-generators", - "tags": ["create-your-own-plugin"], - "file": "shared/recipes/plugins/migration-generators" - }, - { - "name": "Create a Preset", - "id": "create-preset", - "tags": ["create-your-own-plugin"], - "file": "shared/recipes/plugins/create-preset" - }, - { - "name": "Modify the Project Graph", - "id": "project-graph-plugins", - "tags": ["create-your-own-plugin", "explore-graph"], - "file": "shared/recipes/plugins/project-graph-plugins" - }, - { - "name": "Identify Custom Projects", - "id": "project-inference-plugins", - "tags": ["create-your-own-plugin"], - "file": "shared/recipes/plugins/project-inference-plugins" - } - ] - } - ] - }, - { - "name": "Nx Recipes", - "id": "nx-recipes", - "description": "Learn quickly how to do things with Nx.", - "itemList": [ - { - "name": "Getting Started", - "id": "getting-started", - "description": "Basic information to get you started.", - "itemList": [ - { - "name": "Set up a new workspace", - "id": "set-up-a-new-workspace", - "description": "How to setup quickly a new Nx workspace.", - "file": "shared/recipes/set-up-a-new-workspace" - } - ] - }, - { - "name": "Nx Console", - "id": "nx-console", - "description": "Checkout all the recipes related to Nx Console.", - "itemList": [ - { - "name": "Nx Console Telemetry", - "id": "console-telemetry", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-telemetry" - }, - { - "name": "Nx Console Generate Command", - "id": "console-generate-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-generate-command" - }, - { - "name": "Nx Console Run Command", - "id": "console-run-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-run-command" - }, - { - "name": "Nx Console Add Dependency Command", - "id": "console-add-dependency-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-add-dependency-command" - }, - { - "name": "Nx Console Project Pane", - "id": "console-project-pane", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-project-pane" - }, - { - "name": "Nx Console Keyboard Shortcuts", - "id": "console-shortcuts", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-shortcuts" - } - ] - }, - { - "name": "CI", - "id": "ci", - "description": "All recipes about how to use Nx to make your CI faster.", - "itemList": [ - { - "name": "CI Setup", - "id": "ci-setup", - "tags": ["distribute-task-execution"], - "file": "shared/ci-overview" - }, - { - "name": "Prepare applications for deployment via CI", - "id": "ci-deployment", - "tags": ["docker", "deploy"], - "file": "shared/recipes/ci-deployment" - }, - { - "name": "Setting up Azure Pipelines", - "id": "monorepo-ci-azure", - "file": "shared/monorepo-ci-azure" - }, - { - "name": "Setting up CircleCI", - "id": "monorepo-ci-circle-ci", - "file": "shared/monorepo-ci-circle-ci" - }, - { - "name": "Setting up GitHub Actions", - "id": "monorepo-ci-github-actions", - "file": "shared/monorepo-ci-github-actions" - }, - { - "name": "Setting up Jenkins", - "id": "monorepo-ci-jenkins", - "file": "shared/monorepo-ci-jenkins" - }, - { - "name": "Setting up GitLab", - "id": "monorepo-ci-gitlab", - "file": "shared/monorepo-ci-gitlab" - }, - { - "name": "Setting up Bitbucket", - "id": "monorepo-ci-bitbucket-pipelines", - "file": "shared/monorepo-ci-bitbucket-pipelines" - }, - { - "name": "Troubleshooting Nx Install Issues", - "id": "troubleshoot-nx-install-issues", - "file": "shared/installation/troubleshoot-installation" - } - ] - }, - { - "name": "Adopting Nx", - "id": "adopting-nx", - "description": "Adopting Nx incrementally, on existing project or from scratch.", - "itemList": [ - { - "name": "NPM/Yarn/PNPM workspaces", - "id": "adding-to-monorepo", - "file": "shared/migration/adding-to-monorepo" - }, - { - "name": "Add to any Project", - "id": "adding-to-existing-project", - "file": "shared/migration/adding-to-existing-project" - }, - { - "name": "From CRA", - "id": "migration-cra", - "file": "shared/migration/migration-cra" - }, - { - "name": "From Angular CLI", - "id": "migration-angular", - "file": "shared/migration/migration-angular" - }, - { - "name": "Nx and Lerna", - "id": "lerna-and-nx", - "file": "shared/migration/lerna-and-nx" - }, - { - "name": "From AngularJS", - "id": "migration-angularjs", - "file": "shared/migration/migration-angularjs" - }, - { - "name": "Preserving Git Histories", - "id": "preserving-git-histories", - "file": "shared/migration/preserving-git-histories" - }, - { - "name": "Manual migration", - "id": "manual", - "file": "shared/migration/manual" - } - ] - }, - { - "name": "Adopting Nx From Angular CLI", - "id": "adopting-nx-angular", - "description": "Advanced guides to adopt Nx coming from the Angular CLI", - "itemList": [ - { - "name": "From Angular CLI", - "id": "migration-angular", - "file": "shared/migration/migration-angular" - }, - { - "name": "From Angular CLI to Integrated", - "id": "angular-integrated", - "file": "shared/migration/angular-integrated" - }, - { - "name": "From Angular CLI Manually", - "id": "angular-manual", - "file": "shared/migration/angular-manual" - }, - { - "name": "From Multiple Angular CLI Repos", - "id": "angular-multiple", - "file": "shared/migration/angular-multiple" - } - ] - }, - { - "name": "Executors", - "id": "executors", - "description": "Use, extend and compose executors.", - "itemList": [ - { - "name": "Use Executor Configurations", - "id": "use-executor-configurations", - "tags": ["use-task-executors"], - "file": "shared/recipes/use-executor-configurations" - }, - { - "name": "Running Custom Commands", - "id": "run-commands-executor", - "tags": ["use-task-executors"], - "file": "shared/running-custom-commands" - } - ] - }, - { - "name": "Environment Variables", - "id": "environment-variables", - "description": "Using environment variables in an Nx workspace.", - "itemList": [ - { - "name": "Define Environment Variables", - "id": "define-environment-variables", - "tags": ["environment-variables"], - "file": "shared/guides/define-environment-variables" - }, - { - "name": "Use Environment Variables in React", - "id": "use-environment-variables-in-react", - "tags": ["environment-variables"], - "file": "shared/guides/use-environment-variables-in-react" - }, - { - "name": "Use Environment Variables in Angular", - "id": "use-environment-variables-in-angular", - "tags": ["environment-variables"], - "file": "shared/guides/use-environment-variables-in-angular" - } - ] - }, - { - "name": "Module Federation and Micro Frontends", - "id": "module-federation", - "description": "How to work with and setup Module Federation with Nx.", - "itemList": [ - { - "name": "Faster Builds with Module Federation", - "id": "faster-builds", - "tags": [ - "use-task-executors", - "module-federation", - "angular", - "react" - ], - "file": "shared/guides/module-federation/faster-builds" - }, - { - "name": "Setup Module Federation with SSR for Angular and React", - "id": "module-federation-with-ssr", - "tags": [ - "use-task-executors", - "module-federation", - "angular", - "react" - ], - "file": "shared/recipes/module-federation-with-ssr" - }, - { - "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "id": "dynamic-module-federation-with-angular", - "tags": ["use-task-executors", "module-federation", "angular"], - "file": "shared/guides/module-federation/dynamic-mfe-angular" - }, - { - "name": "Nx Micro-Frontend Example", - "id": "nx-examples", - "file": "shared/examples/nx-examples" - } - ] - }, - { - "name": "Storybook", - "id": "storybook", - "description": "Storybook how tos.", - "itemList": [ - { - "name": "Publishing Storybook: One main Storybook instance for all projects", - "id": "one-storybook-for-all", - "tags": ["storybook"], - "file": "shared/recipes/one-storybook-for-all" - }, - { - "name": "Publishing Storybook: One Storybook instance per scope", - "id": "one-storybook-per-scope", - "tags": ["storybook"], - "file": "shared/recipes/one-storybook-per-scope" - }, - { - "name": "Publishing Storybook: One main Storybook instance using Storybook Composition", - "id": "one-storybook-with-composition", - "tags": ["storybook"], - "file": "shared/recipes/one-storybook-with-composition" - } - ] - }, - { - "name": "Deployment", - "id": "deployment", - "description": "Deployment recipes for Node.js and Deno server applications.", - "itemList": [ - { - "name": "Deploying a Node App to Fly.io", - "id": "node-server-fly-io", - "tags": ["deployment", "node"], - "file": "shared/recipes/deployment/node-server-fly-io" - }, - { - "name": "Add and Deploy Netlify Edge Functions with Node", - "id": "node-serverless-functions-netlify", - "tags": ["deployment", "node"], - "file": "shared/recipes/deployment/node-serverless-functions-netlify" - }, - { - "name": "Deploying AWS lambda in Node.js", - "id": "node-aws-lambda", - "tags": ["deployment", "node"], - "file": "shared/recipes/deployment/node-aws-lambda" - }, - { - "name": "Serverless deployment with Deno Deploy", - "id": "deno-deploy", - "tags": ["deployment", "deno"], - "file": "shared/recipes/deployment/deno-deploy" - }, - { - "name": "Add and Deploy Netlify Edge Functions with Deno", - "id": "deno-netlify-functions", - "tags": ["deployment", "deno"], - "file": "shared/recipes/deployment/deno-netlify-edge-functions" - }, - { - "name": "Deploying Next.js applications to Vercel", - "id": "deploy-nextjs-to-vercel", - "file": "shared/recipes/deployment/deploy-nextjs-to-vercel" - } - ] - }, - { - "name": "Database", - "id": "database", - "description": "Recipes for using various databases in node apps.", - "itemList": [ - { - "name": "Using Prisma with NestJS", - "id": "nestjs-prisma", - "tags": ["database", "node"], - "file": "shared/recipes/database/nestjs-prisma" - }, - { - "name": "Using Mongo with Fastify", - "id": "mongo-fastify", - "tags": ["database", "node"], - "file": "shared/recipes/database/mongo-fastify" - }, - { - "name": "Using Redis with Fastify", - "id": "redis-fastify", - "tags": ["database", "node"], - "file": "shared/recipes/database/redis-fastify" - }, - { - "name": "Using Postgres with Fastify", - "id": "postgres-fastify", - "tags": ["database", "node"], - "file": "shared/recipes/database/postgres-fastify" - }, - { - "name": "Using PlanetScale with Serverless Fastify", - "id": "serverless-fastify-planetscale", - "tags": ["database", "node", "serverless"], - "file": "shared/recipes/database/serverless-fastify-planetscale" + "tags": [], + "file": "shared/reference/glossary" } ] }, { - "name": "Enforce Module Boundaries", - "id": "enforce-module-boundaries", - "description": "Configuring the enforce module boundaries rule", + "name": "Deprecated", + "id": "deprecated", + "description": "Functionality that has been superseded in the current version of Nx. Listed here for those running older versions.", "itemList": [ { - "name": "Ban Dependencies with Certain Tags", - "id": "ban-dependencies-with-tags", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/ban-dependencies-with-tags" + "name": "workspace.json", + "id": "workspace-json", + "file": "shared/deprecated/workspace-json" }, { - "name": "Tag in Multiple Dimensions", - "id": "tag-multiple-dimensions", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/tag-multiple-dimensions" + "name": "workspace-lint", + "id": "workspace-lint", + "file": "shared/deprecated/workspace-lint" }, { - "name": "Ban External Imports", - "id": "ban-external-imports", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/ban-external-imports" + "name": "Workspace Generators", + "id": "workspace-generators", + "file": "shared/deprecated/workspace-generators" }, { - "name": "Tags Allow List", - "id": "tags-allow-list", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/tags-allow-list" - } - ] - }, - { - "name": "Example Repos", - "id": "example-repos", - "description": "Examples of different ways to use Nx", - "itemList": [ + "name": "Workspace Executors", + "id": "workspace-executors", + "file": "shared/deprecated/workspace-executors" + }, { - "name": "Powering Up React Development With Nx", - "id": "react-nx", - "file": "shared/examples/react-nx" + "name": "defaultCollection", + "id": "default-collection", + "file": "shared/deprecated/default-collection" }, { - "name": "Using Apollo GraphQL", - "id": "apollo-react", - "file": "shared/examples/apollo-react" + "name": "runtimeCacheInputs", + "id": "runtime-cache-inputs", + "file": "shared/deprecated/runtime-cache-inputs" }, { - "name": "Large Repo and Caching", - "id": "caching", - "file": "shared/examples/caching" + "name": "globalImplicitDependencies", + "id": "global-implicit-dependencies", + "file": "shared/deprecated/global-implicit-dependencies" }, { - "name": "Large Repo and DTE", - "id": "dte", - "file": "shared/examples/dte" + "name": "Storybook deprecated docs", + "id": "storybook", + "description": "Deprecated @nx/storybook package documentation and guides.", + "itemList": [ + { + "id": "angular-storybook-targets", + "name": "Angular: Information about the Storybook targets", + "description": "This document explains the role of the storybook and build-storybook targets in Angular projects with a Storybook configuration, and specifically which executors are used for them.", + "file": "shared/deprecated/storybook/angular-storybook-targets" + }, + { + "id": "angular-browser-target", + "name": "Angular: The browserTarget", + "description": "This document explains the role of the browserTarget in Angular projects with a Storybook configuration, and how the Storybook executors use it.", + "file": "shared/deprecated/storybook/angular-browser-target" + }, + { + "id": "migrate-webpack-final-angular", + "name": "Angular: Storybook Migration to webpackFinal", + "description": "This guide explains how migrate from older versions of Storybook which used a custom webpack.config.js to the new Storybook 6.3+ which uses the webpackFinal property in the main configuration.", + "file": "shared/deprecated/storybook/migrate-webpack-final-angular" + }, + { + "id": "upgrade-storybook-v6-angular", + "name": "Angular: Upgrading to Storybook 6", + "description": "This guide explains how you can upgrade your Storybook from versions 5.3 and below to Storybook 6, for Angular projects.", + "file": "shared/deprecated/storybook/storybook-v6-angular" + }, + { + "id": "migrate-webpack-final-react", + "name": "React: Storybook Migration to webpackFinal and the Nx Addon", + "description": "This guide explains how migrate from older versions of Storybook which used a custom webpack.config.js to the new Storybook 6.3+ which uses the webpackFinal property in the main configuration and the Nx React Addon.", + "file": "shared/deprecated/storybook/migrate-webpack-final-react" + }, + { + "id": "upgrade-storybook-v6-react", + "name": "React: Upgrading to Storybook 6", + "description": "This guide explains how you can upgrade your Storybook from versions 5.3 and below to Storybook 6, for React projects.", + "file": "shared/deprecated/storybook/storybook-v6-react" + } + ] } ] }, { - "name": "Other", - "id": "other", - "description": "Other recipes you will find useful.", + "name": "See Also", + "id": "see-also", + "description": "Links to other pieces of documentation", "itemList": [ { - "name": "Run Root-Level NPM Scripts with Nx", - "id": "root-level-scripts", - "tags": ["run-tasks"], - "file": "shared/recipes/root-level-scripts" - }, - { - "name": "Disable Graph Links Created from Analyzing Source Files", - "id": "analyze-source-files", - "tags": ["explore-graph"], - "file": "shared/recipes/analyze-source-files" - }, - { - "name": "Workspace Watching", - "id": "workspace-watching", - "tags": ["workspace-watching"], - "file": "shared/recipes/workspace-watching" + "name": "Nx Cloud Documentation", + "id": "nx-cloud-documentation", + "file": "", + "tags": ["cache-task-results", "distribute-task-execution"], + "path": "/nx-cloud/intro/what-is-nx-cloud", + "isExternal": true }, { - "name": "Advanced Update Process", - "id": "advanced-update", - "tags": ["automate-updating-dependencies"], - "file": "shared/recipes/advanced-update" + "name": "Nx Cloud Main Site", + "id": "nx-cloud-main-site", + "file": "", + "tags": ["cache-task-results", "distribute-task-execution"], + "path": "https://nx.app", + "isExternal": true }, { - "name": "JavaScript and TypeScript", - "id": "js-and-ts", - "file": "shared/guides/js-and-ts" + "name": "--skip-nx-cache flag", + "id": "skip-nx-cache-flag", + "file": "", + "tags": ["cache-task-results"], + "path": "/packages/nx/documents/affected#skip-nx-cache", + "isExternal": true }, { - "name": "React Native with Nx", - "id": "react-native", - "file": "shared/guides/react-native" + "name": "tasks-runner-options property", + "id": "tasks-runner-options-property", + "file": "", + "tags": ["cache-task-results"], + "path": "/reference/nx-json#tasks-runner-options", + "isExternal": true }, { - "name": "Remix with Nx", - "id": "remix", - "file": "shared/guides/remix" + "name": "nx.json reference: inputs and namedInputs", + "id": "nxjson-inputs", + "file": "", + "tags": ["cache-task-results"], + "path": "/reference/nx-json#inputs-&-namedinputs", + "isExternal": true }, { - "name": "Adding Images, Fonts, and Files", - "id": "adding-assets-react", - "file": "shared/guides/adding-assets" + "name": "Project Configuration reference: inputs and namedInputs", + "id": "project-config-inputs", + "file": "", + "tags": ["cache-task-results"], + "path": "/reference/project-configuration#inputs-&-namedinputs", + "isExternal": true }, { - "name": "Setup incremental builds for Angular applications", - "id": "setup-incremental-builds-angular", - "file": "shared/guides/setup-incremental-builds-angular" + "name": "nx.json workspaceLayout property", + "id": "nxjson-workspaceLayout", + "file": "", + "tags": ["enforce-module-boundaries"], + "path": "/reference/nx-json#workspace-layout", + "isExternal": true }, { - "name": "Profiling Build Performance", - "id": "performance-profiling", - "tags": ["use-task-executors", "environment-variables"], - "file": "shared/guides/performance-profiling" + "name": "nx.json generator defaults", + "id": "nxjson-generator-defaults", + "file": "", + "tags": ["use-code-generators"], + "path": "/reference/nx-json#generators", + "isExternal": true }, { - "name": "Using ESLint in Nx Workspaces", - "id": "eslint", - "tags": ["enforce-project-boundaries"], - "file": "shared/eslint" - }, + "name": "Site Map", + "id": "sitemap", + "tags": [], + "file": "shared/reference/sitemap" + } + ] + } + ] + }, + { + "name": "Extending Nx", + "id": "extending-nx", + "description": "Learn more about creating your own plugin, extending Nx.", + "itemList": [ + { + "name": "Intro", + "id": "intro", + "description": "Learn about plugins.", + "itemList": [ { - "name": "Configuring Browser Support", - "id": "browser-support", - "file": "shared/guides/browser-support" + "name": "Getting Started with Plugins", + "id": "getting-started", + "description": "Learn how to extend Nx by creating and releasing your own Nx plugin.", + "file": "shared/plugins/intro" }, { - "name": "Using Tailwind CSS in React", - "id": "using-tailwind-css-in-react", - "file": "shared/guides/using-tailwind-css-in-react" - }, + "name": "Plugin Registry", + "description": "Browse official and community plugins", + "id": "registry", + "file": "", + "path": "/extending-nx/registry", + "isExternal": false + } + ] + }, + { + "name": "5 Min Tutorials", + "id": "tutorials", + "description": "Get started with plugins", + "itemList": [ { - "name": "React 18 Migration", - "id": "react-18", - "file": "shared/guides/react-18" + "name": "Create a Local Plugin", + "id": "create-plugin", + "file": "shared/plugins/create-plugin" }, { - "name": "Using Tailwind CSS with Angular projects", - "id": "using-tailwind-css-with-angular-projects", - "file": "shared/guides/using-tailwind-css-with-angular-projects" - }, + "name": "Maintain a Published Plugin", + "id": "publish-plugin", + "file": "shared/plugins/maintain-published-plugin" + } + ] + }, + { + "name": "Recipes", + "id": "recipes", + "description": "Focused instructions to complete a specific task", + "itemList": [ { - "name": "Using NgRx", - "id": "misc-ngrx", - "file": "shared/guides/misc-ngrx" + "name": "Write a Simple Executor", + "id": "local-executors", + "tags": ["use-task-executors"], + "file": "shared/recipes/plugins/local-executors" }, { - "name": "Using Data Persistence operators", - "id": "misc-data-persistence", - "file": "shared/guides/misc-data-persistence" + "name": "Compose Executors", + "id": "compose-executors", + "tags": ["use-task-executors"], + "file": "shared/recipes/plugins/compose-executors" }, { - "name": "Find the Last Successful Commit in Azure Pipelines", - "id": "azure-last-successful-commit", - "file": "shared/recipes/azure-last-successful-commit" + "name": "Write a Simple Generator", + "id": "local-generators", + "tags": ["use-code-generators"], + "file": "shared/recipes/generators/local-generators" }, { - "name": "Troubleshoot Cache Misses", - "id": "troubleshoot-cache-misses", - "tags": ["cache-task-results"], - "file": "shared/recipes/troubleshoot-cache-misses" + "name": "Compose Generators", + "id": "composing-generators", + "tags": ["use-code-generators"], + "file": "shared/recipes/generators/composing-generators" }, { - "name": "Export Project Graph", - "id": "export-project-graph", - "tags": ["explore-graph"], - "file": "shared/recipes/export-project-graph" + "name": "Provide Options for Generators", + "id": "generator-options", + "tags": ["use-code-generators"], + "file": "shared/recipes/generators/generator-options" }, { - "name": "Resolve Circular Dependencies", - "id": "resolve-circular-dependencies", - "tags": ["explore-graph"], - "file": "shared/recipes/resolve-circular-dependencies" + "name": "Create Files", + "id": "creating-files", + "tags": ["use-code-generators"], + "file": "shared/recipes/generators/creating-files" }, { - "name": "Include All package.json Files as Projects", - "id": "include-all-packagejson", - "tags": [], - "file": "shared/recipes/include-all-packagejson" + "name": "Modify Files", + "id": "modifying-files", + "tags": ["use-code-generators"], + "file": "shared/recipes/generators/modifying-files" }, { - "name": "Include Assets in Build", - "id": "include-assets-in-build", - "tags": [], - "file": "shared/recipes/include-assets-in-build" + "name": "Write a Migration", + "id": "migration-generators", + "tags": ["create-your-own-plugin"], + "file": "shared/recipes/plugins/migration-generators" }, { - "name": "Identify Dependencies Between Folders", - "id": "identify-dependencies-between-folders", - "tags": [], - "file": "shared/recipes/identify-dependencies-between-folders" + "name": "Create a Preset", + "id": "create-preset", + "tags": ["create-your-own-plugin"], + "file": "shared/recipes/plugins/create-preset" }, { - "name": "Rescope Packages from @nrwl to @nx", - "id": "rescope", - "tags": [], - "file": "shared/recipes/rescope" + "name": "Modify the Project Graph", + "id": "project-graph-plugins", + "tags": ["create-your-own-plugin", "explore-graph"], + "file": "shared/recipes/plugins/project-graph-plugins" }, { - "name": "Standalone NgRx APIs", - "id": "standalone-ngrx-apis", - "tags": [], - "file": "shared/recipes/standalone-ngrx-apis" + "name": "Identify Custom Projects", + "id": "project-inference-plugins", + "tags": ["create-your-own-plugin"], + "file": "shared/recipes/plugins/project-inference-plugins" } ] } ] }, { - "name": "Nx Cloud docs", + "name": "Nx Cloud", "id": "nx-cloud-documentation", "description": "Learn how to enable Distributed Tasks Executions, remote caching and more.", "itemList": [ @@ -1540,9 +1494,9 @@ ] }, { - "name": "On Prem", + "name": "Enterprise + On Prem", "id": "private-cloud", - "description": "Learn about Nx Cloud On Premise, dedicated Nx Cloud application hosted on your server, in your network with total private access.", + "description": "Learn about Nx Cloud Enterprise + On-Prem.", "itemList": [ { "name": "Get Started", @@ -1559,6 +1513,11 @@ "id": "auth-github", "file": "nx-cloud/private/auth-github" }, + { + "name": "On-Prem VM Setup", + "id": "ami-setup", + "file": "nx-cloud/private/ami-setup" + }, { "name": "Authenticate with GitLab", "id": "auth-gitlab", @@ -1578,16 +1537,6 @@ "name": "Advanced Configuration", "id": "advanced-config", "file": "nx-cloud/private/advanced-config" - }, - { - "name": "Kubernetes Setup", - "id": "kubernetes-setup", - "file": "nx-cloud/private/kubernetes-setup" - }, - { - "name": "Standalone", - "id": "standalone", - "file": "nx-cloud/private/standalone" } ] }, @@ -1625,6 +1574,13 @@ } ] }, + { + "name": "Changelog", + "id": "changelog", + "file": "", + "path": "/changelog", + "isExternal": true + }, { "name": "additional api references", "id": "additional-api-references", @@ -1693,13 +1649,13 @@ { "name": "format:check", "id": "format-check", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "file": "generated/cli/format-check" }, { "name": "format:write", "id": "format-write", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "file": "generated/cli/format-write" }, { @@ -1721,7 +1677,7 @@ { "name": "workspace-lint", "id": "workspace-lint", - "tags": ["enforce-project-boundaries"], + "tags": ["enforce-module-boundaries"], "file": "generated/cli/workspace-lint" }, { @@ -1970,6 +1926,20 @@ } ] }, + + { + "name": "playwright", + "id": "playwright", + "description": "Playwright package.", + "itemList": [ + { + "name": "Overview", + "id": "overview", + "path": "/packages/playwright", + "file": "shared/packages/playwright/playwright-plugin" + } + ] + }, { "name": "storybook", "id": "storybook", @@ -2018,6 +1988,12 @@ "description": "This guide explains how to customize the webpack configuration and your vite configuration for Storybook.", "file": "shared/packages/storybook/custom-builder-configs" }, + { + "id": "storybook-interaction-tests", + "name": "Setting up Storybook Interaction Tests with Nx", + "description": "This guide explains how you can set up Storybook interaction tests on your Nx workspace.", + "file": "shared/packages/storybook/interaction-tests" + }, { "id": "storybook-composition-setup", "name": "Setting up Storybook Composition with Nx", @@ -2067,6 +2043,12 @@ "name": "The `enforce-module-boundaries` rule", "path": "/packages/eslint-plugin", "file": "shared/packages/linter/enforce-module-boundaries" + }, + { + "id": "dependency-checks", + "name": "The `dependency-checks` rule", + "path": "/packages/eslint-plugin", + "file": "shared/packages/linter/dependency-checks" } ] }, diff --git a/docs/nx-cloud/intro/nx-cloud.md b/docs/nx-cloud/intro/nx-cloud.md index b43a759c7652f..9a02c9718bb21 100644 --- a/docs/nx-cloud/intro/nx-cloud.md +++ b/docs/nx-cloud/intro/nx-cloud.md @@ -2,15 +2,15 @@ Nx partitions a command into smaller tasks and runs them in parallel, in the correct order. Nx Cloud takes it one step further and [runs any command across multiple machines](/core-features/distribute-task-execution), while giving you a consolidated view of the command as if it ran locally. -Nx caches the output of any previously run command such as testing and building, so it can replay the cached results instead of rerunning it. Nx Cloud allows you to [share the computation cache](/core-features/share-your-cache) across everyone in your team and CI. +Nx caches the output of any previously run command such as testing and building, so it can replay the cached results instead of rerunning it. Nx Cloud allows you to [share the computation cache](/core-features/remote-cache) across everyone in your team and CI. And it takes five minutes to set up. {% personas %} -{% persona type="cache" title="Share Your Cache" url="/core-features/share-your-cache" %} +{% persona type="cache" title="Share Your Cache" url="/core-features/remote-cache" %} Share the computation cache across CI and developer machines -- [Set up distributed caching](/core-features/share-your-cache) +- [Set up distributed caching](/core-features/remote-cache) {% /persona %} diff --git a/docs/nx-cloud/private/ami-setup.md b/docs/nx-cloud/private/ami-setup.md new file mode 100644 index 0000000000000..6adaad9105a5f --- /dev/null +++ b/docs/nx-cloud/private/ami-setup.md @@ -0,0 +1,170 @@ +# Setting up a dedicated NxCloud VM + +## AWS EC2 + +1. Login to your AWS Console and select [the top image published here](https://console.aws.amazon.com/ec2/v2/home?home#Images:visibility=public-images;imageName=nx-cloud;owner=623002322076;sort=desc:imageName) +2. Launch a new instance from that AMI +3. Recommended instance type: `t3.2xlarge` +4. You will need to SSH into the instance once it's created: + - Use an existing SSH key-pair that you already have installed locally. + - [Or create a new one and download the keys locally](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html?icmpid=docs_ec2_console#having-ec2-create-your-key-pair) + - Then select your new SSH pair from the list +5. Networking: + - Allow the instance to receive HTTP and HTTPS traffic + - Allow SSH from your current IP +6. Leave the storage options as they are +7. "Launch instance" +8. Wait 10 minutes, then navigate to your instance's IP in the browser. You should see the NxCloud dashboard! + +![NxCloud landing page](/nx-cloud/private/images/nx-cloud-landing.png) + +### Your NxCloud URL + +1. At this point, your instance will have a public IP accessible from the browser. + - You can consider this IP the URL of NxCloud, and proceed with the below steps and all will work fine! +2. You might want, however, to add a Load Balancer in front of the instance, with an explicit domain (e.g. https://my-nxcloud.my-org.com). + - This is strongly recommended because you will be able to upgrade/restart/re-configure your NxCloud EC2 instance while keeping the NxCloud URL static. + - Create an [application load balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html) + - You will need to create a certificate for your domain to assign to the LB + - And you will need to target your EC2 instance from the LB + - You should now have a permanent domain pointing to your NxCloud instance + +Once you have your NxCloud URL proceed to the below steps! + +### Configuring your NxCloud instance + +1. Create a new `myconfiguration.yaml` file with the below contents + +```yaml +# This is all you need to get the baseline of your nx-cloud instance configured! + +# Set the external URL your instance is running on. This is the URL from the previous step +nxCloudAppURL: 'https://nx-cloud.on.my-domain.ca' + +secret: + # set your initial admin password for logging into the app + adminPassword: 'correcthorsebatterystaple' +``` + +2. Apply the configuration: + +```bash +scp -i ./.pem -r ./myconfiguration.yaml nx-cloud@:~/config/user/update.yaml +``` + +That's it! After a few minutes, you should be able to log-in with: + +- username: `admin` +- password: `` + +### Applying the license + +Once you log-in, you will see an organisation has been created for you. + +1. You can rename it or create a new organization. +2. Navigate to your new organization's page and send us it's id + - It should look something like this: https://your-url.com/orgs/649f240f7fb955000c1fd10b/workspaces +3. We will then give you a License Key which you can apply on your org's billing page + +### Connecting to your NxCloud instance + +In your Nx workspace, you can enable NxCloud by running: + +```bash +NX_CLOUD_API="https://nx-cloud.on.my-domain.ca" npx nx connect +``` + +If it doesn't work, there might be an issue with unrecognized certificates on your instance. You can try running with: + +```bash +NODE_TLS_REJECT_UNAUTHORIZED=0 NX_CLOUD_API="https://nx-cloud.on.my-domain.ca" npx nx connect +``` + +Although we have [a full guide here](https://github.com/nrwl/nx-cloud-helm/blob/main/PROXY-GUIDE.md#nxcloud-runner-proxy-issues) for dealing with self-signed certificates. + +### Advanced configuration and auth + +You can optionally enable authentication using your preferred SSO provider: + +- GitHub +- Bitbucket +- GitLab +- SAML (Okta, Azure AD etc.) + +```yaml +# This is all you need to get the baseline of your nx-cloud instance configured! + +# only use this if you'd like to use any of the newer NxCloud version from here: https://nx.dev/nx-cloud/reference/release-notes#docker-containers +# global.imageTag: '' + +# Set the external URL your instance is running on +nxCloudAppURL: 'https://nx-cloud.on.my-domain.ca' + +# Uncomment (along with github secrets below) to enable working with GitHub pull requests or github auth +#github: +# auth: +# enabled: false +# pr: +# apiUrl: '' # this is only needed if you have a self-hosted github instance + +#gitlab: +# apiUrl: '' # this is only needed if you have a self-hosted gitlab instance +# auth: +# enabled: false + +# we do not support self-hosted bitbucket instances +#bitbucket: +# auth: +# enabled: false + +#saml: +# auth: +# enabled: false + +# Provide plaintext values for your application to use. We will extract them, +# store them within the application runtime, and scrub the plaintext ones from +# the filesystem +secret: + # set your initial admin password for logging into the app + # see here: https://nx.dev/nx-cloud/private-cloud/auth-single-admin + adminPassword: 'correcthorsebatterystaple' + + # If you want to enable GitHub Login, just provide your client id & secret, we handle the rest + # see here: https://nx.dev/nx-cloud/private-cloud/auth-github + githubAuthClientId: 'my_client_id' + githubAuthClientSecret: 'my_client_secret' + + # The same goes for GitLab authentication + # see here: https://nx.dev/nx-cloud/private-cloud/auth-gitlab + # gitlabAppId: 'my_gitlab_app_id' + # gitlabAppSecret: 'my_gitlab_app_secret' + + # Bitbucket too! If these are uncommented, BB auth is automatically enabled + # see here: https://nx.dev/nx-cloud/private-cloud/auth-bitbucket + # bitbucketAppId: 'bitbucket_app_id' + # bitbucketAppSecret: 'bitbucket_app_secret' + + # SAML auth + # see here: https://nx.dev/nx-cloud/private-cloud/auth-saml + # samlEntryPoint: 'your_saml_entry_point' + # samlCert: 'saml_cert' +``` + +### Upgrades + +We send out emails with every new NxCloud release to all our Enterprise customers: + +1. You can view your current version at the `/version` route: https://your-nx-cloud-url.com/version +2. [And these are the latest NxCloud releases](https://nx.dev/nx-cloud/reference/release-notes#docker-containers) + +To upgrade to a newer version, add the below line to your `myconfiguration.yml` file: + +```yaml +global.imageTag: '2306.01.2' # set the version of nx-cloud you'd like +``` + +And apply the changes: + +```bash +scp -r ./myconfiguration.yaml nx-cloud@:~/config/user/update.yaml +``` diff --git a/docs/nx-cloud/private/get-started.md b/docs/nx-cloud/private/get-started.md index 5348dfb5be42c..f24f788548710 100644 --- a/docs/nx-cloud/private/get-started.md +++ b/docs/nx-cloud/private/get-started.md @@ -1,23 +1,62 @@ -# Running Nx Cloud on Prem +# Running Nx Cloud Enterprise -Nx Cloud can be deployed to your cloud, which gives you full control of your data, with no external API calls. +We offer multiple ways of running NxCloud for our Enterprise customers. The below options are listed in recommended order, from easiest to most complex in +terms of set-up and maintenance for your team. Please carefully consider your organization's requirements and level of infrastructure expertise before deciding on +a deployment option. -This solution is included as part of the Nx Enterprise package. You can learn more about it at [nx.app/enterprise](https://nx.app/enterprise). +Also, please make sure to [get in touch with us first](https://nx.app/enterprise?utm_source=nx.dev) so we can start creating an Enterprise package +that best fits your needs, and discuss any questions you might have! -Nx Cloud can be deployed in two ways: +## Clusters managed by us -- Using Kubernetes (several containers working together) -- Using a single standalone container (NOT RECOMMENDED) +### Multi-tenant -The flags and the capabilities are the same between the two, but the Kubernetes setup is more robust and better -documented. +The quickest way and easiest way to get up and running with NxCloud is using one of our existing secure, multi-tenant managed clusters: + +- https://nx.app/ +- Or, if you'd like all of your data to be hosted in Europe, you can use https://eu.nx.app/ + +You get the same level of security, dedicated support, SSO/SAML auth options and predictable seat-based pricing as all our other hosting options, but you won't have +to manage the instance yourself. + +We also offer an uptime SLA guarantee of 99.98% for our Enterprise customers, SOC certificates on request, and we're happy to meet with your security teams if they +have questions, or fill in security questionnaires. We also maintain a [Status Page here](https://status.nx.app/). + +To start with this option, it's as easy as running `npx nx connect` in your Nx workspace! + +### Single-tenant instance + +If you have very specific requirements, then we can also offer to host NxCloud for you in an isolated/single-tenant cluster. + +We'll be able to discuss specific requirements such as: + +- Specific regions you want your data to be in +- Network isolation / dedicated VPCs +- Dedicated instances +- Storage encryption +- Storage replication / redundancy + +This would be a "best of both worlds" option, as it would free you up from managing the instance yourself, but you will get to define specific parameters of how it should it run. +Your data and the NxCloud will run in complete isolation and will only serve your company. There will be no external API calls to any services outside of the cluster we set-up for you. + +Once you let us know you'd like this option, depending on the agreed requirements, it might take a few days to get it set up. + +## On-prem, managed by your organization + +#### Self-contained VM + +If you would like to host NxCloud yourself, within your organization's infrastructure, the easiest way to set it up is as a self-contained VM. + +Refer to our ["Self-contained VM" guide](/nx-cloud/private-cloud/ami-setup) for instructions on running NxCloud on Amazon EC2. + +#### Multi-node setup with Kubernetes + +The options above remove most of the maintenance burden required on your part, so we strongly recommend them! They also don't require too much infrastructure expertise. + +We do offer, however, a multi-node Kubernetes setup, that is deployed via Helm. You can head over to our [Helm repository](https://github.com/nrwl/nx-cloud-helm/) to explore this option. ## Resources -- [Kubernetes Setup Instructions](/nx-cloud/private-cloud/kubernetes-setup) -- [Nx Cloud K8s Example + All Config Options](https://github.com/nrwl/nx-cloud-helm) -- [Nx Cloud K8s Example + All Config Options (no Helm)](https://github.com/nrwl/nx-cloud-helm/tree/main/no-helm) -- [Standalone Container](/nx-cloud/private-cloud/standalone) - [GitHub PR Integration](/nx-cloud/set-up/github) - [Auth (Basic)](/nx-cloud/private-cloud/auth-single-admin) - [GitHub Auth](/nx-cloud/private-cloud/auth-github) diff --git a/docs/nx-cloud/private/images/nx-cloud-landing.png b/docs/nx-cloud/private/images/nx-cloud-landing.png new file mode 100644 index 0000000000000..f5d3d9dcc0e43 Binary files /dev/null and b/docs/nx-cloud/private/images/nx-cloud-landing.png differ diff --git a/docs/nx-cloud/private/kubernetes-setup.md b/docs/nx-cloud/private/kubernetes-setup.md deleted file mode 100644 index 330e694d79fe7..0000000000000 --- a/docs/nx-cloud/private/kubernetes-setup.md +++ /dev/null @@ -1,282 +0,0 @@ -# Set Up Nx Cloud on Kubernetes - -A lot of organizations deploy Nx Cloud to Kubernetes. - -This guide references the [nx-cloud-helm](https://github.com/nrwl/nx-cloud-helm) repo which contains: - -- Nx Cloud Helm Chart -- Instructions on how to install Nx Cloud using Helm -- Instructions on how to install Nx Cloud using kubectl. See [here](https://github.com/nrwl/nx-cloud-helm/blob/main/no-helm/README.md). - -## Deployments on AWS/EKS - -If you're deploying on EKS, check out our [AWS Guide](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/AWS-GUIDE.md). Otherwise, continue reading below. - -## Installing Using Helm - -Steps: - -1. Deploy MongoDB Kubernetes Operator - - using helm: https://github.com/mongodb/helm-charts - - using kubectl: https://github.com/mongodb/mongodb-kubernetes-operator -2. Create a mongodb replica set -3. Create a secret -4. Install Nx Cloud using helm - -### Step 1: Deploy MongoDB Kubernetes Operator - -If you are using a hosted MongoDB installation (e.g., Mongo Atlas or CosmosSB, or you are running one yourself), you can -skip steps 1 and 2. - -``` -> helm repo add mongodb https://mongodb.github.io/helm-charts -> helm install community-operator mongodb/community-operator -``` - -### Step 2: Deploy a MongoDB replica set - -``` -> kubectl apply -f examples/mongodb.yml -``` - -This will create a secret. You can get the value of the secret as follows: - -> kubectl get secret cloud-mongodb-nrwl-api-admin-user -o go-template='{{range $k,$v := .data}}{{"### "}}{{$k}}{{"n"}}{{$v|base64decode}}{{"nn"}}{{end}}' - -You might need to wait a bit for the Pods to be created before this secret will be available. - -The output of the command can be a bit confusing (you are only interested in the second part of the output). The default connection string for the Mongo Community Operator will look like -this: `mongodb+srv://admin-user:DB_PASSWORD@cloud-mongodb-svc.default.svc.cluster.local/nrwl-api?replicaSet=cloud-mongodb&ssl=false` -. You should be able to use this value. - -Take this connection string and paste it into your `examples/secret.yml`, replacing the placeholder value. - -### Step 3: Create a secret - -With the values updated, create a secret by running `kubectl apply -f examples/secret.yml` - -### Step 4: Install Nx Cloud using helm - -``` -> helm repo add nx-cloud https://nrwl.github.io/nx-cloud-helm -> helm install nx-cloud nx-cloud/nx-cloud --values=overrides.yml -``` - -`examples/overrides` contains the min overrides files. You need to provision: - -1. The image tag you want to install -2. `nxCloudAppURL` which is the url used to access ingress from CI and dev machines ( - e.g., `https://nx-cloud.myorg.com`). -3. `secret/name` the name of the secret you created in Step 3. -4. `secret/nxCloudMongoServerEndpoint`, the name of the key from the secret. - 5`secret/adminPassword`, the name of the key from the secret. - -If you only applied the secret from Step 3, the only thing you will need to change is `nxCloudAppURL`. - -## Cloud Containers - -The installation will create the following: - -1. nx-cloud-frontend (deployment) -2. nx-cloud-api (deployment) -3. nx-cloud-nx-api (deployment) -4. nx-cloud-file-server (deployment) -5. nx-cloud-aggregator (cron job) - -## Ingress, IP, Certificates - -You can configure Ingress. For instance, the following will see the ingress class to 'gce', the global static ip name -to 'nx-cloud-ip', and will set a global Google managed certificate. - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -ingress: - class: 'gce' - globalStaticIpName: 'nx-cloud-ip' - managedCertificates: 'cloud-cert' - -secret: - name: 'cloud' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - adminPassword: 'ADMIN_PASSWORD' -``` - -This configuration will look different for you. You will have a different global static ip and your cert name will also -be different. If you are interested in creating the two using GKE, check out the following links: - -- [Reserving a static external IP address](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address) -- [Using Google-managed SSL certificates](https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs) - -If you aren't using GKE, `ingress.class` will also be different. For example, see [our example config for AWS](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/helm-values.yml#L7) or check out the AWS Load Balancer set-up section [here for AWS set-up instructions.](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/AWS-GUIDE.md#3-install-a-load-balancer) - -If you need to have a detailed Ingress configuration, you can tell the package to skip defining ingress: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -ingress: - skip: true -``` - -⤵️ and then define it yourself - -```yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: nx-cloud-ingress - annotations: - - labels: - app: nx-cloud -spec: - rules: - - http: - paths: - # define the next /file section only if you use the built-in file server - - path: /file - pathType: Prefix - backend: - service: - name: nx-cloud-file-server-service - port: - number: 5000 - - path: /nx-cloud - pathType: Prefix - backend: - service: - name: nx-cloud-nx-api-service - port: - number: 4203 - - path: /api - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /graphql - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /auth - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /download - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /download - - pathType: Prefix - backend: - service: - name: nx-cloud-frontend-service - port: - number: 8080 -``` - -### Step 5: Connect Your Workspace - -Run `NX_CLOUD_API=https://nx-cloud.myorg.com nx connect`. Click on the link to connect the workspace -to your admin account. - -## Variations - -### External File Storage - -If you use AWS or Azure, you can configure Nx Cloud to store cached artifacts on S3 or Azure Blob. In this case, you -won't need the PVC or the file-server container. S3 and Azure Blob also tend to be faster. - -For S3 buckets, see the [AWS Guide](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/AWS-GUIDE.md#6-external-s3-access) - -For Azure: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -azure: - enabled: true - container: 'nx-cloud' - -secret: - name: 'cloudsecret' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - adminPassword: 'ADMIN_PASSWORD' - azureConnectionString: 'AZURE_CONNECTION_STRING' -``` - -Note that the secret for setting up Azure must contain `AZURE_CONNECTION_STRING`. - -### GitHub Auth - -To use GitHub for user authentication, you can use the following configuration: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -github: - auth: - enabled: true - -secret: - name: 'cloudsecret' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - githubAuthClientId: 'GITHUB_AUTH_CLIENT_ID' - githubAuthClientSecret: 'GITHUB_AUTH_CLIENT_SECRET' -``` - -Note that the secret must contain `GITHUB_AUTH_CLIENT_ID` and `GITHUB_AUTH_CLIENT_SECRET`. -Read [here](https://nx.dev/nx-cloud/private-cloud/auth-github) on how to get those values. - -### GitHub Integration - -To enable the GitHub PR integration, you can use the following configuration: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -github: - pr: - enabled: true - # apiUrl: '' uncomment when using github enterprise - -secret: - name: 'cloudsecret' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - githubWebhookSecret: 'GITHUB_WEBHOOK_SECRET' - githubAuthToken: 'GITHUB_AUTH_TOKEN' -``` - -Note that the secret must contain `GITHUB_WEBHOOK_SECRET` and `GITHUB_AUTH_TOKEN`. -Read [here](https://nx.dev/nx-cloud/private-cloud/github) on how to get those values. - -## More Information - -You can find more information about Nx Cloud and running it on -prem [here](https://nx.dev/nx-cloud/private-cloud/get-started). diff --git a/docs/nx-cloud/private/standalone.md b/docs/nx-cloud/private/standalone.md deleted file mode 100644 index 7f1b34491aa87..0000000000000 --- a/docs/nx-cloud/private/standalone.md +++ /dev/null @@ -1,315 +0,0 @@ -# Running a Standalone Container - -Nx Cloud can be deployed in two ways: - -- [Using Kubernetes](https://github.com/nrwl/nx-cloud-helm) (several containers working together) -- Using a single standalone container (NOT RECOMMENDED) - -The flags and the capabilities are the same between the two, but the Kubernetes setup is more robust and better -documented. This document covers the latter version. - -**Nx Cloud consists of 3 parts:** - -1. The stateless Nx Cloud service -2. MongoDB database -3. File server - -By default, the container created by the `nxprivatecloud/single-image` image will create two of them: the stateless Nx Cloud service, and the file server. Using a single container is the easiest way to set it up, but it isn't the most robust way to run Nx Cloud. - -You will then need to host the database separately: - -- Either by using a service such as Mongo Atlas -- Or running it yourself. For that, we created the `nxprivatecloud/nx-cloud-mongo` image. - -The instructions will go through running the embedded file server, and then, at the end, will talk about hosting your cached artefacts on an external service, such as Amazon S3. - -## Running Nx Cloud - -### Step 1: Pull the Image - -```shell -> docker pull nxprivatecloud/single-image -``` - -To update the version of Nx Cloud, pull the new version of the image and run it against the same mount (see -below). - -### Step 2: Create a Container - -Depending on how your infrastructure is set up, you can either run Nx Cloud using HTTPS or HTTP. If you have a -proxy/load-balancer in front of Nx Cloud, you will likely want to run Nx Cloud using HTTP (the -proxy/load-balancer will handle TLS). Otherwise, you will likely want to run Nx Cloud using HTTPS. - -**To create a container:** - -1. You will need to create a directory on the host machine where data will be stored. (_This is not necessary if you are - running the file server separately. See below._) -2. You will need to know the URL that the Nx Cloud installation can be accessed by (see `NX_CLOUD_APP_URL` below). - - `NX_CLOUD_APP_URL` should be accessible from your CI and dev machines. - - `NX_CLOUD_APP_URL` can be set with an HTTP or HTTPS url. In a case where you are using a proxy/load-balancer, you - can still put HTTPS (the url will be resolved by the proxy before hitting the app). - - `NX_CLOUD_APP_URL` is likely to be an external IP/domain of the load balancer. -3. If you are running Nx Cloud using HTTPS, you need to generate or obtain an SSL certificate and an SSL private - key. - -**Once you obtain all the needed information, you can run the following:** - -**Using HTTPS** - -```shell -> docker create --name cloud \ - - -p 443:8081 \ - -e CERT_KEY="$(cat ./tools/certs/key.pem)" \ - -e CERT="$(cat ./tools/certs/cert.pem)" \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -**Using HTTP (no proxy)** - -```shell -> docker create --name cloud \ - - -p 80:8081 \ - -e NX_CLOUD_APP_URL="http://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -**Using HTTPS via proxy** - -```shell -> docker create --name cloud \ - -p 80:8081 \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -**Let's see what those options mean:** - -- `443:8081` maps the internal port 8081 to 443, so it can be accessed in the browser without specifying the port. 80: - 8081 works the same way when you use HTTP instead of HTTPS. -- `CERT_KEY` and `CERT` contain the values of private key and cert. The file extensions of the cert and key files can be - different, but as long as they are in the PEM format (which is the case if you use, for instance, OpenSSL), the - command will work. -- `NX_CLOUD_APP_URL` is the URL the cloud can be accessed by (e.g., `https://nxcloud.privateurl.com`). **Important: - Unless you are experimenting, it won't be localhost. It has to be the URL that your CI and your developer machine can - reach. Also note, there is no trailing slash in the URL.** -- `ADMIN_PASSWORD` contains the password of the admin user. The admin user is created the first time you run cloud, you - can remove this env variable after that. Instead of an admin password, you can also - follow [the instructions here](/nx-cloud/private-cloud/auth-github) to set up GitHub auth. -- `-v /data/private-cloud:/data` sets up the volume where the data (the cached artefacts) is stored. `/data/private-cloud` refers to a folder - on your machine, `/data` is the shareable folder from the Docker image. - -### Step 3: Run the Container - -Once you create the container, you can start it using: - -```shell -> docker start cloud -``` - -Imagine `NX_CLOUD_APP_URL` is set to `https://nxcloud.privateurl.com`. - -Now, go to https://nxcloud.privateurl.com to see cloud running. You can log into the account -using `admin/ADMIN_PASSWORD`. - -### Step 4: Connect Your Workspace - -Run `NX_CLOUD_API=https://nxcloud.privateurl.com` nx connect. Click on the link to connect the workspace -to your admin account. - -### Optional step 5: set up GitHub auth - -Follow the [instructions here](/nx-cloud/private-cloud/auth-github) to set up GitHub OAuth authentication so you can -invite other members in your team to the workspace. - -### Optional step 6: set up GitHub Pull Request integration - -You can [optionally configure Nx Cloud](/nx-cloud/set-up/github) to post build stats directly on your GitHub -pull requests. - -### Optional step 7: Setting Up Proxy - -If your container cannot access `api.nrwl.io` directly and has to talk via a proxy, you can -add `-e HTTPS_PROXY="https://myproxy.myorg.com"` to the container creation command. - -## Running the Mongo Database - -Nx Cloud uses MongoDB to store its metadata. You will need to provision the `NX_CLOUD_MONGO_SERVER_ENDPOINT` env variable when -creating a container, like so: - -```shell --e NX_CLOUD_MONGO_SERVER_ENDPOINT="mongodb://domain-with-mongo:27017/nrwl-api" -``` - -By default, Nx Cloud requires Mongo 4.2+. If you are using an older version of Mongo (for instance, if you are using -Cosmos DB), please add - -```shell --e NX_CLOUD_USE_MONGO42=false -``` - -### Deploy Mongo on your Kubernetes engine or Docker VM - -See [here](https://github.com/nrwl/nx-cloud-helm/blob/main/MONGO-OPERATOR-GUIDE.md) for a full guide on running Mongo yourself. - -### Using CosmosDB - -If you are deploying to Azure, you might have access to CosmosDB. See here for more information. - -### Using Mongo Atlas - -[Mongo Atlas](https://mongodb.com/) is a great option for deploying MongoDB. - -## Using External File Storage - -By default, Nx Cloud is going to start a file server and store the cached artifacts in the provided volume. But -you can also configure Nx Cloud to use an external file storage. At the moment, only S3 and Azure Blob are -supported. - -### Using S3/Minio - -To configure S3 as a file storage, provision the `AWS_S3_ACCESS_KEY_ID`, `AWS_S3_SECRET_ACCESS_KEY`, and `AWS_S3_BUCKET` -env variables when creating the Nx Cloud docker container, like so: - -```shell --e AWS_S3_ACCESS_KEY_ID="SOMEKEY" --e AWS_S3_SECRET_ACCESS_KEY="SOMESECRETKEY" --e AWS_S3_BUCKET="nx-cache-bucket-name" -``` - -If you are using an accelerated bucket, add: `-e AWS_S3_ACCELERATED=true` - -If you are using a local S3 installation (e.g., Minio), you can set the endpoint as follows: - -```shell --e AWS_S3_ENDPOINT="https://local-installation.myorg.com" --e AWS_S3_ACCESS_KEY_ID="SOMEKEY" --e AWS_S3_SECRET_ACCESS_KEY="SOMESECRETKEY" --e AWS_S3_BUCKET="nx-cache-bucket-name" -``` - -{% callout type="note" title="On cache item expiration time" %} -Remember to -set [a cache item expiration time](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html) -. The default is currently 4 weeks. If you would like to keep items for longer, for example for 8 weeks, please remember -to set the `NX_CACHE_EXPIRATION_PERIOD_IN_DAYS=56` env variable as well, so the container knows when to expire the Mongo -cache entries as well. -{% /callout %} - -### Using Azure - -To configure Azure Blob as a file storage, provision the `AZURE_CONNECTION_STRING`, `AZURE_CONTAINER` env variables when -creating the Nx Cloud docker container, like so: - -```shell --e AZURE_CONNECTION_STRING="SOME-CONNECTION-STRING" --e AZURE_CONTAINER="files" -``` - -To obtain the `AZURE_CONNECTION_STRING` value go to your "Storage Account" and click on "Access Keys". You will also -need to create a container in your storage account before starting the Nx Cloud container. - -If you use an external file storage solution, you don't have to provision the volume. - -{% callout type="note" title="Cache expiration time" %} -See note above about setting a cache expiration time. For Azure blob -storage, [see this guide](https://docs.microsoft.com/en-us/azure/cdn/cdn-manage-expiration-of-blob-content). -{% /callout %} - -## Configure Memory Limits - -By default, the Nx Cloud container is configured to run on an instance with 8GB of RAM. - -If you have a container with 4GB of RAM, you can decrease the memory limits by setting the following env variables: - -- `NX_CLOUD_FILE_SERVER_MEMORY_LIMIT=500` -- `NX_CLOUD_API_MEMORY_LIMIT=800` - -Example: - -```shell -> docker create --name cloud \ - -p 80:8081 \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -e NX_CLOUD_FILE_SERVER_MEMORY_LIMIT=500 \ - -e NX_CLOUD_API_MEMORY_LIMIT=800 \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -The right amount of RAM depends heavily on how you run Nx Cloud. - -- The `NX_CLOUD_FILE_SERVER_MEMORY_LIMIT` value is only relevant if you use the built-in file server. - -For instance, if you use S3 to store the cached artifacts, even 2GB might be sufficient. You can set the following limit: - -- `NX_CLOUD_API_MEMORY_LIMIT=800` - -If you run everything in the Nx Cloud container, then 5GB is much preferred. - -## Configure Artifact Expiration When Using Built-in File Server - -By default, the Nx Cloud container is going to remove cached artifacts after two weeks. You can change it by setting `NX_CACHE_EXPIRATION_PERIOD_IN_DAYS` when starting the container. - -Example: - -```shell -> docker create --name cloud \ - -p 80:8081 \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -e NX_CACHE_EXPIRATION_PERIOD_IN_DAYS=5 \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -## Self-Signed Certificates - -If you have a self-signed certificate, you will have to provision `NODE_EXTRA_CA_CERTS`. The env variable should point to a PEM file with either your certificate, or the root certificate your certificate was created from. Though this can be accomplished with a CLI command like `NODE_EXTRA_CA_CERTS=./tools/certs/cert.crt nx test myapp`, you will most likely want to configure it as a global env variable (for instance in your `.bashrc` file). - -A self-sign certificate registered in your OS won't be picked up by Node. Node requires you to provision `NODE_EXTRA_CA_CERTS`. - -## Migration guide from `nxprivatecloud/nxcloud` to `nxprivatecloud/single-image` - -The old version of our Docker image, `nxprivatecloud/nxcloud`, is no longer being maintained. This section will explain how to migrate to the new standalone image, `nxprivatecloud/single-image`. - -Unlike `nxprivatecloud/nx-cloud`, the `nxprivatecloud/single-image` container does not come with MongoDB included. This makes for a much simpler image, based on Alpine (and not Ubuntu), with less chances for security vulnerabilities. However, it does require you to connect to an external Mongo instance. Below we'll cover the two possible migration scenarios. - -#### You are connecting to an external Mongo instance - -If you are currently connecting to an external Mongo instance, then migrating to the new image is as simple as switching the Docker tag from `nxprivatecloud/nxcloud` to `nxprivatecloud/single-image`. All the other configuration options can stay the same. - -#### You are running Mongo inside the Docker image - -If you are currently relying on the image to host Mongo, we will need to move that to an external instance. - -##### Starting fresh with a dedicated Mongo instance - -1. We recommend setting up a dedicated Mongo host, on Atlas [as described above](#using-mongo-atlas). This means you will lose you current workspace set-up, but it is the easiest migration path and the most maintanable one. - 1. To do this, get the connection string from Mongo Atlas - 2. And configure the image with it: `-e NX_CLOUD_MONGO_SERVER_ENDPOINT="mongodb://domain-with-mongo:27017/nrwl-api"` - 3. That's it! -2. If you cannot use Atlas or Azure CosmosDB within your org, then you'll need to run our dedidcated Mongo Docker image. Instructions for this approach are described below. - -##### Migrating your data to a separate self-hosted Mongo instance - -1. When running the image, you are probably mapping to the host volume like this `-v /data/private-cloud:/data:Z` -2. That data folder is where the image stores all its persistent data that needs exist between restarts or updates of the image. Inside it you'll find: - - 1. In the old image (`nxprivatecloud/nx-cloud`): - 1. `/data/file-server`: if you are using the built-in file-server, this is where you'll find all the cached artefacts. If you are using an external S3 buckets this folder won't exist. - 2. `/data/mongo`: this is where Mongo stores all its files. - 2. In the new image (`nxprivatecloud/single-image`): - 1. `/data/file-server` (if using the built-in file-server, otherwise you don't need to map anything) - -3. Copy the contents of `/data/mongo` folder from the host where you previously used to run Mongo, to the new host where you'll run the dedicated Mongo image -4. Run Mongo as described [here](https://github.com/nrwl/nx-cloud-helm/blob/main/MONGO-OPERATOR-GUIDE.md) - 1. In there, you'll find instructions to map the `$PWD/mongo-data:/data/db` folder to your host - 2. Copy the data from Step 1. above into the new mapped folder above. -5. Get the connection string for the above image -6. Start your `nxprivatecloud/single-image` container with the `-e NX_CLOUD_MONGO_SERVER_ENDPOINT="mongodb://52.201.253.213:27017/?authSource=admin&directConnection=true"` env var -7. You can remove the `/data/mongo` folder from the `single-image` mapping (you will need to keep `/data/file-server` if you not using an external S3 bucket) diff --git a/docs/nx-cloud/reference/release-notes.md b/docs/nx-cloud/reference/release-notes.md index 110747b9b3567..fed79301446dd 100644 --- a/docs/nx-cloud/reference/release-notes.md +++ b/docs/nx-cloud/reference/release-notes.md @@ -98,6 +98,11 @@ Cleanup: Handle issues with the network and the api in a consistent fashion. # Docker Containers +## 2306.01.2.patch3 + +- Fixes an issue with multiple admin organizations being created on new installations +- Fixes an issue where Enterprise licenses could not be applied on some new orgs + ## 2306.01.2.patch2 - Fixes an issue with the `single-image` container where the aggregation would block the API from starting up @@ -155,7 +160,7 @@ If you need assistance, please get in touch at [cloud-support@nrwl.io](mailto:cl On May 16th, 2023 we announced our plans to sunset the Community Edition of NxCloud On-Prem to align with our new pricing plans. If you are on the Community Edition, please follow these steps to migrate: -1. Use this image: `2306.01.2` +1. Use this image: `2306.01.2.patch3` 2. Switch to private Enterprise by setting `NX_CLOUD_MODE=private-enterprise` (or `mode: 'private-enterprise'` if using Helm). 3. Reach out to us at [cloud-support@nrwl.io](mailto:cloud-support@nrwl.io). You will get a FREE, unlimited-use coupon for the next 3 months so you can trial Nx Enterprise. diff --git a/docs/nx-cloud/set-up/bitbucket-cloud.md b/docs/nx-cloud/set-up/bitbucket-cloud.md index af3b57d04865a..d40e4f75ee1a5 100644 --- a/docs/nx-cloud/set-up/bitbucket-cloud.md +++ b/docs/nx-cloud/set-up/bitbucket-cloud.md @@ -26,4 +26,10 @@ For example, the url `https://bitbucket.org/nrwl/large-monorepo/src/main/` has a To use an app password for authentication, one must be generated with proper permissions. The minimum required permissions are write access to PRs. +![Create App Password](/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp) + Once the app password is created, verify the username is correct, paste the value, and then click "Connect". This will verify that Nx Cloud can connect to your repo. Upon a successful test, your configuration is saved, and setup is complete. + +{% callout type="note" title="Use the correct username" %} +Make sure that you are using your Bitbucket username, found on the [account settings](https://bitbucket.org/account/settings) screen, and not your email address. +{% /callout %} diff --git a/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.png b/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.png deleted file mode 100644 index a438b328dca61..0000000000000 Binary files a/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.png and /dev/null differ diff --git a/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp b/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp new file mode 100644 index 0000000000000..8a498eacdac5f Binary files /dev/null and b/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp differ diff --git a/docs/shared/angular-standalone-tutorial/1-code-generation.md b/docs/shared/angular-standalone-tutorial/1-code-generation.md index 1d9bc4ff0a1f8..d760a42289742 100644 --- a/docs/shared/angular-standalone-tutorial/1-code-generation.md +++ b/docs/shared/angular-standalone-tutorial/1-code-generation.md @@ -10,9 +10,9 @@ This tutorial sets up a repo with a single application at the root level that br {% youtube src="https://www.youtube.com/embed/LYPVrWQNnEc" title="Tutorial: Standalone Angular Application" -width="100%" /%} +/%} -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-angular-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/angular-standalone" /%} # Angular Standalone Tutorial - Part 1: Code Generation diff --git a/docs/shared/angular-standalone-tutorial/4-task-pipelines.md b/docs/shared/angular-standalone-tutorial/4-task-pipelines.md index 19d76a19e852b..df922c174cd8b 100644 --- a/docs/shared/angular-standalone-tutorial/4-task-pipelines.md +++ b/docs/shared/angular-standalone-tutorial/4-task-pipelines.md @@ -121,7 +121,7 @@ When you run a task, Nx uses the inputs for your task to create a hash that is u If this index does not exist, Nx runs the command and if the command succeeds, it stores the result in the cache. -{% card title="More On Customizing Inputs" description="See the Customizing Inputs Guide for more details on how to set inputs for your tasks." url="/more-concepts/customizing-inputs" /%} +{% card title="More On Customizing Inputs" description="See the Customizing Inputs Guide for more details on how to set inputs for your tasks." url="/concepts/more-concepts/customizing-inputs" /%} ### Outputs diff --git a/docs/shared/angular-standalone-tutorial/5-summary.md b/docs/shared/angular-standalone-tutorial/5-summary.md index a16e2195bb3cd..cdc8b6d3591a8 100644 --- a/docs/shared/angular-standalone-tutorial/5-summary.md +++ b/docs/shared/angular-standalone-tutorial/5-summary.md @@ -13,7 +13,7 @@ In this tutorial you: {% card title="Core Features" description="Read about the core features of Nx." url="/core-features" /%} -{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/plugin-features" /%} +{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/core-features/plugin-features" /%} {% card title="Mental Model" description="Get a deeper understanding of the mental model." url="/concepts/mental-model" /%} diff --git a/docs/shared/angular-standalone-tutorial/angular-standalone.md b/docs/shared/angular-standalone-tutorial/angular-standalone.md index a03f65a5faed8..4ba4d91452dd8 100644 --- a/docs/shared/angular-standalone-tutorial/angular-standalone.md +++ b/docs/shared/angular-standalone-tutorial/angular-standalone.md @@ -18,19 +18,21 @@ Note, this tutorial sets up a repo with a single application at the root level t Here's the source code of the final result for this tutorial. -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-angular-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/angular-standalone" /%} -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/standalone-angular-app?file=README.md" /%} + Also, if you prefer learning with a video, join Juri and walk through the tutorial, step by step together. {% youtube src="https://www.youtube.com/embed/ZAO0yXupIIE" title="Tutorial: Standalone Angular Application" -width="100%" /%} +/%} ## Creating a new Angular App +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=49" /%} + Create a new Angular application with the following command: ```shell {% command="npx create-nx-workspace@latest myngapp --preset=angular-standalone" path="~" %} @@ -44,7 +46,7 @@ Create a new Angular application with the following command: You get asked a few questions that help Nx preconfigure your new Angular application. These include - Angular specific questions, such as whether you want to have the router set up for you, whether to use the Angular Standalone API and which stylesheet format to use -- General Nx questions, such as whether to enable distributed caching with Nx Cloud. Nx comes with built-in [local caching](/core-features/cache-task-results). If you want to benefit from this cache in CI, you can enable [distributed caching](/core-features/share-your-cache) which will set up [Nx Cloud](https://nx.app). This is also a prerequisite for enabling [distributed task execution](/core-features/distribute-task-execution). +- General Nx questions, such as whether to enable distributed caching with Nx Cloud. Nx comes with built-in [local caching](/core-features/cache-task-results). If you want to benefit from this cache in CI, you can enable [distributed caching](/core-features/remote-cache) which will set up [Nx Cloud](https://nx.app). This is also a prerequisite for enabling [distributed task execution](/core-features/distribute-task-execution). For the sake of this tutorial, let's respond to all the questions with "yes". @@ -100,13 +102,15 @@ The setup includes.. Compared to the Angular CLI, you might notice the addition of an `nx.json` file and the absence of an `angular.json` file. Instead of the `angular.json` file there is a `project.json` file. Each file is described below: -| File | Description | -| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `nx.json` | This is where we can fine-tune how Nx works, define the [cacheable operations](/core-features/cache-task-results), our [task pipelines](/concepts/task-pipeline-configuration) as well as defaults for the Nx generators. Find more details in [the reference docs](/reference/nx-json). | -| `project.json` | Nx uses this file to define targets that can be run, similar to how the Angular CLI uses the `angular.json` file. If you're familiar with the Angular CLI you should have no difficulty navigating the `project.json` file. If you're curious how the two compare, you can learn more in [the Nx and Angular CLI comparision article](/more-concepts/nx-and-angular). The [project-configuration documentation page](/reference/project-configuration) has more details on how to use the `project.json` file. | +| File | Description | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `nx.json` | This is where we can fine-tune how Nx works, define the [cacheable operations](/core-features/cache-task-results), our [task pipelines](/concepts/task-pipeline-configuration) as well as defaults for the Nx generators. Find more details in [the reference docs](/reference/nx-json). | +| `project.json` | Nx uses this file to define targets that can be run, similar to how the Angular CLI uses the `angular.json` file. If you're familiar with the Angular CLI you should have no difficulty navigating the `project.json` file. If you're curious how the two compare, you can learn more in [the Nx and Angular CLI comparision article](/concepts/more-concepts/nx-and-angular). The [project-configuration documentation page](/reference/project-configuration) has more details on how to use the `project.json` file. | ## Serving the App +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=296" /%} + The most common tasks are already defined in the `package.json` file: ```json {% fileName="package.json" %} @@ -176,13 +180,15 @@ Each target contains a configuration object that tells Nx how to run that target The most critical parts are: -- `executor` - This corresponds to the `builder` property in an Angular CLI workspace. You can use Angular builders or executors from [Nx plugins](/plugins/intro/getting-started). +- `executor` - This corresponds to the `builder` property in an Angular CLI workspace. You can use Angular builders or executors from [Nx plugins](/extending-nx/intro/getting-started). - `options` - these are additional properties and flags passed to the executor function to customize it Learn more about how to [run tasks with Nx](/core-features/run-tasks). ## Testing and Linting - Running Multiple Tasks +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=369" /%} + Our current setup not only has targets for serving and building the Angular application, but also has targets for unit testing, e2e testing and linting. Again, these are defined in the `project.json` file. We can use the same syntax as before to run these tasks: ```bash @@ -207,6 +213,8 @@ More conveniently, we can also run them in parallel using the following syntax: ### Caching +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=443" /%} + One thing to highlight is that Nx is able to [cache the tasks you run](/core-features/cache-task-results). Note that all of these targets are automatically cached by Nx. If you re-run a single one or all of them again, you'll see that the task completes immediately. In addition, (as can be seen in the output example below) there will be a note that a matching cache result was found and therefore the task was not run again. @@ -229,6 +237,8 @@ Not all tasks might be cacheable though. You can configure `cacheableOperations` ## Creating New Components +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=500" /%} + Similar to the Angular CLI, Nx comes with code generation abilities. What the Angular CLI calls "Schematics", Nx calls "Generators". Generators allow you to easily scaffold code, configuration or entire projects. To see what capabilities the `@nx/angular` plugin ships with, run the following command and inspect the output: @@ -314,6 +324,8 @@ export class HelloWorldComponent {} ## Building the App for Deployment +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=680" /%} + If you're ready and want to ship your application, you can build it using ```shell {% command="npx nx build" path="myngapp" %} @@ -342,6 +354,8 @@ All the required files will be placed in the `dist/myngapp` folder and can be de ## You're ready to go! +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=723" /%} + In the previous sections you learned about the basics of using Nx, running tasks and navigating an Nx workspace. You're ready to ship features now! But there's more to learn. You have two possibilities here: @@ -351,6 +365,8 @@ But there's more to learn. You have two possibilities here: ## Modularizing your Angular App with Local Libraries +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=750" /%} + When you develop your Angular application, usually all your logic sits in the `app` folder. Ideally separated by various folder names which represent your "domains". As your app grows, this becomes more and more monolithic though. The following structure is a common example of this kind of monolithic code organization: @@ -382,6 +398,8 @@ Nx allows you to separate this logic into "local libraries". The main benefits i ### Creating Local Libraries +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=818" /%} + Let's assume our domain areas include `products`, `orders` and some more generic design system components, called `ui`. We can generate a new library for each of these areas using the Angular library generator: ``` @@ -453,6 +471,8 @@ Each of these libraries ### Importing Libraries into the Angular Application +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=976" /%} + All libraries that we generate automatically have aliases created in the root-level `tsconfig.base.json`. ```json {% fileName="tsconfig.base.json" %} @@ -557,6 +577,8 @@ A couple of notes: ## Visualizing your Project Structure +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=958" /%} + Nx automatically detects the dependencies between the various parts of your workspace and builds a [project graph](/core-features/explore-graph). This graph is used by Nx to perform various optimizations such as determining the correct order of execution when running tasks like `nx build`, identifying [affected projects](/core-features/run-tasks#run-tasks-affected-by-a-pr) and more. Interestingly you can also visualize it. Just run: @@ -634,6 +656,8 @@ Exercise for you: change the codebase so that `modules-shared-ui` is used by `mo ## Imposing Constraints with Module Boundary Rules +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=1147" /%} + Once you modularize your codebase you want to make sure that the modules are not coupled to each other in an uncontrolled way. Here are some examples of how we might want to guard our small demo workspace: - we might want to allow `modules-orders` to import from `modules-shared-ui` but not the other way around @@ -642,7 +666,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: -- **type of project:** what is the type of your library. Example: "feature" library, "utility" library, "data-access" library, "ui" library (see [library types](/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/more-concepts/library-types)) - **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 `modules-orders` library and assign the tags `type:feature` and `scope:orders` to it. @@ -789,7 +813,7 @@ If you have the ESLint plugin installed in your IDE you should immediately see a ![ESLint module boundary error](/shared/images/tutorial-angular-standalone/boundary-rule-violation-vscode.png) -Learn more about how to [enforce module boundaries](/core-features/enforce-project-boundaries). +Learn more about how to [enforce module boundaries](/core-features/enforce-module-boundaries). ## Next Steps @@ -798,10 +822,10 @@ Congrats, you made it!! You now know how to leverage the Nx standalone applicati Here's some more things you can dive into next: - Learn more about the [underlying mental model of Nx](/concepts/mental-model) -- Learn about popular generators such as [how to setup Tailwind](/recipes/other/using-tailwind-css-with-angular-projects) or [add Storybook to your UI library](/packages/storybook/documents/overview-angular) -- Learn how to [migrate your existing Angular CLI repo to Nx](/recipes/adopting-nx/migration-angular) +- Learn about popular generators such as [how to setup Tailwind](/recipes/angular/using-tailwind-css-with-angular-projects) or [add Storybook to your UI library](/packages/storybook/documents/overview-angular) +- Learn how to [migrate your existing Angular CLI repo to Nx](/recipes/angular/migration/angular) - [Speed up CI: Run only tasks for project that got changed](/core-features/run-tasks#run-tasks-affected-by-a-pr) -- [Speed up CI: Share your cache](/core-features/share-your-cache) +- [Speed up CI: Share your cache](/core-features/remote-cache) - [Speed up CI: Distribute your tasks across machines](/core-features/distribute-task-execution) Also, make sure you diff --git a/docs/shared/angular-tutorial/5-summary.md b/docs/shared/angular-tutorial/5-summary.md index 1711dcb18f737..02703360f1eb6 100644 --- a/docs/shared/angular-tutorial/5-summary.md +++ b/docs/shared/angular-tutorial/5-summary.md @@ -13,7 +13,7 @@ In this tutorial you: {% card title="Core Features" description="Read about the core features of Nx." url="/core-features" /%} -{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/plugin-features" /%} +{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/core-features/plugin-features" /%} {% card title="Mental Model" description="Get a deeper understanding of the mental model." url="/concepts/mental-model" /%} diff --git a/docs/shared/concepts/customizing-inputs.md b/docs/shared/concepts/customizing-inputs.md index 2002319615580..92621de08003a 100644 --- a/docs/shared/concepts/customizing-inputs.md +++ b/docs/shared/concepts/customizing-inputs.md @@ -16,7 +16,7 @@ Knowing the syntax doesn't always explain how you would use the feature, so here If you don't specify any `inputs`, Nx uses as inputs every file in the task's project and every file in that project's dependencies. It's the same as writing this: -```jsonc +```jsonc {% fileName="nx.json" %} { "namedInputs": { "default": ["{projectRoot}/**/*"] diff --git a/docs/shared/concepts/how-caching-works.md b/docs/shared/concepts/how-caching-works.md index 3946f19574b81..c652c2347267d 100644 --- a/docs/shared/concepts/how-caching-works.md +++ b/docs/shared/concepts/how-caching-works.md @@ -3,7 +3,7 @@ Before running any task, Nx computes its computation hash. As long as the computation hash is the same, the output of running the task is the same. -By default, the computation hash for - say - `nx test remixapp` includes: +By default, the computation hash for something like `nx test remixapp` includes: - All the source files of `remixapp` and its dependencies - Relevant global configuration @@ -88,7 +88,7 @@ With this configuration, the build script will only consider the non-test files The test script will consider all the source files for the project under test and only non-test files of its dependencies. The test script will also consider the jest config file at the root of the workspace. -For more information about modifying `inputs` and `namedInputs` for your own repo, read [Customizing Inputs](/more-concepts/customizing-inputs) +For more information about modifying `inputs` and `namedInputs` for your own repo, read [Customizing Inputs](/concepts/more-concepts/customizing-inputs) ### Filesets diff --git a/docs/shared/concepts/how-project-graph-is-built.md b/docs/shared/concepts/how-project-graph-is-built.md index e80a92c623837..c928262700973 100644 --- a/docs/shared/concepts/how-project-graph-is-built.md +++ b/docs/shared/concepts/how-project-graph-is-built.md @@ -28,7 +28,7 @@ Nx creates a graph of all the dependencies between projects in your workspace us Then `my-app` depends on `awesome-library` - This can be [turned on or off with the `analyzeSourceFiles` flag](../../recipes/other/analyze-source-files). + This can be [turned on or off with the `analyzeSourceFiles` flag](../../recipes/tips-n-tricks/analyze-source-files). 3. Manually created `implicitDependencies` in the project configuration file. diff --git a/docs/shared/concepts/integrated-vs-package-based.md b/docs/shared/concepts/integrated-vs-package-based.md index c959475dcf7cc..0636818ba0423 100644 --- a/docs/shared/concepts/integrated-vs-package-based.md +++ b/docs/shared/concepts/integrated-vs-package-based.md @@ -13,9 +13,9 @@ There are two styles of monorepos that you can build with Nx: integrated repos a ## 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](/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/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. -Lerna, Yarn, Lage, [Turborepo](/more-concepts/turbo-and-nx) and Nx (without plugins) support this style. +Lerna, Yarn, Lage, [Turborepo](/concepts/more-concepts/turbo-and-nx) and Nx (without plugins) support this style. {% cards %} {% card title="Tutorial: Getting Started with Package-Based Repos" description="Walkthrough for creating a package-based monorepo with Nx" type="documentation" url="/getting-started/tutorials/package-based-repo-tutorial" /%} @@ -23,7 +23,7 @@ Lerna, Yarn, Lage, [Turborepo](/more-concepts/turbo-and-nx) and Nx (without plug ## 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](/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/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. Bazel and Nx (with plugins) support this style. @@ -33,7 +33,7 @@ Bazel and Nx (with plugins) support this style. ## Standalone Applications -Nx plugins, especially the [generators](/plugin-features/use-code-generators), [executors](/plugin-features/use-task-executors) and [migrations](/core-features/automate-updating-dependencies) that come with them, are not only valuable for a monorepo scenario. In fact, many developers use Nx not primarily for its monorepo support, but for its tooling support, particularly its ability to modularize a codebase and, thus, better scale it. In v15.3, Nx introduced support for Standalone Applications. It is like an integrated monorepo setup, but with just a single, root-level application. Think of it as an advanced, more capable Create-React-App or Angular CLI. And obviously, you can still leverage all the generators and executors and structure your application into libraries or submodules. +Nx plugins, especially the [generators](/core-features/plugin-features/use-code-generators), [executors](/core-features/plugin-features/use-task-executors) and [migrations](/core-features/automate-updating-dependencies) that come with them, are not only valuable for a monorepo scenario. In fact, many developers use Nx not primarily for its monorepo support, but for its tooling support, particularly its ability to modularize a codebase and, thus, better scale it. In v15.3, Nx introduced support for Standalone Applications. It is like an integrated monorepo setup, but with just a single, root-level application. Think of it as an advanced, more capable Create-React-App or Angular CLI. And obviously, you can still leverage all the generators and executors and structure your application into libraries or submodules. {% cards %} {% card title="Standalone Applications with Nx" description="Learn what Standlone Apps are and how Nx can be useful" type="video" url="https://youtu.be/qEaVzh-oBBc" /%} diff --git a/docs/shared/core-features/automate-updating-dependencies.md b/docs/shared/core-features/automate-updating-dependencies.md index 07a5f3f5eb21f..9e9181c9cf100 100644 --- a/docs/shared/core-features/automate-updating-dependencies.md +++ b/docs/shared/core-features/automate-updating-dependencies.md @@ -1,16 +1,29 @@ # Automate Updating Dependencies -The Nx CLI provides the `migrate` command to help you stay up to date with the latest version of Nx. +Keeping a codebase updated with the latest changes in your framework of choice can be challenging. Not to mention that "tooling maintenance work" is usually hard to squeeze into your feature sprint. -Not only does `nx migrate` update you to the latest version of Nx, but it also updates the versions of dependencies that we support and test such as Jest and Cypress. You can also use the `migrate` command to update any Nx plugin. +The `nx migrate` command helps by automating the process of updating: -## Update to the latest Nx version +- package versions in your `package.json` +- configuration files (e.g. your Jest, ESLint or Nx config) +- your source code (e.g. fixing breaking changes or migrating to new best practices) + +## How does it work? + +{% youtube +src="https://www.youtube.com/embed/Ss6MfcXi0jE" +title="How Automated Code Migrations Work" +/%} + +Nx knows where its configuration files are and can therefore make sure they match the expected format. This automated update process, commonly referred to as "migration," becomes even more powerful when you leverage [Nx plugins](/packages). Nx plugins, which are NPM packages with a range of capabilities (code generation, task automation...), offer targeted updates based on their specific areas of responsibility. + +For example, the [Nx ESLint plugin](/packages/linter) excels at configuring linting in your workspace. With its understanding of the configuration file locations, this plugin can provide precise migration scripts to update ESLint packages in your `package.json` and corresponding configuration files in your workspace when a new version is released. Updating happens in three steps: - The installed dependencies are updated including the `package.json` (and `node_modules`). -- The source code in the repo is updated to match the new versions of packages in `package.json`. -- Remove the `migrations.json` file +- The source code in the repo is updated to match the new versions of packages according to the set of instructions specified in `migrations.json` file. +- Optionally remove the `migrations.json` file or keep it to re-run the migration in different Git branches ### Step 1: Updating dependencies and generating migrations @@ -20,11 +33,7 @@ First, run the `migrate` command: nx migrate latest # same as nx migrate nx@latest ``` -You can also specify the name of the package and the version: - -```shell -nx migrate nx@version # you can also specify version -``` +Note you can also specify an exact version by replacing `latest` with `nx@`. This fetches the specified version of the `nx` package, analyzes the dependencies and fetches all the dependent packages. The process keeps going until all the dependencies are resolved. This results in: @@ -41,11 +50,7 @@ At this stage, after inspecting the `package.json`, you may wish to manually run ### Step 2: Running migrations -The next step in the process involves using the `migrate` CLI in order to apply the migrations that were generated in `migrations.json` in the previous step. - -Each Nx plugin is able to provide a set of migrations which are relevant to particular versions of the package, and so `migrations.json` will only contain migrations which are appropriate for the update you are currently applying. - -The common case is that you will simply apply all migrations from the generated JSON file, exactly as they were generated in the previous step, by running: +You can now run the actual code migrations that were generated in the `migrations.json` in the previous step. ```shell nx migrate --run-migrations @@ -53,12 +58,14 @@ nx migrate --run-migrations This will update your source code in your workspace in accordance with the implementation of the various migrations which ran and all the changes will be unstaged ready for you to review and commit yourself. +Note that each Nx plugin is able to provide a set of migrations which are relevant to particular versions of the package. Hence `migrations.json` will only contain migrations which are appropriate for the update you are currently applying. + ### Step 3: Cleaning up After you run all the migrations, you can remove `migrations.json` and commit any outstanding changes. Note: You may want to keep the `migrations.json` until every branch that was created before the migration has been merged. Leaving the `migrations.json` in place allows devs to run `nx migrate --run-migrations` to apply the same migration process to their newly merged code as well. -## Problems? +## Need to opt-out of some migrations? -If you can't run `nx migrate --run-migrations` all in one step, try the tips in [Advanced Update Process](/recipes/other/advanced-update) +Sometimes you need to temporarily opt-out from some migrations because your workspace is not ready yet. You can manually adjust the `migrations.json` or run the update with the `--interactive` flag to choose which migrations you accept. Find more details in our [Advanced Update Process](/recipes/tips-n-tricks/advanced-update) guide. diff --git a/docs/shared/core-features/cache-task-results.md b/docs/shared/core-features/cache-task-results.md index 381927bf4ace5..ff6cfe34bc1f1 100644 --- a/docs/shared/core-features/cache-task-results.md +++ b/docs/shared/core-features/cache-task-results.md @@ -64,7 +64,7 @@ header/ └── dist/ <-- this folder gets recreated ``` -If your task creates output artifacts in a different location, you can [change the output folder(s)](/reference/project-configuration#outputs) that are cached. You can also [customize which inputs](/more-concepts/customizing-inputs) will invalidate the cache if they are changed. +If your task creates output artifacts in a different location, you can [change the output folder(s)](/reference/project-configuration#outputs) that are cached. You can also [customize which inputs](/concepts/more-concepts/customizing-inputs) will invalidate the cache if they are changed. ## Advanced Caching diff --git a/docs/shared/core-features/enforce-project-boundaries.md b/docs/shared/core-features/enforce-module-boundaries.md similarity index 97% rename from docs/shared/core-features/enforce-project-boundaries.md rename to docs/shared/core-features/enforce-module-boundaries.md index 8fde324e58cfd..824ac8ae28c41 100644 --- a/docs/shared/core-features/enforce-project-boundaries.md +++ b/docs/shared/core-features/enforce-module-boundaries.md @@ -1,9 +1,14 @@ -# Enforce Project Boundaries +# Enforce Module Boundaries If you partition your code into well-defined cohesive units, even a small organization will end up with a dozen apps and dozens or hundreds of libs. If all of them can depend on each other freely, chaos will ensue, and the workspace will become unmanageable. To help with that Nx uses code analysis to make sure projects can only depend on each other's well-defined public API. It also allows you to declaratively impose constraints on how projects can depend on each other. +{% youtube +src="https://www.youtube.com/embed/q0en5vlOsWY" +title="Applying Module Boundaries" +/%} + ## Project APIs Nx provides an `enforce-module-boundaries` eslint rule that enforces the public API of projects in the repo. Each project defines its public API in an `index.ts` (or `index.js`) file. If another project tries to import a variable from a file deep within a different project, an error will be thrown during linting. diff --git a/docs/shared/core-features/explore-graph.md b/docs/shared/core-features/explore-graph.md index 3165ccc3628e0..ca6b24b5495d2 100644 --- a/docs/shared/core-features/explore-graph.md +++ b/docs/shared/core-features/explore-graph.md @@ -8,7 +8,7 @@ high level view of your code architecture. To launch the project graph visualization run: ```shell -nx graph +npx nx graph ``` This will open a browser window with an interactive representation of the project graph of your current codebase. @@ -132,3 +132,13 @@ Try playing around with a [fully interactive graph on a sample repo](https://nrw ``` {% /graph %} + +## Export Project Graph to JSON + +If you prefer to analyze the underlying data of the project graph with a script or some other tool, you can run: + +```shell +nx graph --file=output.json +``` + +This will give you all the information that is used to create the project graph visualization. diff --git a/docs/shared/core-features/share-your-cache.md b/docs/shared/core-features/remote-cache.md similarity index 74% rename from docs/shared/core-features/share-your-cache.md rename to docs/shared/core-features/remote-cache.md index f8ac0eaa09eb2..b1728c8351a9a 100644 --- a/docs/shared/core-features/share-your-cache.md +++ b/docs/shared/core-features/remote-cache.md @@ -1,40 +1,22 @@ -# Share Your Cache +# Use Remote Caching -The computation cache provided by Nx can be distributed across multiple machines. You can either build an implementation -of the cache or use Nx Cloud. Nx Cloud is an app that provides a fast and zero-config implementation of distributed -caching. It's completely free for OSS projects and for most closed-sourced -projects ([read more here](https://dev.to/nrwl/more-time-saved-for-free-with-nx-cloud-4a2j)). +The computation cache provided by Nx can be distributed across multiple machines. You can either build an implementation of the cache or use Nx Cloud. Nx Cloud is an app that provides a fast and zero-config implementation of distributed caching. It's completely free for OSS projects and for most closed-sourced +projects ([read more here](https://nx.app/pricing)). ![Diagram showing Teika sharing his cache with CI, Kimiko and James](/shared/images/dte/distributed-caching.svg) In this diagram, Teika runs the build once on his machine, then CI, Kimiko and James can use the cached artifact from Teika instead of re-executing the same work. +## Connecting Your Workspace to Your Nx Cloud Account + You can connect your workspace to Nx Cloud by running: ```shell npx nx connect-to-nx-cloud ``` -```{% command="npx nx connect-to-nx-cloud"%} -✔ Enable distributed caching to make your CI faster · Yes - - > NX Distributed caching via Nx Cloud has been enabled - - In addition to the caching, Nx Cloud provides config-free distributed execution, - UI for viewing complex runs and GitHub integration. Learn more at https://nx.app - - Your workspace is currently unclaimed. Run details from unclaimed workspaces can be viewed on cloud.nx.app by anyone - with the link. Claim your workspace at the following link to restrict access. - - https://cloud.nx.app/orgs/workspace-setup?accessToken=YOURACCESSTOKEN -``` - To see the remote cache in action, run: -```shell -nx build header && nx reset && nx build header -``` - ```{% command="nx build header && nx reset && nx build header"%} > nx run header:build @@ -81,11 +63,11 @@ created dist in 786ms Nx Cloud made it possible to reuse header: https://nx.app/runs/P0X6ZGTkqZ ``` -## Connecting Your Workspace to Your Nx Cloud Account +## Claim your Nx Cloud Workspace After you have enabled Nx Cloud in your workspace, you will see the following: -```shell +```plaintext > NX NOTE Nx Cloud has been enabled Your workspace is currently public. Anybody with code access @@ -109,5 +91,4 @@ account, and connect your workspace using the access token from `nx.json`. ## Skipping Cloud -Similar to how `--skip-nx-cache` will instruct Nx not to use the cache, passing `--no-cloud` will tell Nx not to use Nx -Cloud. +Similar to how `--skip-nx-cache` will instruct Nx not to use the local cache, passing `--no-cloud` will tell Nx not to use the remote cache from Nx Cloud. diff --git a/docs/shared/core-features/run-tasks.md b/docs/shared/core-features/run-tasks.md index c643a7b69b21a..7c68c89bacf82 100644 --- a/docs/shared/core-features/run-tasks.md +++ b/docs/shared/core-features/run-tasks.md @@ -136,7 +136,7 @@ If you want Nx to cache the task, but prefer to use npm (or pnpm/yarn) to run th } ``` -Learn more about root-level tasks [in our dedicated recipe page](/recipes/other/root-level-scripts). +Learn more about root-level tasks [in our dedicated recipe page](/recipes/tips-n-tricks/root-level-scripts). ## Defining the Task Pipeline diff --git a/docs/shared/daemon.md b/docs/shared/daemon.md index 6a348395c8fbe..6bea760737dda 100644 --- a/docs/shared/daemon.md +++ b/docs/shared/daemon.md @@ -29,7 +29,10 @@ If you ever need to manually shut down the Nx Daemon, you can run `nx reset` wit ## Turning it Off -As of v13.6.0, the Nx Daemon is enabled by default when running on your local machine. If you want to turn it off, simply set `useDaemonProcess: false` in the runners options in nx.json. You can also set the `NX_DAEMON` env variable to `false`. +As of v13.6.0, the Nx Daemon is enabled by default when running on your local machine. If you want to turn it off + +- simply set `useDaemonProcess: false` in the runners options in `nx.json` or +- set the `NX_DAEMON` env variable to `false`. When using Nx in a CI environment, the Nx Daemon is disabled by default. Whether the process runs is determined by the following function: [https://github.com/nrwl/nx/blob/master/packages/nx/src/utils/is-ci.ts](https://github.com/nrwl/nx/blob/master/packages/nx/src/utils/is-ci.ts) diff --git a/docs/shared/deprecated/global-implicit-dependencies.md b/docs/shared/deprecated/global-implicit-dependencies.md index 39f8de3614118..d31536ac28d16 100644 --- a/docs/shared/deprecated/global-implicit-dependencies.md +++ b/docs/shared/deprecated/global-implicit-dependencies.md @@ -1,6 +1,6 @@ # Global Implicit Dependencies -Since v14.4, Nx supports [`inputs` and `namedInputs`](/more-concepts/customizing-inputs) for setting up implicit dependencies. As of Nx v16, the `implicitDependencies` defined in `nx.json` are ignored and do not influence the affected graph. This field will be removed in v17. The [`implicitDependencies` in the project configuration](/reference/project-configuration#implicitdependencies) are still the best way to manually set up a dependency between two projects that Nx is not able to detect automatically. +Since v14.4, Nx supports [`inputs` and `namedInputs`](/concepts/more-concepts/customizing-inputs) for setting up implicit dependencies. As of Nx v16, the `implicitDependencies` defined in `nx.json` are ignored and do not influence the affected graph. This field will be removed in v17. The [`implicitDependencies` in the project configuration](/reference/project-configuration#implicitdependencies) are still the best way to manually set up a dependency between two projects that Nx is not able to detect automatically. ## Projects Depending on Global Files @@ -34,7 +34,7 @@ To express the same dependencies with `inputs` and `namedInputs`, modify the def The `sharedGlobals` are included in the `default` named input, so most targets will be set up to depend on them. -For a more detailed explanation, read the [Customizing Inputs and Named Inputs guide](/more-concepts/customizing-inputs) +For a more detailed explanation, read the [Customizing Inputs and Named Inputs guide](/concepts/more-concepts/customizing-inputs) ### Dependencies on Sections of the Root `package.json` File diff --git a/docs/shared/deprecated/storybook/migrate-webpack-final-react.md b/docs/shared/deprecated/storybook/migrate-webpack-final-react.md index de4ebf8e763e1..53600951a1e60 100644 --- a/docs/shared/deprecated/storybook/migrate-webpack-final-react.md +++ b/docs/shared/deprecated/storybook/migrate-webpack-final-react.md @@ -14,7 +14,7 @@ Nx 12.7 comes with a dedicated Storybook addon for React which dramatically simp {% youtube src="https://www.youtube.com/embed/oUE74McS_NY" title="New in Nx 12.7: React Storybook Preset" -width="100%" /%} +/%} Here are the main differences to the previous versions of Nx: diff --git a/docs/shared/deprecated/workspace-executors.md b/docs/shared/deprecated/workspace-executors.md index 872772eb864c4..bce0270ee43fc 100644 --- a/docs/shared/deprecated/workspace-executors.md +++ b/docs/shared/deprecated/workspace-executors.md @@ -1,6 +1,6 @@ # Workspace Executors -In Nx 13.10+, local nx plugins can contain executors that are used in the workspace. When creating a custom executor for your workspace, look into the [local executor guide](/plugins/recipes/local-executors) to simplify the build process. +In Nx 13.10+, local nx plugins can contain executors that are used in the workspace. When creating a custom executor for your workspace, look into the [local executor guide](/extending-nx/recipes/local-executors) to simplify the build process. ## Converting workspace executors to local executors diff --git a/docs/shared/deprecated/workspace-generators.md b/docs/shared/deprecated/workspace-generators.md index cdb3ee4c5947a..c8ca4149ac30d 100644 --- a/docs/shared/deprecated/workspace-generators.md +++ b/docs/shared/deprecated/workspace-generators.md @@ -4,7 +4,7 @@ In Nx 13.10, we introduced the ability to run generators from Nx plugins in the By using a "local" plugin, you can set the plugin as your workspace's default collection and get several other affordances that are not provided to workspace generators. This is the preferred method for "workspace generators", and existing generators will eventually be transitioned to use a local plugin. -Check the [local generator guide](/plugins/recipes/local-generators) for information on creating a new plugin. +Check the [local generator guide](/extending-nx/recipes/local-generators) for information on creating a new plugin. ## Converting workspace generators to local generators diff --git a/docs/shared/deprecated/workspace-json.md b/docs/shared/deprecated/workspace-json.md index d726c24891b66..b03ece4a3c946 100644 --- a/docs/shared/deprecated/workspace-json.md +++ b/docs/shared/deprecated/workspace-json.md @@ -5,7 +5,7 @@ Nx used to have a `workspace.json` file at the root of the repo that at various 1. Identified the locations of all project in the repo 2. Contained the target configuration for all projects -Identifying the locations of projects is now done automatically through project inference. You can even customize how projects are inferred with a [project inference plugin](/plugins/recipes/project-inference-plugins). +Identifying the locations of projects is now done automatically through project inference. You can even customize how projects are inferred with a [project inference plugin](/extending-nx/recipes/project-inference-plugins). The target configuration for each project is now stored in individual `project.json` files or `package.json` files. diff --git a/docs/shared/deprecated/workspace-lint.md b/docs/shared/deprecated/workspace-lint.md index e47a3f586bc4e..5a605d5e96a1a 100644 --- a/docs/shared/deprecated/workspace-lint.md +++ b/docs/shared/deprecated/workspace-lint.md @@ -6,7 +6,7 @@ Before Nx 15, the `workspace-lint` command performed workspace wide lint checks 2. Checking for files that do not belong to a project 3. Ensuring that all the versions of Nx packages are in sync -Checks (1) and (2) are no longer necessary because [Nx no longer uses a `workspace.json` file](../workspace-json) to define project locations. Instead, Nx dynamically detects projects anywhere in the workspace based on the presence of `package.json` or `project.json` files. +Checks (1) and (2) are no longer necessary because [Nx no longer uses a `workspace.json` file](/deprecated/workspace-json) to define project locations. Instead, Nx dynamically detects projects anywhere in the workspace based on the presence of `package.json` or `project.json` files. Check (3) is now accomplished manually with the [`nx report` command](/packages/nx/documents/report). diff --git a/docs/shared/eslint.md b/docs/shared/eslint.md index 63efaaf56b90e..3f801960a7ceb 100644 --- a/docs/shared/eslint.md +++ b/docs/shared/eslint.md @@ -1,6 +1,4 @@ -# Using ESLint in Nx Workspaces - -## Rules requiring type information +# Configuring ESLint with Typescript ESLint is powerful linter by itself, able to work on the syntax of your source files and assert things about based on the rules you configure. It gets even more powerful, however, when TypeScript type-checker is layered on top of it when analyzing TypeScript files, which is something that `@typescript-eslint` allows us to do. diff --git a/docs/shared/getting-started/installation.md b/docs/shared/getting-started/installation.md index ee8eca64479f9..314f95388a9fa 100644 --- a/docs/shared/getting-started/installation.md +++ b/docs/shared/getting-started/installation.md @@ -6,21 +6,21 @@ Create a new Nx workspace using the following command: {% tab label="npm" %} ```shell -npm create nx-workspace +npx create-nx-workspace ``` {% /tab %} {% tab label="yarn" %} ```shell -yarn create nx-workspace +npx create-nx-workspace --pm yarn ``` {% /tab %} {% tab label="pnpm" %} ```shell -pnpm create nx-workspace +npx create-nx-workspace --pm pnpm ``` {% /tab %} @@ -28,13 +28,17 @@ pnpm create nx-workspace This will guide you through the setup, asking whether you want a monorepo or a standalone app and whether you want to start with a blank or a preconfigured setup. -```{% command="npm create nx-workspace" %} -? Choose what to create … -Package-based monorepo: Nx makes it fast but lets you run things your way. -Integrated monorepo: Nx configures your favorite frameworks and lets you focus on shipping features. -Standalone React app: Nx configures Vite (or Webpack), ESLint, and Cypress. -Standalone Angular app: Nx configures Jest, ESLint, and Cypress. -Standalone Node app: Nx configures a framework (ex. Express), esbuild, ESlint and Jest. +```{% command="npx create-nx-workspace" path="~" %} + + > NX Let's create a new workspace [https://nx.dev/getting-started/intro] + +✔ Where would you like to create your workspace? · myorg +? Which stack do you want to use? … +None: Configures a minimal structure without specific frameworks or technologies. +TS/JS: Configures a TypeScript/JavaScript package without specific frameworks or platforms. +React: Configures a React app with your framework of choice. +Angular: Configures a Angular app with modern tooling. +Node: Configures a Node API with your framework of choice. ``` Once you've created your workspace, you can @@ -86,4 +90,4 @@ pnpm install --global nx@latest The advantage of a global installation is that you don't have to prefix your commands with npx, yarn or pnpm. The global Nx installation hands off the process execution to the local Nx installation in your repository, which eliminates any issues with outdated globally installed packages. -Learn more about [managing and troubleshooting a global Nx installation](/more-concepts/global-nx). +Learn more about [managing and troubleshooting a global Nx installation](/concepts/more-concepts/global-nx). diff --git a/docs/shared/getting-started/intro.md b/docs/shared/getting-started/intro.md index fd1f2ca146353..8a6ee920763f7 100644 --- a/docs/shared/getting-started/intro.md +++ b/docs/shared/getting-started/intro.md @@ -1,18 +1,44 @@ # Intro to Nx -Nx is a powerful open-source build system that provides tools and techniques for enhancing developer productivity, optimizing CI performance, and maintaining code quality. Learn more about [how Nx works](/getting-started/why-nx). +Nx is a powerful open-source build system that provides tools and techniques for enhancing developer productivity, optimizing CI performance, and maintaining code quality. Find out more about [why you should use Nx](/getting-started/why-nx). -You can use Nx to quickly scaffold a new standalone project or even an entire monorepo. It can be incrementally adopted and will grow with your project as it scales. +If instead you want to jump right into it, run the following command. It will guide you through the setup: + +{% tabs %} +{% tab label="npm" %} + +```shell +npx create-nx-workspace +``` + +{% /tab %} +{% tab label="yarn" %} + +```shell +npx create-nx-workspace --pm yarn +``` + +{% /tab %} +{% tab label="pnpm" %} + +```shell +npx create-nx-workspace --pm pnpm +``` + +{% /tab %} +{% /tabs %} + +You can use Nx to quickly scaffold a new project or even an entire monorepo. It can be incrementally adopted and will grow with your project as it scales. {% cards cols="3" %} -{% title-card title="New Monorepo" url="#start-a-new-monorepo" /%} -{% title-card title="New Standalone Project" url="#start-a-new-standalone-project" /%} -{% title-card title="Add to an Existing Project or Monorepo" url="#adding-nx-to-an-existing-project-or-monorepo" /%} +{% title-card title="New Monorepo" url="#get-started-with-the-basics" /%} +{% title-card title="Choose a Stack" url="#learn-about-nx-and-your-favorite-stack" /%} +{% title-card title="Add to an Existing Project" url="#adding-nx-to-an-existing-project" /%} {% /cards %} -## Start a New Monorepo +## Get Started with the Basics Its modular architecture lets you adopt Nx for package-based monorepos in combination with NPM, Yarn or PNPM, or create a fully integrated monorepo using Nx plugins. Learn more with the tutorials below. @@ -36,41 +62,47 @@ Get a pre-configured setup. Nx configures your favorite frameworks and lets you {% /cards %} -## Start a New Standalone Project +## Learn About Nx and Your Favorite Stack -Nx works well not just for monorepos. Nx plugins help you scaffold new standalone projects with pre-configured tooling and modularize your codebase with local libraries. +Nx works well not just for monorepos. Nx plugins help you scaffold new projects with pre-configured tooling and modularize your codebase with local libraries. {% cards cols="3" %} -{% persona type="react" title="Create a Standalone React app" url="/getting-started/tutorials/react-standalone-tutorial" %} +{% persona type="react" title="Create a React app" url="/getting-started/tutorials/react-standalone-tutorial" %} A modern React setup with built-in support for Vite, ESLint, Cypress, and more. Think CRA but modern, always up-to-date and scalable. -- [Create a Standalone React app](/getting-started/tutorials/react-standalone-tutorial) +- [Create a React app](/getting-started/tutorials/react-standalone-tutorial) {% /persona %} -{% persona type="angular" title="Create a Standalone Angular app" url="/getting-started/tutorials/angular-standalone-tutorial" %} +{% persona type="angular" title="Create an Angular app" url="/getting-started/tutorials/angular-standalone-tutorial" %} A modern Angular development experience powered by advanced generators and integrations with modern tooling. -- [Create a Standalone Angular app](/getting-started/tutorials/angular-standalone-tutorial) +- [Create an Angular app](/getting-started/tutorials/angular-standalone-tutorial) {% /persona %} -{% persona type="node" title="Create a Standalone Node server" url="/getting-started/tutorials/node-server-tutorial" %} +{% persona type="node" title="Create a Node server" url="/getting-started/tutorials/node-server-tutorial" %} A modern Node server with scaffolding for Express, Fastify or Koa. There's also Docker support built-in. -- [Create a Standalone Node server](/getting-started/tutorials/node-server-tutorial) +- [Create a Node server](/getting-started/tutorials/node-server-tutorial) {% /persona %} {% /cards %} -## Adding Nx to an Existing Project or Monorepo +## Adding Nx to an Existing Project + +If you have an existing project and want to adopt Nx or migrate to Nx just run the following command which guides you through the migration process: + +```shell +npx nx@latest init +``` -Coming from an existing project and want to adopt Nx? We have a few recipes to help you get started. +Alternatively, here are some recipes that give you more details based on the technology stack you're using: {% cards cols="2" %} @@ -79,14 +111,14 @@ Add Nx to your existing NPM/YARN/PNPM workspace {% /persona %} {% persona title="Add to any Project" type="extend" url="/recipes/adopting-nx/adding-to-existing-project" %} -Add Nx to a standalone project +Add Nx to a project {% /persona %} -{% persona title="Migrate from CRA" type="react" url="/recipes/adopting-nx/migration-cra" %} +{% persona title="Migrate from CRA" type="react" url="/recipes/react/migration-cra" %} Migrate from a CRA setup and automatically switch to Vite {% /persona %} -{% persona title="Migrate from Angular CLI" type="angular" url="/recipes/adopting-nx/migration-angular" %} +{% persona title="Migrate from Angular CLI" type="angular" url="/recipes/angular/migration/angular" %} Automatically migrate from the Angular CLI {% /persona %} diff --git a/docs/shared/getting-started/why-nx.md b/docs/shared/getting-started/why-nx.md index 4548a78c64ccf..94c638cc20e9f 100644 --- a/docs/shared/getting-started/why-nx.md +++ b/docs/shared/getting-started/why-nx.md @@ -2,7 +2,7 @@ We created Nx because developers struggle to configure, maintain and especially integrate various tools and frameworks. Setting up a system that works well for a handful of developers and at the same time, easily scales up to an entire organization is hard. This includes setting up low-level build tooling, configuring fast CI, and keeping your codebase healthy, up-to-date, and maintainable. -We wanted to provide a solution that is easy to adopt and scales. +We wanted to provide a solution that is easy to adopt and scale. ## How Does Nx Help You? @@ -22,8 +22,8 @@ Nx is built in a modular fashion to let you only use the features you need. ![High-level Nx architecture](/shared/images/nx-architecture.svg) -- The **Nx** package provides fundamental technology-agnostic capabilities such as: [workspace analysis](/core-features/explore-graph), [task running](/core-features/run-tasks), [caching](/core-features/cache-task-results), [distribution](/core-features/distribute-task-execution), [code generation](/plugin-features/use-code-generators) and [automated code migrations](/core-features/automate-updating-dependencies). -- **Plugins** are NPM packages that built on top of the fundamental capabilities provided by the Nx package. Nx plugins contain [code generators](/plugin-features/use-code-generators), [executors](/plugin-features/use-task-executors) (to abstract lower-level build tooling) and automated code migrations for keeping your tools up to date. Contrary to the Nx package, which works the same way with any JS or non-JS project, plugins are usually technology specific. For instance, `@nx/react` adds support for building React apps and libs, `@nx/cypress` adds e2e testing capabilities with Cypress. Plugins make developers more productive by removing any friction of integrating different tools with each other and by providing utilities to keep them up to date. The Nx team maintains plugins for React, Next, Remix, Angular, Jest, Cypress, Storybook and more. You can use the `@nx/plugin` package to easily [scaffold a new plugin](/plugins/intro/getting-started) or even just [automate your local workspace](/plugins/recipes/local-generators). There are also more than 80 [community plugins](/plugins/registry). -- **Devkit** is a set of utilities for [building Nx plugins](/plugins/intro/getting-started). -- **Nx Cloud** helps scale your project on CI by [adding remote caching](/concepts/how-caching-works) and [distributed task execution](/more-concepts/illustrated-dte). It also improves developer ergonomics by integrating with GitHub, GitLab and BitBucket and providing searchable structured logs. Learn more at [nx.app](https://nx.app). +- The **Nx** package provides fundamental technology-agnostic capabilities such as: [workspace analysis](/core-features/explore-graph), [task running](/core-features/run-tasks), [caching](/core-features/cache-task-results), [distribution](/core-features/distribute-task-execution), [code generation](/core-features/plugin-features/use-code-generators) and [automated code migrations](/core-features/automate-updating-dependencies). +- **Plugins** are NPM packages that built on top of the fundamental capabilities provided by the Nx package. Nx plugins contain [code generators](/core-features/plugin-features/use-code-generators), [executors](/core-features/plugin-features/use-task-executors) (to abstract lower-level build tooling) and automated code migrations for keeping your tools up to date. Contrary to the Nx package, which works the same way with any JS or non-JS project, plugins are usually technology specific. For instance, `@nx/react` adds support for building React apps and libs, `@nx/cypress` adds e2e testing capabilities with Cypress. Plugins make developers more productive by removing any friction of integrating different tools with each other and by providing utilities to keep them up to date. The Nx team maintains plugins for React, Next, Remix, Angular, Jest, Cypress, Storybook and more. You can use the `@nx/plugin` package to easily [scaffold a new plugin](/extending-nx/intro/getting-started) or even just [automate your local workspace](/extending-nx/recipes/local-generators). There are also more than 80 [community plugins](/extending-nx/registry). +- **Devkit** is a set of utilities for [building Nx plugins](/extending-nx/intro/getting-started). +- **Nx Cloud** helps scale your project on CI by [adding remote caching](/concepts/how-caching-works) and [distributed task execution](/concepts/more-concepts/illustrated-dte). It also improves developer ergonomics by integrating with GitHub, GitLab and BitBucket and providing searchable structured logs. Learn more at [nx.app](https://nx.app). - **Nx Console** is an extension for **VSCode, IntelliJ and VIM**. It provides code autocompletion, interactive generators, workspace visualizations, powerful refactorings and more. You can [install it here](/core-features/integrate-with-editors). diff --git a/docs/shared/guides/define-environment-variables.md b/docs/shared/guides/define-environment-variables.md index e2dfd9125e5d7..6926e3a4f52d5 100644 --- a/docs/shared/guides/define-environment-variables.md +++ b/docs/shared/guides/define-environment-variables.md @@ -46,7 +46,7 @@ For example: from `apps/my-app/.env`, it will notice that `NX_API_URL` already exists, so it will ignore it. We recommend nesting your **app** specific `env` files in `apps/your-app`, and creating workspace/root level `env` files -for workspace-specific settings (like the [Nx Cloud token](/core-features/share-your-cache)). +for workspace-specific settings (like the [Nx Cloud token](/core-features/remote-cache)). {% /callout %} ### Pointing to custom env files diff --git a/docs/shared/guides/global-nx.md b/docs/shared/guides/global-nx.md index 8ff36cf904c69..55fc991dc7a5a 100644 --- a/docs/shared/guides/global-nx.md +++ b/docs/shared/guides/global-nx.md @@ -3,7 +3,7 @@ Nx can be ran in a total of 3 ways: - Through your package manager (e.g. `npx nx`, `yarn nx`, or `pnpm exec nx`) -- Through [./nx or ./nx.bat](/more-concepts/nx-and-the-wrapper) +- Through [./nx or ./nx.bat](/concepts/more-concepts/nx-and-the-wrapper) - Through a global Nx installation (e.g. `nx`) With a global Nx installation, Nx looks for the local copy of Nx in your repo and hands off the process execution to it. This means that whichever version of Nx is installed locally in your repo is still the version of Nx that runs your code. For the most part, this can eliminate any issues that may arise from the global install being outdated. diff --git a/docs/shared/guides/integrated-repo-folder-structure.md b/docs/shared/guides/integrated-repo-folder-structure.md index 1859835e8d070..061f9f742375a 100644 --- a/docs/shared/guides/integrated-repo-folder-structure.md +++ b/docs/shared/guides/integrated-repo-folder-structure.md @@ -16,7 +16,7 @@ myorg/ `/libs/` contains the library projects. There are many kinds of libraries, and each library defines its own external API so that boundaries between libraries remain clear. -`/tools/` contains scripts that act on your code base. This could be database scripts, [local executors](/plugins/recipes/local-executors), or [local generators](/plugins/recipes/local-generators). +`/tools/` contains scripts that act on your code base. This could be database scripts, [local executors](/extending-nx/recipes/local-executors), or [local generators](/extending-nx/recipes/local-generators). `/nx.json` configures the Nx CLI itself. It tells Nx what needs to be cached, how to run tasks etc. diff --git a/docs/shared/guides/misc-data-persistence.md b/docs/shared/guides/misc-data-persistence.md deleted file mode 100644 index a995bfdfb50ed..0000000000000 --- a/docs/shared/guides/misc-data-persistence.md +++ /dev/null @@ -1,218 +0,0 @@ -# Using Data Persistence operators - -Managing state is a hard problem. We need to coordinate multiple backends, web workers, and UI components, all of which update the state concurrently. - -What should we store in memory and what in the URL? What about the local UI state? How do we synchronize the persistent state, the URL, and the state on the server? All these questions have to be answered when designing the state management of our applications. **Nx** provides a set of helper functions that enables the developer to manage state in Angular with an intentional synchronization strategy and handle error state. Check out the [Managing State in Angular Applications using NgRx](https://blog.nrwl.io/using-ngrx-4-to-manage-state-in-angular-applications-64e7a1f84b7b) for more detailed example of the state problem Nx is solving. - -## Optimistic Updates - -For a better user experience, the `optimisticUpdate` operator updates the state on the client application first, before updating the data on the server-side. While it addresses fetching data in order, removing the race conditions and handling error, it is optimistic about not failing to update the server. In case of a failure, when using `optimisticUpdate`, the local state on the client is already updated. The developer must provide an undo action to restore the previous state to keep it consistent with the server state. The error handling must be done in the callback, or by means of the undo action. - -```typescript -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { optimisticUpdate } from '@nx/angular'; - -@Injectable() -class TodoEffects { - updateTodo$ = createEffect(() => - this.actions$.pipe( - ofType('UPDATE_TODO'), - optimisticUpdate({ - // provides an action - run: (action: UpdateTodo) => { - return this.backend.updateTodo(action.todo.id, action.todo).pipe( - mapTo({ - type: 'UPDATE_TODO_SUCCESS', - }) - ); - }, - undoAction: (action: UpdateTodo, error: any) => { - // dispatch an undo action to undo the changes in the client state - return { - type: 'UNDO_TODO_UPDATE', - todo: action.todo, - }; - }, - }) - ) - ); - - constructor(private actions$: Actions, private backend: Backend) {} -} -``` - -## Pessimistic Updates - -To achieve a more reliable data synchronization, the `pessimisticUpdate` operator updates the server data first. When the change is reflected in the server state, changes the client state by dispatching an action. `pessimisticUpdate` method enforces the order of the fetches and error handling. - -```typescript -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { pessimisticUpdate } from '@nx/angular'; - -@Injectable() -class TodoEffects { - updateTodo$ = createEffect(() => - this.actions$.pipe( - ofType('UPDATE_TODO'), - pessimisticUpdate({ - // provides an action - run: (action: UpdateTodo) => { - // update the backend first, and then dispatch an action that will - // update the client side - return this.backend.updateTodo(action.todo.id, action.todo).pipe( - map((updated) => ({ - type: 'UPDATE_TODO_SUCCESS', - todo: updated, - })) - ); - }, - onError: (action: UpdateTodo, error: any) => { - // we don't need to undo the changes on the client side. - // we can dispatch an error, or simply log the error here and return `null` - return null; - }, - }) - ) - ); - - constructor(private actions$: Actions, private backend: Backend) {} -} -``` - -## Data Fetching - -The `fetch` operator provides consistency when fetching data. If there are multiple requests scheduled for the same action, it will only run the last one. - -```typescript -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { fetch } from '@nx/angular'; - -@Injectable() -class TodoEffects { - loadTodos$ = createEffect(() => - this.actions$.pipe( - ofType('GET_TODOS'), - fetch({ - // provides an action - run: (a: GetTodos) => { - return this.backend.getAll().pipe( - map((response) => ({ - type: 'TODOS', - todos: response.todos, - })) - ); - }, - - onError: (action: GetTodos, error: any) => { - // dispatch an undo action to undo the changes in the client state - return null; - }, - }) - ) - ); - - constructor(private actions$: Actions, private backend: Backend) {} -} -``` - -This is correct, but we can improve the performance by supplying an id of the data by using an accessor function and adding concurrency to the fetch action for different ToDo's. - -```typescript -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { fetch } from '@nx/angular'; - -@Injectable() -class TodoEffects { - loadTodo$ = createEffect(() => - this.actions$.pipe( - ofType('GET_TODO'), - fetch({ - id: (todo: GetTodo) => { - return todo.id; - }, - - // provides an action - run: (todo: GetTodo) => { - return this.backend.getTodo(todo.id).pipe( - map((response) => ({ - type: 'LOAD_TODO_SUCCESS', - todo: response.todo, - })) - ); - }, - - onError: (action: GetTodo, error: any) => { - // dispatch an undo action to undo the changes in the client state - return null; - }, - }) - ) - ); - - constructor(private actions$: Actions, private backend: Backend) {} -} -``` - -With this setup, the requests for Todo will run concurrently with the requests for Todo 2. - -## Data Fetching On Router Navigation - -Since the user can always interact with the URL directly, we should treat the router as the source of truth and the initiator of actions. In other words, the router should invoke the reducer, not the other way around. - -When our state depends on navigation, we can not assume the route change happened when a new url is triggered but when we actually know the user was able to navigate to the url. The `navigation` operator checks if an activated router state contains the passed in component type, and, if it does, runs the `run` callback. It provides the activated snapshot associated with the component and the current state. And it only runs the last request. - -```typescript -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { navigation } from '@nx/angular'; - -@Injectable() -class TodoEffects { - loadTodo$ = createEffect(() => - this.actions$.pipe( - // listens for the routerNavigation action from @ngrx/router-store - navigation(TodoComponent, { - run: (activatedRouteSnapshot: ActivatedRouteSnapshot) => { - return this.backend - .fetchTodo(activatedRouteSnapshot.params['id']) - .pipe( - map((todo) => ({ - type: 'LOAD_TODO_SUCCESS', - todo: todo, - })) - ); - }, - - onError: ( - activatedRouteSnapshot: ActivatedRouteSnapshot, - error: any - ) => { - // we can log and error here and return null - // we can also navigate back - return null; - }, - }) - ) - ); - - constructor(private actions$: Actions, private backend: Backend) {} -} -``` - -The StoreRouterConnectingModule must be configured with an appropriate serializer. The `FullRouterStateSerializer` provides the full router state instead of the `MinimalRouterStateSerializer` that is used without configuration. - -```typescript -import { NgModule } from '@angular/core'; -import { - StoreRouterConnectingModule, - FullRouterStateSerializer, -} from '@ngrx/router-store'; - -@NgModule({ - imports: [ - StoreRouterConnectingModule.forRoot({ - serializer: FullRouterStateSerializer, - }), - ], -}) -export class TodosModule {} -``` diff --git a/docs/shared/guides/misc-ngrx.md b/docs/shared/guides/misc-ngrx.md deleted file mode 100644 index 0cbf303d9fab8..0000000000000 --- a/docs/shared/guides/misc-ngrx.md +++ /dev/null @@ -1,126 +0,0 @@ -# State Management with NgRx - -Using [NgRx](https://ngrx.io) for state management in an Angular application allows you to -build out application flows that track unique events and manage the state of shared data in a reactive, explicit, and consistent way. - -## Overview - -Nx provides a schematic to build out a new NgRx feature area that manages shared state. - -The **@nx/angular** package has an `ngrx` schematic to generate files that implement best practices when using NgRx for state management. This schematic generates source files that include enhancements to NgRx for data persistence strategies, and simplified testing. - -The `ngrx` schematic generates an NgRx feature set containing the following files: - -- `actions` - Express unique events throughout your application. -- `reducer` - Handle state changes from dispatched actions to perform state changes in an immutable way. -- `effects` - Handle side effects for isolating external interactions from UI components. -- `selectors` - Composable functions that select pieces of state and update when their inputs change. -- `facade` - Optional class that provides further encapsulation of NgRx from your component. - -{% callout type="note" title="Schematics" %} -The `ngrx` schematic only provides a sub-set of schematics for the NgRx libraries. See [@ngrx/schematics](https://ngrx.io/guide/schematics) for the full set of available schematics. -{% /callout %} - -## Command - -The following command is used to run the `ngrx` schematic: - -```shell -nx g @nx/angular:ngrx --module= --no-interactive [options] -``` - -{% callout type="note" title="Command" %} -The `name` and the `--module=` arguments are required. The `no-interactive` option chooses the recommended defaults for the schematic, unless you override them. -{% /callout %} - -The most common additional options are: - -- `root` - Set up the initial NgModule imports for NgRx Store, Effects, Router-Store, and Store DevTools. -- `facade` - Optional. If you prefer to further encapsulate NgRx from your components, add an injectable facade. See the blog [Better State Management with Facades](https://blog.nrwl.io/nrwl-nx-6-2-angular-6-1-and-better-state-management-e139da2cd074#cb93) for details. - -See the [API Docs](/packages/angular/generators/ngrx) for detailed descriptions of all the available options. Also visit the [NgRx](https://ngrx.io) website for more guides and documentation about the libraries. - ---- - -## Initial Setup - -To get started with NgRx in an Angular application, you set up the root level store. As your application grows, you add feature level states, ensuring that your code follows a common pattern each time. - -The example below shows you how to setup NgRx in the root of your application. - -```shell -nx g @nx/angular:ngrx app --module=apps//src/app/app.module.ts --root -``` - -The above command applies the following changes to the provided module: - -- Registers `StoreModule.forRoot({})` in the imports array for state management, with recommended runtime checks enabled for maintaining immutable actions and state. -- Registers `EffectsModule.forRoot([])` in the `imports` array for isolation of side effects. -- Registers `StoreRouterConnectingModule.forRoot()` in the `imports` array for integration with the [Angular Router](https://angular.io/guide/router). -- Registers `StoreDevtools.instrument()` in the `imports` array for integration with the [Redux Devtools browser extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd). - -You manage separate slices of state using libraries and feature states. - -## Feature Workflow - -When building new features using NgRx, you want to manage the state from within a separate library. This allows your -state to be easily shared across other libraries and applications. The steps below go through the workflow of using NgRx within the context of a library. - -The example below generates a library to begin a new feature. For this example, `products` is used as the library name. - -```shell -nx g @nx/angular:lib products -``` - -To manage the feature state: - -- Use the `ngrx` schematic with the feature name in plural form, such as `products`. -- Provide a path to the `products` library module. - -```shell -nx g @nx/angular:ngrx products --module=libs/products/src/lib/products.module.ts --directory +state/products --no-interactive -``` - -{% callout type="note" title="Enabling Facades" %} -Use the `--facade` option to generate an injectable Facade class along with the feature. -{% /callout %} - -The following files are created, or updated: - -```text -myorg/ -├── apps/ -└── libs/ - └── products/ - └── src/ - ├── lib/ - │ ├── +state/ - │ │ ├── products.actions.ts - │ │ ├── products.effects.ts - │ │ ├── products.effects.spec.ts - │ │ ├── products.facade.ts # optional - │ │ ├── products.facade.spec.ts # optional - │ │ ├── products.models.ts - │ │ ├── products.reducer.ts - │ │ ├── products.reducer.spec.ts - │ │ ├── products.selectors.ts - │ │ └── products.selectors.spec.ts - │ ├── products.module.spec.ts - │ └── products.module.ts - └── index.ts -``` - -The above command also does the following changes: - -- Updates the feature module and registers `StoreModule.forFeature()` with the name of your feature state in the `imports` array. -- Updates the feature module and registers `EffectsModule.forFeature()` in the `imports` array. - -The feature library's barrel `index.ts` is also updated to export the updated _public API_ for the state including: - -- The NgRx selectors. -- The NgRx feature reducer. -- The optional facade class for the NgRx feature. - -{% callout type="warning" title="Naming collisions" %} -When generating multiple feature states within a single library, make sure there are no naming collisions in the barrel `index.ts` file. -{% /callout %} diff --git a/docs/shared/guides/module-federation/faster-builds.md b/docs/shared/guides/module-federation/faster-builds.md index 8000dc2f7f376..898649906923c 100644 --- a/docs/shared/guides/module-federation/faster-builds.md +++ b/docs/shared/guides/module-federation/faster-builds.md @@ -440,7 +440,7 @@ first before building the remotes. ## Summary -You could use Module Federation to implement [micro frontends](/more-concepts/micro-frontend-architecture), but this +You could use Module Federation to implement [micro frontends](/concepts/more-concepts/micro-frontend-architecture), but this guide showed how to use it to speed up your builds. Module Federation allows you to split a single build process into multiple processes which can run in parallel or even diff --git a/docs/shared/guides/module-federation/micro-frontend-architecture.md b/docs/shared/guides/module-federation/micro-frontend-architecture.md index b7c48c3749595..3d9eff4e588b3 100644 --- a/docs/shared/guides/module-federation/micro-frontend-architecture.md +++ b/docs/shared/guides/module-federation/micro-frontend-architecture.md @@ -1,9 +1,9 @@ # Micro Frontend Architecture -Since version 14, Nx provides out-of-the-box [Module Federation](/recipes/module-federation/faster-builds) support to both React +Since version 14, Nx provides out-of-the-box [Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) support to both React and Angular. The Micro Frontend (MFE) architecture builds on top of Module Federation by providing _independent deployability_. -If you have not read the [Module Federation guide](/recipes/module-federation/faster-builds) yet, we recommend that you read it +If you have not read the [Module Federation guide](/concepts/more-concepts/faster-builds-with-module-federation) yet, we recommend that you read it before continuing with this MFE guide. ## When should I use micro frontend architecture? @@ -17,7 +17,7 @@ of MFEs and decide whether it makes sense for your own teams. logic that breaks compatibility with remotes. If you are looking at optimizing builds and do not need independent deployments, we recommend reading our guide on -[Faster Builds with Module Federation](/recipes/module-federation/faster-builds). +[Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation). If you need to use MFEs, keep reading, and we'll examine the architecture and strategies to deal with shared libraries and deployments. @@ -29,7 +29,7 @@ With MFE architecture, a large application is split into: 1. A single **Host** application that references external... 2. **Remote** applications, which handle a single domain or feature. -In a normal Module Federation setup, we [recommend setting up implicit dependencies](/recipes/module-federation/faster-builds#architectural-overview) +In a normal Module Federation setup, we [recommend setting up implicit dependencies](/concepts/more-concepts/faster-builds-with-module-federation#architectural-overview) from the host application to remote applications. However, in an MFE architecture you _do not_ want these dependencies to exist between host and remotes. diff --git a/docs/shared/guides/nx-and-angular-cli.md b/docs/shared/guides/nx-and-angular-cli.md index 7ebff2fb303ac..ab03f4c8354bb 100644 --- a/docs/shared/guides/nx-and-angular-cli.md +++ b/docs/shared/guides/nx-and-angular-cli.md @@ -24,7 +24,7 @@ If you haven't used Nx before and used the Angular CLI, you probably ran `ng upd - Fix migrations that "almost work". - Commit a partially migrated state. - Change versions of packages to match org requirements. -- [Opt out of Angular updates when updating Nx versions](/recipes/other/advanced-update#choosing-optional-package-updates-to-apply) as long as [the Angular version is still supported](/packages/angular/documents/angular-nx-version-matrix) +- [Opt out of Angular updates when updating Nx versions](/recipes/tips-n-tricks/advanced-update#choosing-optional-package-updates-to-apply) as long as [the Angular version is still supported](/packages/angular/documents/angular-nx-version-matrix) `nx migrate` does this by splitting the process into two steps. `nx migrate latest` creates a `migrations.json` file with a list of all the migrations that are needed by Nx, Angular and other packages. You then have a chance to modify that file before running `nx migrate --run-migrations` to actually execute those migrations. diff --git a/docs/shared/guides/react-native.md b/docs/shared/guides/react-native.md index c78b2f4d6edb0..b5b0de8799730 100644 --- a/docs/shared/guides/react-native.md +++ b/docs/shared/guides/react-native.md @@ -157,8 +157,8 @@ Nx allows you to create libraries with just one command. Some reasons you might - Publish a package to be used outside the monorepo - Better visualize the architecture using `npx nx graph` -For more information on Nx libraries, see our documentation on [Creating Libraries](/more-concepts/creating-libraries) -and [Library Types](/more-concepts/library-types). +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: diff --git a/docs/shared/guides/turbo-and-nx.md b/docs/shared/guides/turbo-and-nx.md index 764f60eacf45e..f475134dd53a8 100644 --- a/docs/shared/guides/turbo-and-nx.md +++ b/docs/shared/guides/turbo-and-nx.md @@ -32,7 +32,7 @@ The starting point of any non-trivial monorepo management tool is to be able to - Turborepo only analyzes package.json files to understand how projects relate to each other. Built-in Nx plugins also analyze package.json files but in addition they analyze JS/TS files, so you don't have to have bogus package.json files (that you don’t use for the purposes of installing packages or publishing) in your repo. There are plugins for Nx that do that for other languages (e.g., Golang, .Net). - Since the computation of the project graph can take a lot of time for complex workspaces, both Nx and Turborepo have a daemon process to create the graph in the background. -- **Nx has [project boundary rules](/core-features/enforce-project-boundaries), which are essential for any monorepo with multiple teams contributing.** You can say that some things in the monorepo are private to your team so they cannot be depended on by other teams. Turborepo doesn't have project boundary rules. **Project boundary rules prevent the monorepo from becoming a “big ball of mud”.** +- **Nx has [module boundary rules](/core-features/enforce-module-boundaries), which are essential for any monorepo with multiple teams contributing.** You can say that some things in the monorepo are private to your team so they cannot be depended on by other teams. Turborepo doesn't have project boundary rules. **Project boundary rules prevent the monorepo from becoming a “big ball of mud”.** #### 3. Project graph visualization diff --git a/docs/shared/guides/unknown-local-cache.md b/docs/shared/guides/unknown-local-cache.md new file mode 100644 index 0000000000000..ec9151683cbbc --- /dev/null +++ b/docs/shared/guides/unknown-local-cache.md @@ -0,0 +1,86 @@ +# Unknown Local Cache Error + +This document will explain why the following error happens and how to address it. + +``` +NX Invalid Cache Directory for Task "myapp:build" + +The local cache artifact in "node_modules/.cache/nx/786524780459028195" was not been generated on this machine. +As a result, the cache's content integrity cannot be confirmed, which may make cache restoration potentially unsafe. +If your machine ID has changed since the artifact was cached, run "nx reset" to fix this issue. +Read about the error and how to address it here: https://nx.dev/recipes/troubleshooting/unknown-local-cache +``` + +## Nx Tracks Cache Source + +Nx can cache tasks, which can drastically speed up your CI and local builds. However, this comes with the potential risk +of "cache poisoning", where cache artifacts could be intentionally or inadvertently overwritten. If another user +executes a task that matches the hash of the tainted artifact, they could retrieve the corrupted artifact and use it as +the outcome of the task. Nx and Nx Cloud contain several safeguards to minimize the likelihood of cache poisoning or, in +the case of Nx Cloud, completely prevent it. + +The error above is one such safeguard. + +Nx trusts the local cache. If you executed a task and stored the corresponding cached artifact on your machine, you can +safely restore it on the same machine without worrying about cache poisoning. After all, in order to tamper with the +cache artifact, the actor would need access to the machine itself. + +However, when artifacts in the local cache are created by a different machine, we cannot make such assumption. By +default, Nx will refuse to use such artifacts and will throw the "Invalid Cache Directory" error. + +## Your MachineId Has Changed + +Upgrading your computer's hardware may alter its Machine ID, yielding the error above. To fix it execute `nx reset` to +remove all the cache directories created under the previous Machine ID. After doing so, you should no longer see the +error. After doing so, you should no longer see the error. + +## You Share Cache with Another Machine Using a Network Drive + +You can prefix any Nx command with `NX_REJECT_UNKNOWN_LOCAL_CACHE=0` to ignore the error ( +e.g., `NX REJECT_UNKNOWN_LOCAL_CACHE=0 nx run-many -t build test`). This is similar to +setting `NODE_TLS_REJECT_UNAUTHORIZED=0` to ignore any errors stemming form self-signed certificates. Even though it +will make it work, this approach is discouraged. + +Storing Nx's local cache on a network drive can present security risks. When a network drive is shared, every CI run has +access to all the previously created Nx cache artifacts. Hence, it is plausible for every single artifact - for every +single task hash - to be accessed without leaving any trace. This is feasible due to the network drive's capability to +allow overwrites. + +Instead of sharing the network drive, we highly recommend you to implement the `RemoteCache` interface. + +## Implementing Remote Cache Interface + +This is the interface: + +```typescript +interface RemoteCache { + retrieve(hash: string, cachePath: string); + + store(hash: string, cachePath: string); +} +``` + +> You will need to wrap the default tasks runner to provide the remote cache implementation. + +## How Nx Cloud Makes Sure Sharing Cache is Safe + +The Nx Cloud runner provides an implementation of `RemoteCache` which does the following things making sharing the cache safe: + +1. **Immutable Artifacts:** Nx Cloud allows you to create and store new artifacts without the ability to override the + existing ones. This prevents any possibility of poisoning an existing artifact. This is achieved by managing the + cache using short-lived signed URLs. + +2. **Artifact Accessibility:** Nx Cloud provides access to the cache artifact specifically for the task that is + currently being executed. It restricts the ability to list all cache artifacts. + +3. **Visibility Control:** Nx Cloud comes with options to manage the visibility of your cache artifacts. For instance, + the cache artifacts created in `main` might be accessible by anyone across any branch, whereas the artifacts created + in your PR could be shared only within your PR runs. + +4. **Access Token Traceability:** Nx Cloud keeps a record of the access token used to create a cache artifact. In case + an access token gets compromised it can be easily removed, in turn deleting all the cache artifacts that were created + using it. + +Nx Cloud is not the only remote cache you can use. If you are using a different remote cache or using your +own implementation, we would highly recommend ensuring that the same safety mechanisms as Nx Cloud have been put in +place. diff --git a/docs/shared/guides/use-environment-variables-in-angular.md b/docs/shared/guides/use-environment-variables-in-angular.md index f718584449e78..5477bb5376b1b 100644 --- a/docs/shared/guides/use-environment-variables-in-angular.md +++ b/docs/shared/guides/use-environment-variables-in-angular.md @@ -101,6 +101,14 @@ Now, when we define variables in our `.env` file, such as... NX_API_URL=http://localhost:3333 ``` +{% callout type="note" title="Set environment variables from the terminal" %} +Alternatively, you can set the variable when running a terminal command by using: + +- MacOS & Linux: `NX_API_URL=http://localhost:9999 npm run build-prod` +- Windows: `set NX_API_URL=http://localhost:9999 & npm run build-prod` + +{% /callout %} + Finally, We can use environment variables in our code. For example, ```typescript {% fileName="apps/myapp/src/main.ts" %} diff --git a/docs/shared/guides/why-monorepos.md b/docs/shared/guides/why-monorepos.md index 68c1999870a72..90ae72a13071a 100644 --- a/docs/shared/guides/why-monorepos.md +++ b/docs/shared/guides/why-monorepos.md @@ -8,13 +8,13 @@ If you are familiar with Lerna or Yarn workspaces, check out [this guide](/recip ## What are the benefits of a monorepo? -- **Shared code and visibility** - [Keeps your code DRY across your entire organization.](/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/more-concepts/code-sharing) 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. - **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](/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/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. ## Why not just code collocation? diff --git a/docs/shared/images/caching/cache-terminal-animation.mp4 b/docs/shared/images/caching/cache-terminal-animation.mp4 new file mode 100644 index 0000000000000..3a4428e0630de Binary files /dev/null and b/docs/shared/images/caching/cache-terminal-animation.mp4 differ diff --git a/docs/shared/incremental-builds.md b/docs/shared/incremental-builds.md index 56a4596f16728..bca58cbe7a097 100644 --- a/docs/shared/incremental-builds.md +++ b/docs/shared/incremental-builds.md @@ -8,7 +8,7 @@ nx g @nx/react:app myapp nx g @nx/react:lib mylib ``` -...and then import the library from the application. In this case, `mylib` isn't a buildable library. We cannot test and lint it independently, but the only way to build it is by building some application using it (in this case `myapp`). The default setup is to use Webpack, which builds "mylib" and bundles it directly into "myapp". +...and then import the library from the application. In this case, `mylib` isn't a buildable library. We can test and lint it independently, but the only way to build it is by building some application using it (in this case `myapp`). The default setup is to use Webpack, which builds "mylib" and bundles it directly into "myapp". This provides the best dev experience for small and medium-size applications, because Webpack is optimized for this scenario. But as your application keeps growing, the dev experience degrades. > The **duration** of the invoked operations should be **proportional** to the **size of the change** @@ -27,7 +27,7 @@ On the other hand, the executor of a **buildable library**, performs a subset of nx g @nx/react:lib mylib --buildable ``` -Read more about [Publishable and Buildable Nx Libraries here.](/more-concepts/buildable-and-publishable-libraries) +Read more about [Publishable and Buildable Nx Libraries here.](/concepts/more-concepts/buildable-and-publishable-libraries) ## Nx computation cache and Nx Cloud @@ -66,7 +66,33 @@ The downsides of incremental builds: If you are only planning to use incremental builds to speed up your CI, then the watch mode concern is irrelevant, and the only thing you need to assess is whether the benefits of skipping the compilation outweigh the costs of initializing the TypeScript compiler several times. -## Custom Serve Target +## Using the @nx/js:tsc Batch Implementation + +{% callout type="check" title="Available since Nx 16.5.0" %} +The `@nx/js:tsc` batch implementation was introduced in Nx **16.5.0**. +{% /callout %} + +If you're using the `@nx/js:tsc` to build your projects, you can opt-in to use its batch implementation. The batch implementation uses the [TypeScript APIs for incremental builds](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript) and batches the execution of the tasks into a single process. This results in a much faster build time when compared to the default implementation (the bigger the task graph to run, the more the performance improvements). + +{% callout type="warning" title="Experimental feature" %} +Executing tasks in batch mode is an experimental feature. +{% /callout %} + +{% callout type="info" title="Requirements" %} +Building a project with the `@nx/js:tsc` executor in batch mode requires all dependent projects to be buildable and built using the `@nx/js:tsc` executor. +{% /callout %} + +To run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`: + +```shell +NX_BATCH_MODE=true nx build my-project +``` + +For optimal performance, you could set the `clean` option to `false`. Otherwise, the executor cleans the output folder before running the build, which results in the loss of the [`.tsbuildinfo` file](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile) and, consequently, the loss of important optimizations performed by TypeScript. This is not a requirement. Even if the `clean` option is not set to `false` there are other important optimizations that are performed by the batch implementation. + +You can get a sense of the performance improvements over using the `@nx/js:tsc` default implementation in the following example repository: https://github.com/nrwl/large-ts-monorepo. + +## Custom Serve Target with Webpack If you are implementing a custom serve command, you can use `WebpackNxBuildCoordinationPlugin` provided by `@nx/webpack`. It's a webpack plugin you can use to coordinate the compiling of the libs and the webpack linking. @@ -78,4 +104,4 @@ But there are other ways to make the build process incremental. One of them is u When using WebPack Module Federation, you split the application into multiple webpack builds. Imagine the application has 3 big sections, and they are built using 3 webpack builds: `W1`, `W2`, and `W3`. Each of them has to build shared code in addition to building the corresponding application section code. So the time it takes to build all of them (`W1` + `W2` + `W3`) will be greater than `W`. However, if you change only Section 1, you will only need to run `W1`. `W2` and `W3` will be retrieved from cache. In addition, `W1`, `W2`, and `W3` can run on separate machines. Because of that, both the CI time and the local serve time can be drastically reduced. -Learn more: [Faster Builds with Module Federation](/recipes/module-federation/faster-builds) +Learn more: [Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) diff --git a/docs/shared/migration/adding-to-existing-project.md b/docs/shared/migration/adding-to-existing-project.md index 4cd829e17c01a..98b3134d88c47 100644 --- a/docs/shared/migration/adding-to-existing-project.md +++ b/docs/shared/migration/adding-to-existing-project.md @@ -109,13 +109,13 @@ For example, excluding markdown files from the `lint` task cache: This includes all TypeScript files, but excludes markdown files. As a result, changing your README won't invalidate your "lint cache". -Learn more about [Nx Inputs](/more-concepts/customizing-inputs). +Learn more about [Nx Inputs](/concepts/more-concepts/customizing-inputs). ## Learn More {% cards %} -{% card title="Customizing Inputs and Named Inputs" description="Learn more about how to fine-tune caching with custom inputs" type="documentation" url="/more-concepts/customizing-inputs" /%} +{% card title="Customizing Inputs and Named Inputs" description="Learn more about how to fine-tune caching with custom inputs" type="documentation" url="/concepts/more-concepts/customizing-inputs" /%} {% card title="Cache Task Results" description="Learn more about how caching works" type="documentation" url="/core-features/cache-task-results" /%} diff --git a/docs/shared/migration/adding-to-monorepo.md b/docs/shared/migration/adding-to-monorepo.md index ecaad25e2f4ba..226c401d58ffe 100644 --- a/docs/shared/migration/adding-to-monorepo.md +++ b/docs/shared/migration/adding-to-monorepo.md @@ -9,7 +9,7 @@ Nx has first-class support for [package-based monorepos](/getting-started/tutori - fast [task scheduling](/core-features/run-tasks) - support for [task pipelines](/concepts/task-pipeline-configuration) - [caching](/core-features/cache-task-results) -- optionally [remote caching with Nx Cloud](/core-features/share-your-cache) +- optionally [remote caching with Nx Cloud](/core-features/remote-cache) - optionally [distributed task execution with Nx Cloud](/core-features/distribute-task-execution) This is a low-impact operation because all that needs to be done is to install the `nx` package at the root level and add an `nx.json` for configuring caching and task pipelines. @@ -90,7 +90,7 @@ This allows for incrementally adopting Nx in your existing workspace. {% card title="Nx Ignore" description="Learn about how to ignore certain projects using .nxignore" type="documentation" url="/reference/nxignore" /%} -{% card title="Nx and Turbo" description="Read about how Nx compares to Turborepo" url="/more-concepts/turbo-and-nx" /%} +{% card title="Nx and Turbo" description="Read about how Nx compares to Turborepo" url="/concepts/more-concepts/turbo-and-nx" /%} {% card title="Nx and Lerna" description="Read about how Nx and Lerna can be used together" url="/recipes/adopting-nx/lerna-and-nx" /%} diff --git a/docs/shared/migration/angular-integrated.md b/docs/shared/migration/angular-integrated.md deleted file mode 100644 index 1abdbc117b67f..0000000000000 --- a/docs/shared/migration/angular-integrated.md +++ /dev/null @@ -1,98 +0,0 @@ -# Migrating an Angular CLI workspace to an Integrated Nx Monorepo - -If you want to migrate your Angular CLI project to an [Integrated Nx Monorepo](/concepts/integrated-vs-package-based#integrated-repos), run the following command: - -```shell -npx nx@latest init --integrated -``` - -The command applies the following changes to your workspace: - -- Installs the `nx`, `@nx/angular` and `@nx/workspace` packages. -- Moves your applications into the `apps` folder, and updates the relevant file paths in your configuration files. -- Moves your e2e suites into the `apps/-e2e` folder, and updates the relevant file paths in your configuration files. -- Moves your libraries into the `libs` folder, and updates the relevant file paths in your configuration files. -- Updates your `package.json` scripts to use `nx` instead of `ng`. -- Splits your `angular.json` into `project.json` files for each project with updated paths. - -After the changes are applied, your workspace file structure should look similar to the one below: - -```text -/ -├── apps/ -│ └─ / -│ ├── src/ -│ │ ├── app/ -│ │ ├── assets/ -│ │ ├── favicon.ico -│ │ ├── index.html -│ │ ├── main.ts -│ │ └── styles.css -│ ├── project.json -│ ├── tsconfig.app.json -│ └── tsconfig.spec.json -├── libs/ -│ └── / -│ ├── src/ -│ ├── ng-package.json -│ ├── package.json -│ ├── project.json -│ ├── README.md -│ ├── tsconfig.lib.json -│ ├── tsconfig.lib.prod.json -│ └── tsconfig.spec.json -├── tools/ -├── .editorconfig -├── .gitignore -├── .prettierignore -├── .prettierrc -├── karma.conf.js -├── nx.json -├── package.json -├── README.md -└── tsconfig.base.json -``` - -Your workspace is now powered by Nx! You can verify that your application still runs as intended: - -- To serve, run `nx serve `. -- To build, run `nx build `. -- To run unit tests, run `nx test `. -- To see your project graph, run `nx graph`. - -> Your project graph will grow as you add and use more applications and libraries. You can add the `--watch` flag to `nx graph` to see the changes in-browser as you add them. - -## Older Versions of Angular - -Support for workspaces with multiple applications and libraries was added in Nx v14.1.0. If you are migrating using an older version of Nx, your workspace can only contain one application and no libraries in order to use the automated migration, otherwise, you can still [migrate manually](/recipes/adopting-nx-angular/angular-manual). - -## Modified Folder Structure - -The automated migration supports Angular CLI workspaces with a standard structure, configurations and features. If your workspace has deviated from what the Angular CLI generates, you might not be able to use the automated migration and you will need to [manually migrate your workspace](/recipes/adopting-nx-angular/angular-manual). - -Currently, the automated migration supports workspaces using the following executors (builders): - -- `@angular-devkit/build-angular:browser` -- `@angular-devkit/build-angular:dev-server` -- `@angular-devkit/build-angular:extract-i18n` -- `@angular-devkit/build-angular:karma` -- `@angular-devkit/build-angular:ng-packagr` -- `@angular-devkit/build-angular:protractor` -- `@angular-devkit/build-angular:server` -- `@angular-eslint/builder:lint` -- `@cypress/schematic:cypress` -- `@nguniversal/builders:prerender` -- `@nguniversal/builders:ssr-dev-server` - -Support for other executors may be added in the future. - -## Learn More - -Learn more about the advantages of Nx in the following guides: - -- [Using Cypress for e2e tests](/packages/cypress) -- [Using Jest for unit tests](/packages/jest) -- [Computation Caching](/concepts/how-caching-works) -- [Rebuilding and Retesting What is Affected](/concepts/affected) -- [Integrate with Editors](/core-features/integrate-with-editors) -- [Advanced Angular Micro Frontends with Dynamic Module Federation](/recipes/module-federation/dynamic-module-federation-with-angular) diff --git a/docs/shared/migration/angular-manual.md b/docs/shared/migration/angular-manual.md index 0eb3a72a78652..85e06967c09b0 100644 --- a/docs/shared/migration/angular-manual.md +++ b/docs/shared/migration/angular-manual.md @@ -4,7 +4,7 @@ If you are using older versions of Angular (version 13 or lower), make sure to use the appropriate version of Nx that matches your version of Angular. See the [Nx and Angular Version Compatibility Matrix](/packages/angular/documents/angular-nx-version-matrix) to find the correct version. The generated files will also be slightly different. {% /callout %} -If you are unable to automatically transform your Angular CLI workspace to an [Nx Integrated workspace](/recipes/adopting-nx-angular/angular-integrated), there are some manual steps you can take to move your project(s) into an Nx workspace. +If you are unable to automatically transform your Angular CLI workspace to an [Nx workspace](/recipes/angular/migration/angular), there are some manual steps you can take to move your project(s) into an Nx workspace. ### Generating a new workspace diff --git a/docs/shared/migration/angular-multiple.md b/docs/shared/migration/angular-multiple.md index 7e3ee56bc5528..6dd60ba035334 100644 --- a/docs/shared/migration/angular-multiple.md +++ b/docs/shared/migration/angular-multiple.md @@ -17,4 +17,4 @@ The following video tutorial walks you through such a scenario. {% youtube src="https://www.youtube.com/embed/M5NwkRNrpK0" title="Nx Tutorial: Migrate Multiple Angular CLI apps into a Single Nx Monorepo" -width="100%" /%} +/%} diff --git a/docs/shared/migration/lerna-and-nx.md b/docs/shared/migration/lerna-and-nx.md index 175142285619b..806c1b0b7fbea 100644 --- a/docs/shared/migration/lerna-and-nx.md +++ b/docs/shared/migration/lerna-and-nx.md @@ -20,7 +20,7 @@ For a discussion on #2, see [dependency management](#dependency-management) belo Nx comes with a powerful task scheduler that intelligently runs operations and makes sure they are quick. This happens in a variety of ways: -- **Parallelization and task dependencies -** Nx automatically [knows how your projects relate to each other](/more-concepts/how-project-graph-is-built). As a result, if `project-a` depends on `project-b` and you run the build command for `project-a`, Nx first runs the builds for all of `project-a`'s dependencies and then the invoked project itself. Nx sorts these tasks to maximize parallelism. +- **Parallelization and task dependencies -** Nx automatically [knows how your projects relate to each other](/concepts/more-concepts/how-project-graph-is-built). As a result, if `project-a` depends on `project-b` and you run the build command for `project-a`, Nx first runs the builds for all of `project-a`'s dependencies and then the invoked project itself. Nx sorts these tasks to maximize parallelism. - **Only run what changed -** Using [Nx affected commands](/concepts/affected) you only really execute tasks on the projects that changed, compared to a given baseline (usually the main branch). - **Caching -** You get Nx's [computation caching](/concepts/how-caching-works) for free. All operations, including artifacts and terminal output are restored from the cache (if present) in a completely transparent way without disrupting your DX. No configuration needed. Obviously this results in an incredible speed improvement. - **Distributed Task Execution -** This is unique to Nx. In combination with Nx Cloud your tasks are automatically distributed across CI agents, taking into account build order, maximizing parallelization and thus agent utilization. It even learns from previous runs to better distribute tasks! [Learn more](/concepts/dte) diff --git a/docs/shared/migration/manual.md b/docs/shared/migration/manual.md index cfd2990ec65c5..cf4b29cad10ec 100644 --- a/docs/shared/migration/manual.md +++ b/docs/shared/migration/manual.md @@ -69,11 +69,11 @@ In general, you should not replace the configuration files provided for you. You In addition to configuration files for external libraries, your Nx workspace will have configuration files for Nx itself. This will be `angular.json` for workspaces using the Angular CLI and `project.json` files for workspaces using the Nx CLI. This file will define all of the individual projects in your workspace (of which your application is one) and the tasks available for them. -For example, your generated application should have four [tasks available](/plugin-features/use-task-executors) for it: `build`, `serve`, `lint`, and `test`. Each of these comes with its own configuration. If you find you need to adjust the configuration of a task for your codebase, this is the place to begin looking. +For example, your generated application should have four [tasks available](/core-features/plugin-features/use-task-executors) for it: `build`, `serve`, `lint`, and `test`. Each of these comes with its own configuration. If you find you need to adjust the configuration of a task for your codebase, this is the place to begin looking. These workspace configuration files can seem a little long and intimidating. The Nx Console can help you navigate it more easily with its Workspace JSON panel. By clicking on a project in your workspace, it will navigate you to the right place in the workspace file to begin making edits. -Additionally, there is an `nx.json` file that contains metadata about your projects. [This metadata includes tags](/core-features/enforce-project-boundaries) that can help you impose constraints on your applications and library dependencies. +Additionally, there is an `nx.json` file that contains metadata about your projects. [This metadata includes tags](/core-features/enforce-module-boundaries) that can help you impose constraints on your applications and library dependencies. ## Migrating your code @@ -157,7 +157,7 @@ nx format:write Nx offers built-in tasks for the most common needs: `serve`, `build`, `test`, `e2e`, and `lint`. You likely have additional tasks that are needed to manage or deploy your codebase. These tasks might include deployment, i18n workflows, or uploading assets to CDNs. These tasks can be set up as scripts that you run manually with node, ts-node, or npm scripts. You can migrate those tasks over as-is, to begin with. -You should consider implementing them as Nx tasks which should be a quick transition with the `run-commands` builder. [The `run-commands` executor](/recipes/executors/run-commands-executor) will allow you to run any custom commands you need as an Nx task. By implementing these commands in an Nx task, they are able to take advantage of the project graph in Nx and only run when necessary. They are also able to be cached and only be re-run when necessary. +You should consider implementing them as Nx tasks which should be a quick transition with the `run-commands` builder. [The `run-commands` executor](/recipes/tips-n-tricks/run-commands-executor) will allow you to run any custom commands you need as an Nx task. By implementing these commands in an Nx task, they are able to take advantage of the project graph in Nx and only run when necessary. They are also able to be cached and only be re-run when necessary. Your use-case may also be covered by one of our community plugins. Plugin authors are able to extend the functionality of Nx through our plugin API. @@ -196,4 +196,4 @@ It’s important to remember: don’t just drop your code anywhere! Always gener If you’re consolidating multiple repositories or libraries into a single Nx workspace, you may have concerns about code boundaries. Previously, you may have had well-established boundaries by separating code into different repositories or having a public API for a library. Nx features a tagging system that allows you to enforce these code boundaries in a granular way. Each project can be tagged, and you can constrain dependencies based on these tags. -[Learn more about tags and dependency constraints](/core-features/enforce-project-boundaries) +[Learn more about tags and dependency constraints](/core-features/enforce-module-boundaries) diff --git a/docs/shared/migration/migration-angular.md b/docs/shared/migration/migration-angular.md index a59e8e8c48e48..618753a0faa85 100644 --- a/docs/shared/migration/migration-angular.md +++ b/docs/shared/migration/migration-angular.md @@ -20,6 +20,87 @@ This will enable you to use the Nx CLI in your existing Angular CLI workspace wh **Note:** The changes will be slightly different for Angular 13 and lower. +## Migrating to an Integrated Nx Monorepo + +If you want to migrate your Angular CLI project to an [Integrated Nx Monorepo](/concepts/integrated-vs-package-based#integrated-repos), run the following command: + +```shell +npx nx@latest init --integrated +``` + +The command applies the following changes to your workspace: + +- Installs the `nx`, `@nx/angular` and `@nx/workspace` packages. +- Moves your applications into the `apps` folder, and updates the relevant file paths in your configuration files. +- Moves your e2e suites into the `apps/-e2e` folder, and updates the relevant file paths in your configuration files. +- Moves your libraries into the `libs` folder, and updates the relevant file paths in your configuration files. +- Updates your `package.json` scripts to use `nx` instead of `ng`. +- Splits your `angular.json` into `project.json` files for each project with updated paths. + +After the changes are applied, your workspace file structure should look similar to the one below: + +```text +/ +├── apps/ +│ └─ / +│ ├── src/ +│ │ ├── app/ +│ │ ├── assets/ +│ │ ├── favicon.ico +│ │ ├── index.html +│ │ ├── main.ts +│ │ └── styles.css +│ ├── project.json +│ ├── tsconfig.app.json +│ └── tsconfig.spec.json +├── libs/ +│ └── / +│ ├── src/ +│ ├── ng-package.json +│ ├── package.json +│ ├── project.json +│ ├── README.md +│ ├── tsconfig.lib.json +│ ├── tsconfig.lib.prod.json +│ └── tsconfig.spec.json +├── tools/ +├── .editorconfig +├── .gitignore +├── .prettierignore +├── .prettierrc +├── karma.conf.js +├── nx.json +├── package.json +├── README.md +└── tsconfig.base.json +``` + +### Older Versions of Angular + +Support for workspaces with multiple applications and libraries was added in Nx v14.1.0. If you are migrating using an older version of Nx, your workspace can only contain one application and no libraries in order to use the automated migration, otherwise, you can still [migrate manually](/recipes/angular/migration/angular-manual). + +### Modified Folder Structure + +The automated migration supports Angular CLI workspaces with a standard structure, configurations and features. If your workspace has deviated from what the Angular CLI generates, you might not be able to use the automated migration and you will need to [manually migrate your workspace](/recipes/angular/migration/angular-manual). + +Currently, the automated migration supports workspaces using the following executors (builders): + +- `@angular-devkit/build-angular:browser` +- `@angular-devkit/build-angular:dev-server` +- `@angular-devkit/build-angular:extract-i18n` +- `@angular-devkit/build-angular:karma` +- `@angular-devkit/build-angular:ng-packagr` +- `@angular-devkit/build-angular:protractor` +- `@angular-devkit/build-angular:server` +- `@angular-eslint/builder:lint` +- `@cypress/schematic:cypress` +- `@nguniversal/builders:prerender` +- `@nguniversal/builders:ssr-dev-server` + +Support for other executors may be added in the future. + +## After migration + Your workspace is now powered by Nx! You can verify that your application still runs as intended: - To serve, run `nx serve `. @@ -27,7 +108,9 @@ Your workspace is now powered by Nx! You can verify that your application still - To run unit tests, run `nx test `. - To see your project graph, run `nx graph`. -> Your project graph will grow as you add and use more applications and libraries. +> Your project graph will grow as you add and use more applications and libraries. You can add the `--watch` flag to `nx graph` to see the changes in-browser as you add them. + +## Learn More Learn more about the advantages of Nx in the following guides: @@ -35,13 +118,15 @@ Learn more about the advantages of Nx in the following guides: - [Using Jest for unit tests](/packages/jest) - [Computation Caching](/concepts/how-caching-works) - [Rebuilding and Retesting What is Affected](/concepts/affected) +- [Integrate with Editors](/core-features/integrate-with-editors) +- [Advanced Angular Micro Frontends with Dynamic Module Federation](/recipes/angular/dynamic-module-federation-with-angular) ## From Nx Console {% youtube src="https://www.youtube.com/embed/vRj9SNVYKrE" title="Nx Console Updates 17.15.0" -width="100%" /%} +/%} Nx Console no longer supports the Angular CLI. Angular CLI users will receive a notice, asking if they want to switch to Nx. @@ -65,12 +150,10 @@ If you're not ready to make the change yet, you can come back to this later: {% cards %} -{% card title="Nx and the Angular CLI" description="Differences between Nx and the Angular CLI" type="documentation" url="/more-concepts/nx-and-angular" /%} - -{% card title="Angular CLI to Integrated Nx Workspace" description="Change the folder structure to use an integrated style" type="documentation" url="/recipes/adopting-nx-angular/angular-integrated" /%} +{% card title="Nx and the Angular CLI" description="Differences between Nx and the Angular CLI" type="documentation" url="/concepts/more-concepts/nx-and-angular" /%} -{% card title="Angular CLI manual migration" description="Add Nx by hand" type="documentation" url="/recipes/adopting-nx-angular/angular-manual" /%} +{% card title="Angular CLI manual migration" description="Add Nx by hand" type="documentation" url="/recipes/angular/migration/angular-manual" /%} -{% card title="Multiple Angular Repositories to one Nx Workspace" description="Combine multiple Angular CLI workspaces into one Nx workspace" type="documentation" url="/recipes/adopting-nx-angular/angular-multiple" /%} +{% card title="Multiple Angular Repositories to one Nx Workspace" description="Combine multiple Angular CLI workspaces into one Nx workspace" type="documentation" url="/recipes/angular/migration/angular-multiple" /%} {% /cards %} diff --git a/docs/shared/migration/migration-angularjs.md b/docs/shared/migration/migration-angularjs.md index 09ee504a6c8f8..f0f2a2c89afc2 100644 --- a/docs/shared/migration/migration-angularjs.md +++ b/docs/shared/migration/migration-angularjs.md @@ -365,7 +365,7 @@ But migrating AngularJS code means we need to switch some of our tools to a more npm install -D @nx/web babel-plugin-angularjs-annotate ``` -Nx already has most of what you need for webpack added as a dependency. `@nx/web` contains the [executors](/plugin-features/use-task-executors) we need to use to build and serve the application with webpack and +Nx already has most of what you need for webpack added as a dependency. `@nx/web` contains the [executors](/core-features/plugin-features/use-task-executors) we need to use to build and serve the application with webpack and `babel-plugin-angularjs-annotate` is going to accomplish the same thing that `browserify-ngannotate` previously did in gulp: add dependency injection annotations. Start with a `webpack.config.js` file in your application’s root directory: diff --git a/docs/shared/monorepo-ci-azure.md b/docs/shared/monorepo-ci-azure.md index dd2292f19d82c..5447deed3ce1e 100644 --- a/docs/shared/monorepo-ci-azure.md +++ b/docs/shared/monorepo-ci-azure.md @@ -8,7 +8,7 @@ Nx needs additional Git history available for `affected` to function correctly. {% /callout %} -Unlike `GitHub Actions` and `CircleCI`, you don't have the metadata to help you track the last successful run on `main`. In the example below, the base is set to `HEAD~1` (for push) or branching point (for pull requests), but a more robust solution would be to tag an SHA in the main job once it succeeds and then use this tag as a base. You can also try [using the devops CLI within the pipeline yaml](/recipes/other/azure-last-successful-commit). See the [nx-tag-successful-ci-run](https://github.com/nrwl/nx-tag-successful-ci-run) and [nx-set-shas](https://github.com/nrwl/nx-set-shas) (version 1 implements tagging mechanism) repositories for more information. +Unlike `GitHub Actions` and `CircleCI`, you don't have the metadata to help you track the last successful run on `main`. In the example below, the base is set to `HEAD~1` (for push) or branching point (for pull requests), but a more robust solution would be to tag an SHA in the main job once it succeeds and then use this tag as a base. You can also try [using the devops CLI within the pipeline yaml](#get-the-commit-of-the-last-successful-build). See the [nx-tag-successful-ci-run](https://github.com/nrwl/nx-tag-successful-ci-run) and [nx-set-shas](https://github.com/nrwl/nx-set-shas) (version 1 implements tagging mechanism) repositories for more information. {% callout type="note" title="Tracking the origin branch" %} @@ -66,6 +66,89 @@ jobs: The `main` job implements the CI workflow. +## Get the Commit of the Last Successful Build + +The idea is to use [Azure Devops CLI](https://learn.microsoft.com/en-us/cli/azure/pipelines?view=azure-cli-latest) +directly in the [Pipeline Yaml](https://learn.microsoft.com/en-us/azure/devops/cli/azure-devops-cli-in-yaml?view=azure-devops) + +First, we configure Devops CLI + +```yaml +# Set Azure Devops default settings +- bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject) + displayName: 'Configure Azure DevOps organization and project' +``` + +Then we can query the pipelines API (providing the auth token) + +```yaml +# Get last successfully commit infos from Azure Devops +- bash: | + LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\"ci.sourceSha\"") + echo "Last successful commit SHA: $LAST_SHA" + echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA" + displayName: 'Get last successful commit SHA' + env: + AZURE_DEVOPS_EXT_PAT: $(System.AccessToken) +``` + +We can target a specific build, in this example we specified: + +- The branch (--branch) +- The pipeline Id (--definition-ids) +- The result type (--result) +- The number of result (-top) + +By default the command returns an entire JSON object with all the information. But we can narrow it down to the desired result with the `--query` param that uses [JMESPath](https://jmespath.org/) format ([more details](https://learn.microsoft.com/en-us/cli/azure/query-azure-cli?tabs=concepts%2Cbash)) + +Finally we extract the result in a common [custom variable](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-variables-scripts?view=azure-devops&tabs=bash) named `BASE_SHA` used later by `nx affected` commands + +An example with a default SHA in case no commit is found: + +```yaml {% fileName="azure-pipelines.yml" %} +trigger: + - main +pr: + - main + +variables: + CI: 'true' + NX_BRANCH: $(Build.SourceBranchName) + DEFAULT_BASE_SHA: $(git rev-parse HEAD~1) + HEAD_SHA: $(git rev-parse HEAD) + +jobs: + - job: main + pool: + vmImage: 'ubuntu-latest' + steps: + # Set Azure Devops CLI default settings + - bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject) + displayName: 'Set default Azure DevOps organization and project' + + # Get last successfull commit from Azure Devops CLI + - bash: | + LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\"ci.sourceSha\"") + if [ -z "$LAST_SHA" ] + then + LAST_SHA=$DEFAULT_BASE_SHA + fi + echo "Last successful commit SHA: $LAST_SHA" + echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA" + displayName: 'Get last successful commit SHA' + env: + AZURE_DEVOPS_EXT_PAT: $(System.AccessToken) + + - script: npm ci + + - script: npx nx workspace-lint + - script: npx nx format:check + + - script: npx nx affected --base=$(BASE_SHA) -t lint --parallel=3 + - script: npx nx affected --base=$(BASE_SHA) -t test --parallel=3 --ci --code-coverage + - script: npx nx affected --base=$(BASE_SHA) -t build --parallel=3 +``` + {% nx-cloud-section %} ## Distributed CI with Nx Cloud diff --git a/docs/shared/monorepo-nx-enterprise.md b/docs/shared/monorepo-nx-enterprise.md index aca7a17aa602f..a6749552b8686 100644 --- a/docs/shared/monorepo-nx-enterprise.md +++ b/docs/shared/monorepo-nx-enterprise.md @@ -23,7 +23,7 @@ starting point not the definite list of what you must and must not do. - Apps configure dependency injection and wire up libraries. They should not contain any components, services, or business logic. -- Libs contain services, components, utilities, etc. They have well-≠defined public API. +- Libs contain services, components, utilities, etc. They have well-defined public API. A typical Nx workspace has many more libs than apps, so pay especially careful attention to the organization of the libs directory. @@ -148,7 +148,7 @@ For a large organization it's crucial to establish how projects can depend on ea feature libraries. Nx provides a feature called tags that can be used to codify and statically-enforce these rules. Read more about -tags [here](/core-features/enforce-project-boundaries). +tags [here](/core-features/enforce-module-boundaries). ## Code Ownership diff --git a/docs/shared/node-server-tutorial/1-code-generation.md b/docs/shared/node-server-tutorial/1-code-generation.md index 9a165a8033ace..fabeda4d85233 100644 --- a/docs/shared/node-server-tutorial/1-code-generation.md +++ b/docs/shared/node-server-tutorial/1-code-generation.md @@ -12,7 +12,7 @@ You can find more information on the difference between the two in [our introduc {% youtube src="https://www.youtube.com/embed/-Oe8j-NZcBc" title="Tutorial: Node Server" -width="100%" /%} +/%} # Node Server Tutorial - Part 1: Code Generation diff --git a/docs/shared/node-server-tutorial/6-summary.md b/docs/shared/node-server-tutorial/6-summary.md index fe36979043c54..0ca9262dcc92e 100644 --- a/docs/shared/node-server-tutorial/6-summary.md +++ b/docs/shared/node-server-tutorial/6-summary.md @@ -19,7 +19,7 @@ In this tutorial you: {% card title="Core Features" description="Read about the core features of Nx." url="/core-features" /%} -{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/plugin-features" /%} +{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/core-features/plugin-features" /%} {% card title="Mental Model" description="Get a deeper understanding of the mental model." url="/concepts/mental-model" /%} diff --git a/docs/shared/npm-tutorial/integrated.md b/docs/shared/npm-tutorial/integrated.md index aa2c9b5fc130e..a948d3f90b93b 100644 --- a/docs/shared/npm-tutorial/integrated.md +++ b/docs/shared/npm-tutorial/integrated.md @@ -3,7 +3,7 @@ {% youtube src="https://www.youtube.com/embed/weZ7NAzB7PM" title="Tutorial: Getting Started with Integrated Repos" -width="100%" /%} +/%} {% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/integrated" /%} diff --git a/docs/shared/npm-tutorial/package-based.md b/docs/shared/npm-tutorial/package-based.md index 6f539b583044a..76164bfa8f7a2 100644 --- a/docs/shared/npm-tutorial/package-based.md +++ b/docs/shared/npm-tutorial/package-based.md @@ -3,7 +3,7 @@ {% youtube src="https://www.youtube.com/embed/hzTMKuE3CDw" title="Tutorial: Getting Started with Package-Based Repos" -width="100%" /%} +/%} {% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/package-based" /%} diff --git a/docs/shared/packages/angular/angular-nx-version-matrix.md b/docs/shared/packages/angular/angular-nx-version-matrix.md index e6d79e4d79005..0fc34f98d2849 100644 --- a/docs/shared/packages/angular/angular-nx-version-matrix.md +++ b/docs/shared/packages/angular/angular-nx-version-matrix.md @@ -14,6 +14,7 @@ We provide a recommended version, and it is usually the latest minor version of | Angular Version | **Nx Version _(recommended)_** | Nx Version _(range)_ | | --------------- | ------------------------------ | --------------------------------------- | +| ~16.1.0 | **latest** | 16.4.0 <= latest | | ~16.0.0 | **latest** | 16.1.0 <= latest | | ~15.2.0 | **latest** | 15.8.0 <= latest | | ~15.1.0 | **latest** | 15.5.0 <= latest | diff --git a/docs/shared/packages/angular/angular-plugin.md b/docs/shared/packages/angular/angular-plugin.md index 88e1aa4d0e4ab..8883e2a5db5e3 100644 --- a/docs/shared/packages/angular/angular-plugin.md +++ b/docs/shared/packages/angular/angular-plugin.md @@ -12,7 +12,7 @@ within an Nx workspace. It provides: {% callout type="note" title="Currently using the Angular CLI?" %} You can easily and mostly **automatically migrate from an Angular CLI** project to Nx! Learn -more [here](/recipes/adopting-nx/migration-angular). +more [here](/recipes/angular/migration/angular). {% /callout %} ## Setting up the Angular plugin @@ -75,9 +75,9 @@ nx lint libName Read more about: -- [Creating Libraries](/more-concepts/creating-libraries) -- [Library Types](/more-concepts/library-types) -- [Buildable and Publishable Libraries](/more-concepts/buildable-and-publishable-libraries) +- [Creating Libraries](/concepts/more-concepts/creating-libraries) +- [Library Types](/concepts/more-concepts/library-types) +- [Buildable and Publishable Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) ### Fallback to `@schematics/angular` @@ -92,9 +92,7 @@ nx g @nx/angular:service my-service ## More Documentation - [Angular Nx Tutorial](/angular-tutorial/1-code-generation) -- [Migrating from the Angular CLI](/recipes/adopting-nx/migration-angular) -- [Setup Module Federation with Angular and Nx](/recipes/module-federation/faster-builds) -- [Using NgRx](/recipes/other/misc-ngrx) -- [Using Data Persistence operators](/recipes/other/misc-data-persistence) -- [Upgrading an AngularJS application to Angular](/recipes/adopting-nx/migration-angularjs) -- [Using Tailwind CSS with Angular projects](/recipes/other/using-tailwind-css-with-angular-projects) +- [Migrating from the Angular CLI](/recipes/angular/migration/angular) +- [Setup Module Federation with Angular and Nx](/concepts/more-concepts/faster-builds-with-module-federation) +- [Upgrading an AngularJS application to Angular](/recipes/angular/migration/angularjs) +- [Using Tailwind CSS with Angular projects](/recipes/angular/using-tailwind-css-with-angular-projects) diff --git a/docs/shared/packages/cypress/cypress-plugin.md b/docs/shared/packages/cypress/cypress-plugin.md index 694532c7e2eb0..52868da3b9504 100644 --- a/docs/shared/packages/cypress/cypress-plugin.md +++ b/docs/shared/packages/cypress/cypress-plugin.md @@ -51,7 +51,7 @@ Replace `your-app-name` with the app's name as defined in your `tsconfig.base.js Run `nx e2e frontend-e2e` to execute e2e tests with Cypress. -You can run your e2e test against a production build by using the `production` [configuration](https://nx.dev/recipes/executors/use-executor-configurations#use-executor-configurations) +You can run your e2e test against a production build by using the `production` [configuration](https://nx.dev/plugin-features/use-task-executors#use-executor-configurations) ```shell nx e2e frontend-e2e --configuration=production diff --git a/docs/shared/packages/esbuild/esbuild-plugin.md b/docs/shared/packages/esbuild/esbuild-plugin.md index 5dba8a19770a4..e080e503494fc 100644 --- a/docs/shared/packages/esbuild/esbuild-plugin.md +++ b/docs/shared/packages/esbuild/esbuild-plugin.md @@ -45,13 +45,13 @@ This command will install the esbuild plugin if needed, and set `@nx/esbuild:esb If you already have a JS project that you want to use esbuild for, run this command: ```shell -nx g esbuild-project mylib +nx g @nx/esbuild:configuration mylib ``` This generator validates there isn't an existing `build` target. If you want to overwrite the existing target you can pass the `--skipValidation` option. ```shell -nx g esbuild-project mylib --skipValidation +nx g @nx/esbuild:configuration mylib --skipValidation ``` ## Using esbuild diff --git a/docs/shared/packages/expo/expo-plugin.md b/docs/shared/packages/expo/expo-plugin.md index 2bd3082683376..b7b9e37ba971a 100644 --- a/docs/shared/packages/expo/expo-plugin.md +++ b/docs/shared/packages/expo/expo-plugin.md @@ -50,7 +50,7 @@ nx start my-app To generate a new library run: ```shell -npx nx g @nx/react-native:lib your-lib-name +npx nx g @nx/expo:lib your-lib-name ``` ### Generating Components @@ -58,7 +58,7 @@ npx nx g @nx/react-native:lib your-lib-name To generate a new component inside library run: ```shell -npx nx g @nx/react-native:component your-component-name --project=your-lib-name --export +npx nx g @nx/expo:component your-component-name --project=your-lib-name --export ``` Replace `your-lib-name` with the app's name as defined in your `tsconfig.base.json` file or the `name` property of your `package.json` @@ -247,6 +247,28 @@ To check the details of your build status, run: nx build-list ``` +### Submit an EAS Build + +EAS Submit is a hosted service for uploading and submitting your app binaries to the app stores. Since it's a hosted service, you can submit your app to both stores as long as you can run EAS CLI on your machine. + +To submit an EAS build: + +```shell +nx submit +``` + +### Update an EAS Build + +EAS Update is a hosted service that serves updates for projects using the `expo-updates` library. + +EAS Update makes fixing small bugs and pushing quick fixes a snap in between app store submissions. It accomplishes this by allowing an end-user's app to swap out the non-native parts of their app (for example, JS, styling, and image changes) with a new update that contains bug fixes and other updates. + +To update an EAS build: + +```shell +nx update +``` + ### Testing Projects You can run unit tests with: @@ -269,6 +291,8 @@ Below table is a map between expo commands and Nx commands: | `expo install` | `nx install ` | | `eas build` | `nx build ` | | `eas build:list` | `nx build-list ` | +| `eas update` | `nx update ` | +| `eas submit` | `nx submit ` | ## More Documentation diff --git a/docs/shared/packages/linter/dependency-checks.md b/docs/shared/packages/linter/dependency-checks.md new file mode 100644 index 0000000000000..10733d0326170 --- /dev/null +++ b/docs/shared/packages/linter/dependency-checks.md @@ -0,0 +1,81 @@ +# Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project depends on. If your project is using, for example, the `axios`, but the `package.json` does not specify it as a dependency, your library might not work correctly. This rule helps catch these problems before your users do. + +The rule uses the project graph to collect all the dependencies of your project, based on the input of your `build` target. It will filter out all the dependencies marked as `devDependencies` in your root `package.json` to ensure dependencies of your compilation pipelines (e.g. dependencies of `webpack.config` or `vite.config`) or test setups are not included in the expected list. + +We use the version numbers of the installed packages when checking whether the version specifier in `package.json` is correct. We do this because this is the only version for which we can "guarantee" that things work and were tested. If you specify a range outside of that version, that would mean that you are shipping potentially untested code. + +## Usage + +Library generators from `@nx` packages will configure this rule automatically when you opt-in for bundler/build setup. This rule is intended for publishable/buildable libraries, so it will only run if a `build` target is detected in the configuration (this name can be modified - see [options](#options)). + +### Manual setup + +To set it up manually for existing libraries, you need to add the `dependency-checks` rule to your project's ESLint configuration: + +```jsonc {% fileName="/.eslintrc.json" %} +{ + // ... more ESLint config here + "overrides": [ + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/dependency-checks": "error" + } + } + // ... more ESLint overrides here + ] +} +``` + +Additionally, you need to adjust your `lintFilePatterns` to include the project's `package.json` file:: + +```jsonc {% fileName="/project.json" %} +{ + // ... project.json config + "targets": { + // ... more targets + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": [ + "libs/my-lib/**/*.{ts,tsx,js,jsx}", + "libs/my-lib/package.json" // add this line + ] + } + } + } +} +``` + +### Overriding defaults + +Sometimes we intentionally want to add or remove a dependency from our `package.json` despite what the rule suggests. We can use the rule's options to override default behavior: + +```jsonc {% fileName=".eslintrc.json" %} +{ + "@nx/dependency-checks": [ + "error", + { + "buildTargets": ["build", "custom-build"], // add non standard build target names + "ignoredDependencies": ["lodash"], // these libs will be omitted from checks + "checkMissingDependencies": true, // toggle to disable + "checkObsoleteDependencies": true, // toggle to disable + "checkVersionMismatches": true // toggle to disable + } + ] +} +``` + +## Options + +| Property | Type | Default | Description | +| ------------------------- | --------------- | ----------- | ----------------------------------------------------------------------- | +| buildTargets | _Array_ | _["build"]_ | List of build target names | +| ignoredDependencies | _Array_ | _[]_ | List of dependencies to ignore for checks | +| checkMissingDependencies | _boolean_ | _true_ | Disable to skip checking for missing dependencies | +| checkObsoleteDependencies | _boolean_ | _true_ | Disable to skip checking for unused dependencies | +| checkVersionMismatches | _boolean_ | _true_ | Disable to skip checking if version specifier matches installed version | diff --git a/docs/shared/packages/linter/enforce-module-boundaries.md b/docs/shared/packages/linter/enforce-module-boundaries.md index 17df00f19fed5..3601b6a11b30a 100644 --- a/docs/shared/packages/linter/enforce-module-boundaries.md +++ b/docs/shared/packages/linter/enforce-module-boundaries.md @@ -1,3 +1,5 @@ +# Enforce module boundaries rule + The `@nx/enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps to prevent unplanned cross-dependencies. ## Usage @@ -51,7 +53,7 @@ The `depConstraints` is an array of objects representing the constraints defined Read more about the proper usage of this rule: -- [Enforce Project Boundaries](/core-features/enforce-project-boundaries) +- [Enforce Module Boundaries](/core-features/enforce-module-boundaries) - [Ban Dependencies with Certain Tags](/recipes/enforce-module-boundaries/ban-dependencies-with-tags) - [Tag in Multiple Dimensions](/recipes/enforce-module-boundaries/tag-multiple-dimensions) - [Ban External Imports](/recipes/enforce-module-boundaries/ban-external-imports) diff --git a/docs/shared/packages/linter/eslint-plugin.md b/docs/shared/packages/linter/eslint-plugin.md index 7c966c2c24aba..7b00732054f64 100644 --- a/docs/shared/packages/linter/eslint-plugin.md +++ b/docs/shared/packages/linter/eslint-plugin.md @@ -1,4 +1,7 @@ -The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called [enforce-module-boundaries](#enforce-module-boundaries-rule). +The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as the following Nx-specific ESLint rules: + +- [enforce-module-boundaries](#enforce-module-boundaries-rule) +- [dependency-checks](#dependency-checks-rule) ## Setting Up ESLint Plugin @@ -54,4 +57,8 @@ You can also use `@nx/react` which includes all three `@nx/react-*` plugins ### Enforce Module Boundaries rule -The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps keep prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries) +The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries). + +### Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project actually depends on. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/dependency-checks). diff --git a/docs/shared/packages/nest/nest-plugin.md b/docs/shared/packages/nest/nest-plugin.md index c9d5662de20da..76f73a9778576 100644 --- a/docs/shared/packages/nest/nest-plugin.md +++ b/docs/shared/packages/nest/nest-plugin.md @@ -67,7 +67,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 ``` -> Read more about [building and publishing libraries here](/more-concepts/buildable-and-publishable-libraries). +> Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). ### Nest Generators diff --git a/docs/shared/packages/next/plugin-overview.md b/docs/shared/packages/next/plugin-overview.md index 9670ebee10f12..a5c8681e00892 100644 --- a/docs/shared/packages/next/plugin-overview.md +++ b/docs/shared/packages/next/plugin-overview.md @@ -38,8 +38,8 @@ Nx allows you to create libraries with just one command. Some reasons you might - Publish a package to be used outside the monorepo - Better visualize the architecture using `nx graph` -For more information on Nx libraries, see our documentation on [Creating Libraries](/more-concepts/creating-libraries) -and [Library Types](/more-concepts/library-types). +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: @@ -161,7 +161,7 @@ nx export my-new-app Once you are ready to deploy your Next.js application, you have absolute freedom to choose any hosting provider that fits your needs. -You may know that the company behind Next.js, Vercel, has a great hosting platform offering that is developed in tandem with Next.js itself to offer a great overall developer and user experience. We have detailed [how to deploy your Next.js application to Vercel in a separate guide](/recipes/deployment/deploy-nextjs-to-vercel). +You may know that the company behind Next.js, Vercel, has a great hosting platform offering that is developed in tandem with Next.js itself to offer a great overall developer and user experience. We have detailed [how to deploy your Next.js application to Vercel in a separate guide](/recipes/react/deploy-nextjs-to-vercel). ## More Documentation diff --git a/docs/shared/packages/playwright/playwright-plugin.md b/docs/shared/packages/playwright/playwright-plugin.md new file mode 100644 index 0000000000000..a80a585d40542 --- /dev/null +++ b/docs/shared/packages/playwright/playwright-plugin.md @@ -0,0 +1,209 @@ +Playwright is a modern web test runner. With included features such as: + +- Cross browser support, including mobile browsers +- Multi tab, origin, and user support +- Automatic waiting +- Test generation +- Screenshots and videos + +## Setting Up Playwright + +If the `@nx/playwright` package is not installed, install the version that matches your `nx` package version. + +{% tabs %} +{% tab label="npm" %} + +```shell +npm install --save-dev @nx/playwright +``` + +{% /tab %} +{% tab label="yarn" %} + +```shell +yarn add --dev @nx/playwright +``` + +{% /tab %} +{% tab label="pnpm" %} + +```shell +pnpm i -D @nx/playwright +``` + +{% /tab %} +{% /tabs %} + +## E2E Testing + +By default, when creating a new frontend application, Nx will prompt for which e2e test runner to use. Select `playwright` or pass in the arg `--e2eTestRunner=playwright` + +```shell +nx g @nx/web:app frontend --e2eTestRunner=playwright +``` + +### Add Playwright e2e to an existing project + +To generate an E2E project for an existing project, run the following generator + +```shell +nx g @nx/playwright:configuration --project=your-app-name --project=your-app-name +``` + +Optionally, you can use the `--webServerCommand` and `--webServerAddress` option, to auto setup the [web server option](https://playwright.dev/docs/test-webserver) in the playwright config + +```shell +nx g @nx/playwright:configuration --project=your-app-name --webServerCommand="npx serve your-project-name" --webServerAddress="http://localhost:4200" +``` + +### Testing Applications + +Run `nx e2e ` to execute e2e tests with Playwright + +{% callout type="note" title="Selecting Specific Specs" %} + +You can use the `--grep/-g` flag to glob for test files. +You can use the `--grepInvert/-gv` flag to glob for files to _not_ run. + +```bash +# run the tests in the feat-a/ directory +nx e2e frontend-e2e --grep="**feat-a/**" + +# run everything except feat-a/ directory +nx e2e frontend-e2e --grepInvert=**feat-a/** +``` + +{% /callout %} + +By default, Playwright will run in headless mode. You will have the result of all the tests and errors (if any) in your +terminal. Test output such as reports, screenshots and videos, will be accessible in `dist/.playwright/apps//`. This can be configured with the `outputDir` configuration options. + +{% callout type="note" title="Output Caching" %} +If changing the output directory or report output, make sure to update the [target outputs](/concepts/how-caching-works#what-is-cached) so the artifacts are correctly cached +{% /callout %} + +### Watching for Changes + +With, `nx e2e frontend-e2e --ui` Playwright will start in headed mode where you can see your application being tested. + +From, there you can toggle on the watch icon which will rerun the tests when the spec file updates. + +```shell +nx e2e --ui +``` + +You can also use `--headed` flag to run Playwright where the browser can be seen without using the [Playwright UI](https://playwright.dev/docs/test-ui-mode) + +### Specifying a Base Url + +The `baseURL` property within the Playwright configuration can control where the tests visit by default. + +```ts +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + // Rest of your config... + + // Run your local dev server before starting the tests + webServer: { + command: 'npx serve ', + url: 'http://localhost:4200', + reuseExistingServer: !process.env.CI, + }, + use: { + baseURL: 'http://localhost:4200', // url playwright visits with `await page.goto('/')`; + }, +}); +``` + +In order to set different `baseURL` values for different environments you can pass them via the [environment variables and nx configurations](/recipes/tips-n-tricks/define-environment-variables) or optionally via setting them per the environment they are needed in such as `CI` + +```ts +import { defineConfig } from '@playwright/test'; + +const baseUrl = + process.env.BASE_URL ?? process.env.CI + ? 'https://some-staging-url.example.com' + : 'http://localhost:4200'; + +export default defineConfig({ + // Rest of your config... + + // Run your local dev server before starting the tests + webServer: { + command: 'npx serve ', + url: baseUrl, + reuseExistingServer: !process.env.CI, + }, + use: { + baseURL: baseUrl, // url playwright visits with `await page.goto('/')`; + }, +}); +``` + +By default Nx, provides a `nxE2EPreset` with predefined configuration for Playwright. + +```ts +import { defineConfig } from '@playwright/test'; +import { nxE2EPreset } from '@nx/playwright/preset'; +import { workspaceRoot } from '@nx/devkit'; + +// For CI, you may want to set BASE_URL to the deployed application. +const baseURL = process.env['BASE_URL'] || 'http://localhost:4200'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + ...nxE2EPreset(__filename, { testDir: './e2e' }), + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + baseURL, + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npx nx serve ', + url: baseURL, + reuseExistingServer: !process.env.CI, + cwd: workspaceRoot, + }, +}); +``` + +This preset sets up the `outputDir` and [HTML reporter](https://playwright.dev/docs/test-reporters#html-reporter) to output in `dist/.playwright/` and sets up chromium, firefox, webkit browsers to be used a browser targets. If you want to use mobile and/or branded browsers you can pass those options into the preset function + +```ts +export default defineConfig({ + ...nxE2EPreset(__filename, { + testDir: './e2e', + includeMobileBrowsers: true, // includes mobile Chrome and Safari + includeBrandedBrowsers: true, // includes Google Chrome and Microsoft Edge + }), + // other settings +}); +``` + +If you want to override any settings within the `nxE2EPreset`, You can define them after the preset like so + +```ts +const config = nxE2EPreset(__filename, { + testDir: './e2e', + includeMobileBrowsers: true, // includes mobile Chrome and Safari + includeBrandedBrowsers: true, // includes Google Chrome and Microsoft Edge +}); +export default defineConfig({ + ...config + retries: 3, + reporters: [...config.reporters, /* other reporter settings */], +}); +``` + +See the [Playwright configuration docs](https://playwright.dev/docs/test-configuration) for more options for Playwright. diff --git a/docs/shared/packages/plugin/plugin.md b/docs/shared/packages/plugin/plugin.md index cb5ca805971fc..459807ba2e2ef 100644 --- a/docs/shared/packages/plugin/plugin.md +++ b/docs/shared/packages/plugin/plugin.md @@ -1,5 +1,5 @@ -Nx plugins are npm packages that contain [generators](/plugin-features/use-code-generators) and [executors](/plugin-features/use-task-executors) to extend a Nx workspace. +Nx plugins are npm packages that contain [generators](/core-features/plugin-features/use-code-generators) and [executors](/core-features/plugin-features/use-task-executors) to extend a Nx workspace. This package contains tooling to help plugin authors create and maintain plugins. -For more information, see the [plugins](/plugins/intro/getting-started) section of docs. +For more information, see the [plugins](/extending-nx/intro/getting-started) section of docs. diff --git a/docs/shared/packages/react/react-plugin.md b/docs/shared/packages/react/react-plugin.md index ef171ef6a4fcc..1953591a95d38 100644 --- a/docs/shared/packages/react/react-plugin.md +++ b/docs/shared/packages/react/react-plugin.md @@ -43,7 +43,7 @@ nx g @nx/react:lib my-new-lib \ --importPath=@myorg/my-new-lib ``` -Read more about [building and publishing libraries here](/more-concepts/buildable-and-publishable-libraries). +Read more about [building and publishing libraries here](/concepts/more-concepts/buildable-and-publishable-libraries). ### Creating Components diff --git a/docs/shared/packages/storybook/best-practices.md b/docs/shared/packages/storybook/best-practices.md index 07e5ffa035d92..c4c3ba91fdbb5 100644 --- a/docs/shared/packages/storybook/best-practices.md +++ b/docs/shared/packages/storybook/best-practices.md @@ -91,7 +91,7 @@ In the following section, we are going to see how to set up Storybook in these c ### 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](/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. Let’s see this in more detail. +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. Let’s see this in more detail. #### Local development and testing @@ -121,7 +121,7 @@ Since each Storybook, in this case, is attached to a project, so is the serving #### Publishing -When you are publishing your Storybook, you can follow the same principles described in the [Applications and Libraries Mental Model](/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/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. 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. @@ -131,7 +131,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](/packages/storybook/documents/storybook-composition-setup). However, in this case, you would still need to build each project’s Storybook individually, and also deploy it individually. So in the cases where you have multiple projects, Storybook Composition would not be very efficient. {% /callout %} -Before moving on to the examples section, it could be useful to read the [Library Types](/more-concepts/library-types) documentation page and the [Grouping libraries](/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/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. ## Examples / Use cases diff --git a/docs/shared/packages/storybook/custom-builder-configs.md b/docs/shared/packages/storybook/custom-builder-configs.md index d9012829bdf7b..34886558ae898 100644 --- a/docs/shared/packages/storybook/custom-builder-configs.md +++ b/docs/shared/packages/storybook/custom-builder-configs.md @@ -47,7 +47,7 @@ async viteFinal(config, { configType }) { In the `viteFinal` case, you would have to import the `mergeConfig` function from `vite`. So, on the top of your root `.storybook/main.js|ts` file, you would have to add: ```ts {% fileName=".storybook/main.js" %} -const { mergeConfig } = require('vite'); +import { mergeConfig } from 'vite'; ``` ## Project-specific configuration @@ -57,7 +57,7 @@ const { mergeConfig } = require('vite'); You can customize the `webpack` configuration for a specific project by adding a `webpackFinal` field in your project-specific `.storybok/main.js|ts` file, like this: ```ts {% fileName="apps/my-react-webpack-app/.storybook/main.js" %} -module.exports = { +export default { ... webpackFinal: async (config, { configType }) => { @@ -71,9 +71,9 @@ module.exports = { If you are using a global, root-level, `webpack` configuration in your project, you can customize or extend that for a specific project like this: ```ts {% fileName="apps/my-react-webpack-app/.storybook/main.js" %} -const rootMain = require('../../../.storybook/main'); +import rootMain from '../../../.storybook/main'; -module.exports = { +export default { ...rootMain, ... webpackFinal: async (config, { configType }) => { @@ -96,10 +96,10 @@ Take note how, in this case, we are first applying the global `webpack` configur You can customize the `vite` configuration for a specific project by adding a `viteFinal` field in your project-specific `.storybok/main.js|ts` file, like this: ```ts {% fileName="apps/my-react-vite-app/.storybook/main.js" %} -const { mergeConfig } = require('vite'); -const viteTsConfigPaths = require('vite-tsconfig-paths').default; +import { mergeConfig } from 'vite'; +import viteTsConfigPaths from 'vite-tsconfig-paths'; -module.exports = { +export default { ... async viteFinal(config, { configType }) { return mergeConfig(config, { @@ -112,10 +112,10 @@ module.exports = { If you are using a global, root-level, `vite` configuration in your workspace, you can customize or extend that for a specific project like this: ```ts {% fileName="apps/my-react-vite-app/.storybook/main.js" %} -const { mergeConfig } = require('vite'); -const rootMain = require('../../../.storybook/main'); +import { mergeConfig } from 'vite'; +import rootMain from '../../../.storybook/main'; -module.exports = { +export default { ... async viteFinal(config, { configType }) { return mergeConfig(config, { @@ -128,9 +128,9 @@ module.exports = { So, a full project-level `.storybook/main.js|ts` file for a Vite.js project would look like this: ```ts {% fileName="apps/my-react-vite-app/.storybook/main.js" %} -const { mergeConfig } = require('vite'); +import { mergeConfig } from 'vite'; -module.exports = { +export default { stories: ['../src/app/**/*.stories.@(mdx|js|jsx|ts|tsx)'], addons: ['@storybook/addon-essentials'], framework: { diff --git a/docs/shared/packages/storybook/interaction-tests.md b/docs/shared/packages/storybook/interaction-tests.md new file mode 100644 index 0000000000000..b09cbe9ea2421 --- /dev/null +++ b/docs/shared/packages/storybook/interaction-tests.md @@ -0,0 +1,138 @@ +--- +title: Setting up Storybook Interaction Tests with Nx +description: This guide explains how you can set up Storybook interaction tests on your Nx workspace. +--- + +# Setting up Storybook Interaction Tests with Nx + +[Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing) allow you to test user interactions within your Storybook stories. It enhances your [Storybook](https://storybook.js.org/) setup, ensuring that not only do your components look right, but they also work correctly when interacted with. + +You can read more about Storybook interaction tests in the following sections of the Storybook documentation: + +- [Storybook interaction tests for React](https://storybook.js.org/docs/react/writing-tests/interaction-testing) +- [Storybook interaction tests for Angular](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) +- [Storybook test runner](https://storybook.js.org/docs/react/writing-tests/test-runner) +- [The `play` function](https://storybook.js.org/docs/react/writing-stories/play-function) + +{% callout type="warning" title="Set up Storybook in your workspace" %} +You first need to set up Storybook for your Nx workspace, if you haven't already. You can read the [Storybook plugin overview guide](/packages/storybook) to get started. +{% /callout %} + +## Setup Storybook Interaction Tests + +During the setup, you'll be prompted about setting up interaction tests. Choose `yes` when asked if you want to set up Storybook interaction tests. + +The `--interactionTests` flag is true by default, so when you're setting up Storybook, you can just press enter to accept the default value, or even pass the flag directly. Make sure to use the framework-specific generators, so that you also get your stories set up correctly: + +{% tabs %} +{% tab label="Angular" %} + +```shell +nx g @nx/angular:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="React" %} + +```shell +nx g @nx/react:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="No framework" %} + +```shell +nx g @nx/storybook:configuration project-name --interactionTests=true +``` + +{% /tab %} +{% /tabs %} + +This command will: + +- [Set up Storybook for your project](/packages/storybook) - including the `@storybook/addon-interactions` addon. +- Add a `play` function to your stories. +- Install the necessary dependencies. +- Generate a `test-storybook` target in your project's `project.json`, which has a command to invoke the Storybook test runner. + +## Writing an Interaction Test + +The Nx generator will create a very simple interaction test for you. You can find it in the `.stories.ts` file for your component. This test will only be asserting if some text exists in your component. +You can modify it to suit your needs. + +Let's take an example of a simple React component for a button: + +```typescript +import React, { useState } from 'react'; + +export function Button() { + const [count, setCount] = useState(0); + + const handleClick = () => { + setCount(count + 1); + }; + + return ( + + ); +} + +export default Button; +``` + +In your `.stories.ts` file for that component, you can use the play function to simulate interactions. For example: + +```typescript +export const ButtonClicked: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const button = canvas.getByRole('button'); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 1 times" + ); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 2 times" + ); + }, +}; +``` + +Here, the play function is simulating a click on the button using the `userEvent.click` method. It is then asserting that the button's text has changed to reflect the number of times it has been clicked. + +You can read more about how to write interaction tests in the [Storybook documentation](https://storybook.js.org/docs/react/writing-tests/interaction-testing). + +## Running Interaction Tests + +To run the interaction tests, you can use the `test-storybook` target that was generated for your project: + +```bash +nx test-storybook project-name +``` + +Make sure you have Storybook running in another tab, so that the test runner can connect to it: + +```bash +nx storybook project-name +``` + +## Interaction Tests vs. Cypress E2E Tests + +As the landscape of testing has evolves, we are also adjusting our approach to testing in Nx, and the Storybook generators. Nx has been consistently suggesting the use of Cypress for e2e tests in conjunction with Storybook. This approach, while effective, had its own challenges. A new, separate e2e project would be generated, and setup specifically to work with Storybook, leading to a bifurcated setup: your component stories in one place, and the e2e tests that validated them in another. + +However, with the introduction of Storybook Interaction Tests, this approach can be simplified. This new feature allows developers to integrate tests directly within the stories they are already creating, making the development and testing process more straightforward. Why maintain two separate projects or setups when you can do everything in one place? + +Choosing to promote Storybook Interaction Tests over the previous Cypress e2e setup was not a decision made lightly. Here's why we believe it's a beneficial shift: + +- **Unified Workflow:** Interaction tests allow developers to keep their focus on one tool. Instead of juggling between Storybook and a separate e2e project, everything is integrated. This means quicker iterations and a simplified dev experience. + +- **Leaner Project Structure:** Avoiding the need to generate a separate e2e project means fewer files, less configuration, and a more straightforward project structure. This can make onboarding new developers or navigating the codebase simpler. + +- **Optimized Performance:** Interaction tests are lightweight and quick to execute compared to traditional e2e tests. They run directly in the context of the component story, ensuring that tests are precise and fast. + +- **Consistency:** Keeping the stories and their associated tests together ensures a tighter bond between what's developed and what's tested. It reduces the chances of tests becoming outdated or misaligned with the component's actual behavior. + +Because of these benefits, it made sense for our Storybook configuration generator to switch from the Cypress e2e + Storybook combination to the integrated approach of Storybook Interaction Tests. By integrating e2e-like tests into the existing Storybook setup, we offer developers a smoother, more efficient, and simpler setup and testing experience. diff --git a/docs/shared/packages/webpack/webpack-config-setup.md b/docs/shared/packages/webpack/webpack-config-setup.md index 322cd684703d1..cd48bc0403e8e 100644 --- a/docs/shared/packages/webpack/webpack-config-setup.md +++ b/docs/shared/packages/webpack/webpack-config-setup.md @@ -157,7 +157,7 @@ module.exports = composePlugins(withNx(), (config, { options, context }) => { ### Configure webpack for Module Federation -If you use the [Module Federation](/recipes/module-federation/faster-builds) support from `@nx/angular` or `@nx/react` then +If you use the [Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) support from `@nx/angular` or `@nx/react` then you can customize your webpack configuration as follows. ```js {% fileName="apps/my-app/webpack.config.js" %} diff --git a/docs/shared/packages/webpack/webpack-plugins.md b/docs/shared/packages/webpack/webpack-plugins.md index 90897910400a3..7d34a3dda3182 100644 --- a/docs/shared/packages/webpack/webpack-plugins.md +++ b/docs/shared/packages/webpack/webpack-plugins.md @@ -165,7 +165,7 @@ module.exports = composePlugins( The `withModuleFederation` and `withModuleFederationForSSR` plugins add module federation support to the webpack build. These plugins use [`ModuleFederationPlugin`](https://webpack.js.org/concepts/module-federation/) and provide a simpler API through Nx. -For more information, refer to the [Module Federation recipe](/recipes/module-federation/faster-builds). +For more information, refer to the [Module Federation recipe](/concepts/more-concepts/faster-builds-with-module-federation). ### Options diff --git a/docs/shared/packages/workspace/workspace-plugin.md b/docs/shared/packages/workspace/workspace-plugin.md index f4eada5dfb589..84518542c6663 100644 --- a/docs/shared/packages/workspace/workspace-plugin.md +++ b/docs/shared/packages/workspace/workspace-plugin.md @@ -4,7 +4,7 @@ The workspace plugin contains executors and generators that are useful for any N Codifying your organization's best practices into local generators is a great way to ensure that the best practices are easy to follow and implement. Running `nx g @nx/plugin:plugin feature` will create a local plugin with a generator which is written the same way generators are written for Nx plugins. -> See more about [local generators](/plugins/recipes/local-generators) +> See more about [local generators](/extending-nx/recipes/local-generators) ## Reorganizing Projects diff --git a/docs/shared/plugin-features/use-code-generators.md b/docs/shared/plugin-features/use-code-generators.md index 5a9c721df1771..4c088b275eb8c 100644 --- a/docs/shared/plugin-features/use-code-generators.md +++ b/docs/shared/plugin-features/use-code-generators.md @@ -7,7 +7,7 @@ Generators provide a way to automate many tasks you regularly perform as part of There are three main types of generators: 1. **Plugin Generators** are available when an Nx plugin has been installed in your workspace. -2. **Local Generators** are generators that you can create for your own workspace. [Local generators](/plugins/recipes/local-generators) allow you to codify the processes that are unique to your own organization. +2. **Local Generators** are generators that you can create for your own workspace. [Local generators](/extending-nx/recipes/local-generators) allow you to codify the processes that are unique to your own organization. 3. **Update Generators** are invoked by Nx plugins when you [update Nx](/recipes/adopting-nx) to keep your config files in sync with the latest versions of third party tools. ## Invoking Plugin Generators diff --git a/docs/shared/plugin-features/use-task-executors.md b/docs/shared/plugin-features/use-task-executors.md index e6e8be5af5c22..6e4f42612c50b 100644 --- a/docs/shared/plugin-features/use-task-executors.md +++ b/docs/shared/plugin-features/use-task-executors.md @@ -103,3 +103,70 @@ If defining a new target that needs to run a single shell command, there is a sh ``` For more info, see the [run-commands documentation](/packages/nx/executors/run-commands) + +## Use Executor Configurations + +The `configurations` property provides extra sets of values that will be merged into the options map. + +```json {% fileName="project.json" %} +{ + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{workspaceRoot}/dist/libs/mylib"], + "dependsOn": ["^build"], + "options": { + "tsConfig": "libs/mylib/tsconfig.lib.json", + "main": "libs/mylib/src/main.ts" + }, + "configurations": { + "production": { + "tsConfig": "libs/mylib/tsconfig-prod.lib.json" + } + } + } +} +``` + +You can select a configuration like this: `nx build mylib --configuration=production` +or `nx run mylib:build:production`. + +The following code snippet shows how the executor options get constructed: + +```javascript +require(`@nx/jest`).executors['jest']({ + ...options, + ...selectedConfiguration, + ...commandLineArgs, +}); // Pseudocode +``` + +The selected configuration adds/overrides the default options, and the provided command line args add/override the +configuration options. + +### Default Configuration + +When using multiple configurations for a given target, it's helpful to provide a default configuration. +For example, running e2e tests for multiple environments. By default it would make sense to use a `dev` configuration for day to day work, but having the ability to run against an internal staging environment for the QA team. + +```json {% fileName="project.json" %} +{ + "e2e": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/my-app-e2e/cypress.config.ts" + }, + "configurations": { + "dev": { + "devServerTarget": "my-app:serve" + }, + "qa": { + "baseUrl": "https://some-internal-url.example.com" + } + }, + "defaultConfiguration": "dev" + } +} +``` + +When running `nx e2e my-app-e2e`, the _dev_ configuration will be used. In this case using the local dev server for `my-app`. +You can always run the other configurations by explicitly providing the configuration i.e. `nx e2e my-app-e2e --configuration=qa` or `nx run my-app-e2e:e2e:qa` diff --git a/docs/shared/plugins/create-plugin.md b/docs/shared/plugins/create-plugin.md index ebeaddda897cc..54a424ab98fbf 100644 --- a/docs/shared/plugins/create-plugin.md +++ b/docs/shared/plugins/create-plugin.md @@ -20,7 +20,7 @@ nx generate @nx/plugin:generator my-generator --project=my-plugin The new generator is located in `/src/generators/my-generator`. The `my-generator.ts` file contains the code that runs the generator. This generator creates a new project using a folder of template files. -For more information about this sample generator, read the [simple generator recipe](/plugins/recipes/local-generators). +For more information about this sample generator, read the [simple generator recipe](/extending-nx/recipes/local-generators). ### Generator options @@ -48,7 +48,7 @@ nx generate @nx/plugin:executor my-executor --project=my-plugin The new executor is located in `/src/executors/my-executor`. The `my-executor.ts` file contains the code that runs the executor. This executor emits a console log, but executors can compile code, deploy an app, publish to NPM and much more. -For more information about this sample executor, read the [simple executor recipe](/plugins/recipes/local-executors). +For more information about this sample executor, read the [simple executor recipe](/extending-nx/recipes/local-executors). ### Executor testing diff --git a/docs/shared/plugins/intro.md b/docs/shared/plugins/intro.md index 5dd3fb0863263..9f5836ab3d088 100644 --- a/docs/shared/plugins/intro.md +++ b/docs/shared/plugins/intro.md @@ -1,6 +1,6 @@ # Getting Started with Plugins -Nx plugins contain [generators](/plugin-features/use-code-generators) and [executors](/plugin-features/use-task-executors) that extend the capabilities of an Nx workspace. They can be shared as npm packages or referenced locally within the same repo. +Nx plugins contain [generators](/core-features/plugin-features/use-code-generators) and [executors](/core-features/plugin-features/use-task-executors) that extend the capabilities of an Nx workspace. They can be shared as npm packages or referenced locally within the same repo. {% cards cols="2" %} @@ -17,10 +17,9 @@ Nx plugins help you scaffold new projects, pre-configure tooling, follow best pr {% cards cols="2" %} -{% card title="Browse Existing Plugins" description="Find a plugin to use" url="/plugins/registry" /%} -{% card title="Use Task Executors" description="Run operations on your code" url="/plugin-features/use-task-executors" /%} -{% card title="Use Code Generators" description="Create or modify code" url="/plugin-features/use-code-generators" /%} -{% card title="Automate Updating Dependencies" description="Keep code up to date with package breaking changes" url="/core-features/automate-updating-dependencies" /%} +{% card title="Browse Existing Plugins" description="Find a plugin to use" url="/extending-nx/registry" /%} +{% card title="Use Task Executors" description="Run operations on your code" url="/core-features/plugin-features/use-task-executors" /%} +{% card title="Use Code Generators" description="Create or modify code" url="/core-features/plugin-features/use-code-generators" /%} {% /cards %} @@ -30,9 +29,9 @@ Local plugins allow you to automate repository specific tasks and enforce best p {% cards cols="3" %} -{% card title="Create a Plugin" description="Set up a new plugin" url="/plugins/tutorials/create-plugin" /%} -{% card title="Local Generators" description="Add a generator to your plugin" url="/plugins/recipes/local-generators" /%} -{% card title="Local Executors" description="Add an executor to your plugin" url="/plugins/recipes/local-executors" /%} +{% card title="Create a Plugin" description="Set up a new plugin" url="/extending-nx/tutorials/create-plugin" /%} +{% card title="Local Generators" description="Add a generator to your plugin" url="/extending-nx/recipes/local-generators" /%} +{% card title="Local Executors" description="Add an executor to your plugin" url="/extending-nx/recipes/local-executors" /%} {% /cards %} @@ -42,8 +41,8 @@ If your plugin has functionality that would be useful in more than just your rep {% cards cols="2" %} -{% card title="Share Your Plugin" description="Submit your plugin to the Nx plugin registry" url="/plugins/tutorials/publish-plugin" /%} -{% card title="Migration Generators" description="Update repos when you introduce breaking changes" url="/plugins/recipes/migration-generators" /%} +{% card title="Share Your Plugin" description="Submit your plugin to the Nx plugin registry" url="/extending-nx/tutorials/publish-plugin" /%} +{% card title="Migration Generators" description="Update repos when you introduce breaking changes" url="/extending-nx/recipes/migration-generators" /%} {% /cards %} @@ -53,8 +52,8 @@ You can also hook into the way Nx works and modify it to suit your needs {% cards cols="3" %} -{% card title="Scaffold a New Workspace" description="Set up a new repo" url="/plugins/recipes/create-preset" /%} -{% card title="Project Inference Plugins" description="Modify how Nx identifies projects" url="/plugins/recipes/project-inference-plugins" /%} -{% card title="Project Graph Plugins" description="Modify the Nx graph" url="/plugins/recipes/project-graph-plugins" /%} +{% card title="Scaffold a New Workspace" description="Set up a new repo" url="/extending-nx/recipes/create-preset" /%} +{% card title="Project Inference Plugins" description="Modify how Nx identifies projects" url="/extending-nx/recipes/project-inference-plugins" /%} +{% card title="Project Graph Plugins" description="Modify the Nx graph" url="/extending-nx/recipes/project-graph-plugins" /%} {% /cards %} diff --git a/docs/shared/plugins/maintain-published-plugin.md b/docs/shared/plugins/maintain-published-plugin.md index 4219b44e5f590..0bd0b5419c4c2 100644 --- a/docs/shared/plugins/maintain-published-plugin.md +++ b/docs/shared/plugins/maintain-published-plugin.md @@ -1,6 +1,6 @@ # Maintain a Published Plugins -To create a plugin, see the [create a local plugin tutorial](/plugins/tutorials/create-plugin). +To create a plugin, see the [create a local plugin tutorial](/extending-nx/tutorials/create-plugin). ## Publish your Nx Plugin @@ -32,4 +32,4 @@ We will then verify the plugin, offer suggestions or merge the pull request! ## Write Migrations -Once other repos are using your plugin, it would help them if you write migrations to automatically update their configuration files whenever you make breaking changes. Read the [migration generators guide](/plugins/recipes/migration-generators) to find out how. +Once other repos are using your plugin, it would help them if you write migrations to automatically update their configuration files whenever you make breaking changes. Read the [migration generators guide](/extending-nx/recipes/migration-generators) to find out how. diff --git a/docs/shared/react-standalone-tutorial/1-code-generation.md b/docs/shared/react-standalone-tutorial/1-code-generation.md index 1aff10e3ab8a4..4165a3ca4fec3 100644 --- a/docs/shared/react-standalone-tutorial/1-code-generation.md +++ b/docs/shared/react-standalone-tutorial/1-code-generation.md @@ -11,9 +11,9 @@ This tutorial sets up a repo with a single application at the root level that br {% youtube src="https://www.youtube.com/embed/dqCZteGFP4k" title="Tutorial: React Standalone Application" -width="100%" /%} +/%} -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-react-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/react-standalone" /%} # React Standalone Tutorial - Part 1: Code Generation diff --git a/docs/shared/react-standalone-tutorial/5-summary.md b/docs/shared/react-standalone-tutorial/5-summary.md index 647be6d305299..cadf9639c4415 100644 --- a/docs/shared/react-standalone-tutorial/5-summary.md +++ b/docs/shared/react-standalone-tutorial/5-summary.md @@ -13,7 +13,7 @@ In this tutorial you: {% card title="Core Features" description="Read about the core features of Nx." url="/core-features" /%} -{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/plugin-features" /%} +{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/core-features/plugin-features" /%} {% card title="Mental Model" description="Get a deeper understanding of the mental model." url="/concepts/mental-model" /%} diff --git a/docs/shared/react-standalone-tutorial/react-standalone.md b/docs/shared/react-standalone-tutorial/react-standalone.md index 12c39caa4d221..48340bc3a3dde 100644 --- a/docs/shared/react-standalone-tutorial/react-standalone.md +++ b/docs/shared/react-standalone-tutorial/react-standalone.md @@ -19,16 +19,25 @@ Note, this tutorial sets up a repo with a single application at the root level t {% /callout %} +Note, while you could easily use Nx together with your manually set up React application, we're going to use the `@nx/react` plugin for this tutorial which provides some nice enhancements when working with React. [Visit our "Why Nx" page](/getting-started/why-nx) to learn more about plugins and what role they play in the Nx architecture. + ## Warm Up Here's the source code of the final result for this tutorial. -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-react-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/react-standalone" /%} + + -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/standalone-react-app?file=README.md" /%} +{% youtube +src="https://www.youtube.com/embed/OQ-Zc5tcxJE" +title="Tutorial: Standalone React Application" +/%} ## Creating a new React App +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=64" /%} + Create a new standalone React application with the following command: ```shell {% command="npx create-nx-workspace@latest myreactapp --preset=react-standalone" path="~" %} @@ -83,6 +92,8 @@ Let me explain a couple of things that might be new to you. ## Serving the App +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=207" /%} + The most common tasks are already mapped in the `package.json` file: ```json {% fileName="package.json" %} @@ -163,13 +174,15 @@ Each target contains a configuration object that tells Nx how to run that target The most critical parts are: -- `executor` - this is of the syntax `:`, where the `plugin` is an NPM package containing an [Nx Plugin](/plugins/intro/getting-started) and `` points to a function that runs the task. In this case, the `@nx/vite` plugin contains the `dev-server` executor which serves the React app using Vite. +- `executor` - this is of the syntax `:`, where the `plugin` is an NPM package containing an [Nx Plugin](/extending-nx/intro/getting-started) and `` points to a function that runs the task. In this case, the `@nx/vite` plugin contains the `dev-server` executor which serves the React app using Vite. - `options` - these are additional properties and flags passed to the executor function to customize it Learn more about how to [run tasks with Nx](/core-features/run-tasks). ## Testing and Linting - Running Multiple Tasks +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=410" /%} + Our current setup doesn't just come with targets for serving and building the React application, but also has targets for unit testing, e2e testing and linting. Again, these are defined in the `project.json` file. We can use the same syntax as before to run these tasks: ```bash @@ -214,9 +227,23 @@ Note that all of these targets are automatically cached by Nx. If you re-run a s Not all tasks might be cacheable though. You can configure `cacheableOperations` in the `nx.json` file. You can also [learn more about how caching works](/core-features/cache-task-results). +## Nx Plugins? Why? + +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=598" /%} + +One thing you might be curious about is the project.json. You may wonder why we define tasks inside the `project.json` file instead of using the `package.json` file with scripts that directly launch Vite. + +Nx understands and supports both approaches, allowing you to define targets either in your `package.json` or `project.json` files. While both serve a similar purpose, the `project.json` file can be seen as an advanced form of `package.json` scripts, providing additional metadata and capabilities. In this tutorial, we utilize the `project.json` approach primarily because we take advantage of Nx Plugins. + +So, what are Nx Plugins? Nx Plugins are optional packages that extend the capabilities of Nx, catering to various specific technologies. For instance, we have plugins tailored to React (e.g., `@nx/react`), Vite (`@nx/vite`), Cypress (`@nx/cypress`), and more. These plugins offer additional features, making your development experience more efficient and enjoyable when working with specific tech stacks. + +[visit our "Why Nx" page](/getting-started/why-nx) for more deails. + ## Creating New Components -You can just create new React components as you normally would. However, Nx plugins usually also ship [generators](/plugin-features/use-code-generators). They allow you to easily scaffold code, configuration or entire projects. To see what capabilities the `@nx/react` plugin ships, run the following command and inspect the output: +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=706" /%} + +You can just create new React components as you normally would. However, Nx plugins usually also ship [generators](/core-features/plugin-features/use-code-generators). They allow you to easily scaffold code, configuration or entire projects. To see what capabilities the `@nx/react` plugin ships, run the following command and inspect the output: ```shell {% command="npx nx list @nx/react" path="myreactapp" %} @@ -289,6 +316,8 @@ export default HelloWorld; ## Building the App for Deployment +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=856" /%} + If you're ready and want to ship your application, you can build it using ```shell {% command="npx nx build" path="myreactapp" %} @@ -308,6 +337,8 @@ All the required files will be placed in the `dist/myreactapp` folder and can be ## You're ready to go! +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=906" /%} + In the previous sections you learned about the basics of using Nx, running tasks and navigating an Nx workspace. You're ready to ship features now! But there's more to learn. You have two possibilities here: @@ -317,6 +348,8 @@ But there's more to learn. You have two possibilities here: ## Modularizing your React App with Local Libraries +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=986" /%} + When you develop your React application, usually all your logic sits in the `app` folder. Ideally separated by various folder names which represent your "domains". As your app grows, this becomes more and more monolithic though. ``` @@ -346,6 +379,8 @@ Nx allows you to separate this logic into "local libraries". The main benefits i ### Creating Local Libraries +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1041" /%} + Let's assume our domain areas include `products`, `orders` and some more generic design system components, called `ui`. We can generate a new library for each of these areas using the React library generator: ``` @@ -410,6 +445,8 @@ Each of these libraries ### Importing Libraries into the React Application +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1245" /%} + All libraries that we generate automatically have aliases created in the root-level `tsconfig.base.json`. ```json {% fileName="tsconfig.base.json" %} @@ -434,7 +471,7 @@ nx g @nx/react:component product-list --project=modules-products We don't need to implement anything fancy as we just want to learn how to import it into our main React application. -```tsx {% fileName="modules/products/src/lib/product-list.tsx" %} +```tsx {% fileName="modules/products/src/lib/product-list/product-list.tsx" %} import styles from './product-list.module.css'; /* eslint-disable-next-line */ @@ -544,6 +581,8 @@ export default App; ## Visualizing your Project Structure +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1416" /%} + Nx automatically detects the dependencies between the various parts of your workspace and builds a [project graph](/core-features/explore-graph). This graph is used by Nx to perform various optimizations such as determining the correct order of execution when running tasks like `nx build`, identifying [affected projects](/core-features/run-tasks#run-tasks-affected-by-a-pr) and more. Interestingly you can also visualize it. Just run: @@ -621,6 +660,8 @@ Exercise for you: change the codebase such that `modules-shared-ui` is used by ` ## Imposing Constraints with Module Boundary Rules +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1456" /%} + Once you modularize your codebase you want to make sure that the modules are not coupled to each other in an uncontrolled way. Here are some examples of how we might want to guard our small demo workspace: - we might want to allow `modules-orders` to import from `modules-shared-ui` but not the other way around @@ -777,18 +818,18 @@ If you have the ESLint plugin installed in your IDE you should immediately see a ![ESLint module boundary error](/shared/images/tutorial-react-standalone/react-standalone-module-boundaries.png) -Learn more about how to [enforce module boundaries](/core-features/enforce-project-boundaries). +Learn more about how to [enforce module boundaries](/core-features/enforce-module-boundaries). ## Next Steps Here's some more things you can dive into next: - Learn more about the [underlying mental model of Nx](/concepts/mental-model) -- Learn how to [migrate your CRA app to Nx](/recipes/adopting-nx/migration-cra) -- [Learn how to setup Tailwind](/recipes/other/using-tailwind-css-in-react) +- Learn how to [migrate your CRA app to Nx](/recipes/react/migration-cra) +- [Learn how to setup Tailwind](/recipes/react/using-tailwind-css-in-react) - [Setup Storybook for our shared UI library](/packages/storybook/documents/overview-react) - [Speed up CI: Run only tasks for project that got changed](/core-features/run-tasks#run-tasks-affected-by-a-pr)] -- [Speed up CI: Share your cache](/core-features/share-your-cache)] +- [Speed up CI: Share your cache](/core-features/remote-cache)] - [Speed up CI: Distribute your tasks across machines](/core-features/distribute-task-execution) Also, make sure you diff --git a/docs/shared/react-tutorial/5-summary.md b/docs/shared/react-tutorial/5-summary.md index 0b50a4fb9881f..1ccf19eba1d22 100644 --- a/docs/shared/react-tutorial/5-summary.md +++ b/docs/shared/react-tutorial/5-summary.md @@ -13,7 +13,7 @@ In this tutorial you: {% card title="Core Features" description="Read about the core features of Nx." url="/core-features" /%} -{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/plugin-features" /%} +{% card title="Plugin Features" description="Read about the plugin features of Nx." url="/core-features/plugin-features" /%} {% card title="Mental Model" description="Get a deeper understanding of the mental model." url="/concepts/mental-model" /%} diff --git a/docs/shared/recipes/add-stack/add-lit.md b/docs/shared/recipes/add-stack/add-lit.md new file mode 100644 index 0000000000000..9958fe6a4a71a --- /dev/null +++ b/docs/shared/recipes/add-stack/add-lit.md @@ -0,0 +1,206 @@ +# Add a New Lit Project + +The code for this example is available on Github: + +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/lit" /%} + +**Supported Features** + +Because we are not using an Nx plugin for Lit, there are few items we'll have to configure manually. We'll have to configure our own build system. There are no pre-created Lit-specific code generators. And we'll have to take care of updating any framework dependencies as needed. + +{% pill url="/core-features/run-tasks" %}✅ Run Tasks{% /pill %} +{% pill url="/core-features/cache-task-results" %}✅ Cache Task Results{% /pill %} +{% pill url="/core-features/remote-cache" %}✅ Share Your Cache{% /pill %} +{% pill url="/core-features/explore-graph" %}✅ Explore the Graph{% /pill %} +{% pill url="/core-features/distribute-task-execution" %}✅ Distribute Task Execution{% /pill %} +{% pill url="/core-features/integrate-with-editors" %}✅ Integrate with Editors{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}✅ Automate Updating Nx{% /pill %} +{% pill url="/core-features/enforce-module-boundaries" %}✅ Enforce Module Boundaries{% /pill %} +{% pill url="/core-features/plugin-features/use-task-executors" %}🚫 Use Task Executors{% /pill %} +{% pill url="/core-features/plugin-features/use-code-generators" %}🚫 Use Code Generators{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}🚫 Automate Updating Framework Dependencies{% /pill %} + +## Install Lit and Other Dependencies + +Install all the dependencies we need: + +{% tabs %} +{%tab label="npm"%} + +```shell +npm i --save-dev @nx/node lit http-server +``` + +{% /tab %} +{%tab label="yarn"%} + +```shell +yarn add --dev @nx/node lit http-server +``` + +{% /tab %} +{% /tabs %} + +## Create an Application + +We'll start with a node application and then tweak the settings to match what we need. Add a new node application to your workspace with the following command: + +```shell +nx g @nx/node:app my-lit-app +``` + +Choose `none` for the node framework, since we won't be using this as a node app. + +### Turn the Application into a Lit Application + +Update `main.ts`: + +```typescript {% fileName="apps/my-lit-app/src/main.ts" %} +import { LitElement, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +@customElement('my-element') +export class MyElement extends LitElement { + @property() + version = 'STARTING'; + + render() { + return html` +

Welcome to the Lit tutorial!

+

This is the ${this.version} code.

+ `; + } +} +``` + +Create `index.html`: + +```html {% fileName="apps/my-lit-app/index.html" %} + + + + + + + + + + +``` + +### Update the Build Task + +In the `project.json` file update the `options` under the `build` target. The properties that need to change are `format`, `bundle`, `thirdParty`, and `assets`: + +```json {% fileName="apps/my-lit-app/project.json" %} +{ + "targets": { + "build": { + "executor": "@nx/esbuild:esbuild", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/apps/my-lit-app", + "format": ["esm"], + "bundle": true, + "thirdParty": true, + "main": "apps/my-lit-app/src/main.ts", + "tsConfig": "apps/my-lit-app/tsconfig.app.json", + "assets": ["apps/my-lit-app/src/assets", "apps/my-lit-app/index.html"], + "generatePackageJson": true, + "esbuildOptions": { + "sourcemap": true, + "outExtension": { + ".js": ".js" + } + } + } + } + } +} +``` + +Now, when you run the build, there should be `index.html`, `main.js` and `package.json` under `dist/apps/my-lit-app`. Try it out: + +```shell +nx build my-lit-app +``` + +### Update the Serve Task + +To serve the app, we'll completely overwrite the existing `serve` task. Change it to this: + +```json {% fileName="apps/my-lit-app/project.json" %} +{ + "targets": { + "serve": { + "dependsOn": ["build"], + "executor": "nx:run-commands", + "options": { + "commands": [ + "http-server dist/apps/my-lit-app", + "nx watch --projects=my-lit-app --includeDependentProjects -- nx build my-lit-app" + ] + } + } + } +} +``` + +`"dependsOn": ["build"]` will ensure that the `build` task is always run before the `serve` task. The entries under `commands` will each be run in parallel. The `http-server` line serves the `build` output with a simple server. The `nx watch` line will automatically re-run the `build` task any time the application code or any project it depends on changes. + +Run the `serve` task and see your Lit app in action: + +```shell +nx serve my-lit-app +``` + +## Create a Library + +Let's create a library that our Lit application is going to consume. To create a new library, install the `@nx/js` package and run: + +```shell +nx g @nx/js:lib my-lib +``` + +Once the library is created, update the following files. + +```typescript {% fileName="libs/my-lib/src/lib/my-lib.ts" %} +export function someFunction(): string { + return 'some function'; +} +``` + +```typescript {% fileName="apps/my-lit-app/src/main.ts" %} +import { LitElement, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { someFunction } from '@my-org/my-lib'; + +@customElement('my-element') +export class MyElement extends LitElement { + @property() + version = 'STARTING'; + + render() { + return html` +

Welcome to the Lit tutorial!

+

This is the ${this.version} code.

+

Imported from a library: ${someFunction()}.

+ `; + } +} +``` + +Now when you serve your application, you'll see the content from the library being displayed. + +## More Documentation + +- [@nx/esbuild](/packages/esbuild) +- [@nx/js](/packages/js) +- [Lit](https://lit.dev/) diff --git a/docs/shared/recipes/add-stack/add-qwik.md b/docs/shared/recipes/add-stack/add-qwik.md new file mode 100644 index 0000000000000..5cd1fe5abef72 --- /dev/null +++ b/docs/shared/recipes/add-stack/add-qwik.md @@ -0,0 +1,270 @@ +# Add a New Qwik Project + +The code for this example is available on GitHub: + +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/qwik" /%} + +**Supported Features** + +We'll be using an Nx Plugin for Qwik called [qwik-nx](https://github.com/qwikifiers/qwik-nx). + +{% pill url="/core-features/run-tasks" %}✅ Run Tasks{% /pill %} +{% pill url="/core-features/cache-task-results" %}✅ Cache Task Results{% /pill %} +{% pill url="/core-features/remote-cache" %}✅ Share Your Cache{% /pill %} +{% pill url="/core-features/explore-graph" %}✅ Explore the Graph{% /pill %} +{% pill url="/core-features/distribute-task-execution" %}✅ Distribute Task Execution{% /pill %} +{% pill url="/core-features/integrate-with-editors" %}✅ Integrate with Editors{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}✅ Automate Updating Nx{% /pill %} +{% pill url="/core-features/enforce-module-boundaries" %}✅ Enforce Module Boundaries{% /pill %} +{% pill url="/core-features/plugin-features/use-task-executors" %}✅ Use Task Executors{% /pill %} +{% pill url="/core-features/plugin-features/use-code-generators" %}✅ Use Code Generators{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}✅ Automate Updating Framework Dependencies{% /pill %} + +## Install the qwik-nx Plugin + +Install the `qwik-nx` plugin: + +{% tabs %} +{%tab label="npm"%} + +```shell +npm i --save-dev qwik-nx +``` + +{% /tab %} +{%tab label="yarn"%} + +```shell +yarn add --dev qwik-nx +``` + +{% /tab %} +{%tab label="pnpm"%} + +```shell +pnpm i --dev qwik-nx +``` + +{% /tab %} +{% /tabs %} + +{% callout type="note" title="Nx Version Compatibility" %} +You can find a compatibility matrix for `qwik-nx` +here: https://github.com/qwikifiers/qwik-nx#qwik-nx--nx-compatibility-chart. +You can use this to help you understand which version of `qwik-nx` you should install based on the version of `nx` you +are currently using. +If you need help finding the version of `nx` you are currently using, run `nx report`. +{% /callout %} + +## Create the application + +Let's generate a new application using `qwik-nx`. + +```shell +nx g qwik-nx:app todo +``` + +## Create a library + +Let's generate a new library using `qwik-nx`. + +```shell +nx g qwik-nx:lib data-access +``` + +## Create a Context in the library + +We'll add a `Context` to the library to store some state. + +Create a new file `libs/data-access/src/lib/todo.context.tsx` with the following content: + +```tsx +import { + component$, + createContextId, + Slot, + useContextProvider, + useStore, +} from '@builder.io/qwik'; + +export interface Todo { + id: number; + message: string; +} + +interface TodoStore { + todos: Todo[]; + lastId: number; +} + +export const TodoContext = createContextId('todo.context'); + +export const TodoContextProvider = component$(() => { + const todoStore = useStore({ + todos: [], + lastId: 0, + }); + + useContextProvider(TodoContext, todoStore); + + return ; +}); +``` + +We'll use this context to store the state for our application. + +Let's create a new file to handle some of the logic for our application. + +Create `libs/data-access/src/lib/todo.ts` and add the following: + +```ts +import { Todo } from './todo.context'; + +// A rudimentary in-mem DB that will run on the server +interface DB { + store: Record; + get: (storeName: string) => any[]; + set: (storeName: string, value: any[]) => boolean; + add: (storeName: string, value: any) => boolean; +} + +export const db: DB = { + store: { todos: [] }, + get(storeName) { + return db.store[storeName]; + }, + set(storeName, value) { + try { + db.store[storeName] = value; + return true; + } catch (e) { + return false; + } + }, + add(storeName, value) { + try { + db.store[storeName].push(value); + return true; + } catch (e) { + return false; + } + }, +}; + +export function getTodos() { + // A network request or db connection could be made here to fetch persisted todos + // For illustrative purposes, we're going to seed a rudimentary in-memory DB if it hasn't been already + // Then return the value from it + if (db.get('todos')?.length === 0) { + db.set('todos', [ + { + id: 1, + message: 'First todo', + }, + ]); + } + const todos: Todo[] = db.get('todos'); + const lastId = [...todos].sort((a, b) => b.id - a.id)[0].id; + return { todos, lastId }; +} + +export function addTodo(todo: { id: string; message: string }) { + const success = db.add('todos', { + id: parseInt(todo.id), + message: todo.message, + }); + return { success }; +} +``` + +Update `libs/data-access/src/index.ts` to export our new context and methods: + +```ts +export * from './lib/todo.context'; +export * from './lib/todo'; +``` + +## Generate a Route + +Next, let's generate a route to store the logic for the application. + +```shell +nx g qwik-nx:route --name=todo --project=todo +``` + +We will use our new context +Update the new route file (`apps/todo/src/routes/todo/index.tsx`) to the following: + +```tsx +import { component$, useContext, useTask$ } from '@builder.io/qwik'; +import { + Form, + routeAction$, + routeLoader$, + z, + zod$, +} from '@builder.io/qwik-city'; +import { addTodo, getTodos, TodoContext } from '@acme/data-access'; + +export const useGetTodos = routeLoader$(() => getTodos()); + +export const useAddTodo = routeAction$( + (todo) => addTodo(todo), + zod$({ id: z.string(), message: z.string() }) +); + +export default component$(() => { + const todoStore = useContext(TodoContext); + const persistedTodos = useGetTodos(); + const addTodoAction = useAddTodo(); + + useTask$(({ track }) => { + track(() => persistedTodos.value); + if (persistedTodos.value) { + todoStore.todos = persistedTodos.value.todos; + todoStore.lastId = + todoStore.lastId > persistedTodos.value.lastId + ? todoStore.lastId + : persistedTodos.value.lastId; + } + }); + + return ( +
+

Todos

+ {todoStore.todos.map((t) => ( +
+ +
+ ))} +
+ + + +
+ {addTodoAction.value?.success &&

Todo added!

} +
+ ); +}); +``` + +## Build and Serve the Application + +To serve the application, run the following command and then navigate your browser to `http://localhost:4200/todo` + +```shell +nx serve todo +``` + +To build the application, run the following command: + +```shell +nx build todo +``` + +## More Documentation + +- [Qwik](https://qwik.builder.io) +- [qwik-nx](https://github.com/qwikifiers/qwik-nx) diff --git a/docs/shared/recipes/add-stack/add-solid.md b/docs/shared/recipes/add-stack/add-solid.md new file mode 100644 index 0000000000000..798ce9f50f90e --- /dev/null +++ b/docs/shared/recipes/add-stack/add-solid.md @@ -0,0 +1,310 @@ +# Add a New Solid Project + +The code for this example is available on GitHub: + +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/solidjs" %} + +**Supported Features** + +Because we are not using an Nx plugin for Solid, there are few items we'll have to configure manually. We'll have to +configure our own build system. There are no pre-created Solid-specific code generators. And we'll have to take care of +updating any framework dependencies as needed. + +{% pill url="/core-features/run-tasks" %}✅ Run Tasks{% /pill %} +{% pill url="/core-features/cache-task-results" %}✅ Cache Task Results{% /pill %} +{% pill url="/core-features/remote-cache" %}✅ Share Your Cache{% /pill %} +{% pill url="/core-features/explore-graph" %}✅ Explore the Graph{% /pill %} +{% pill url="/core-features/distribute-task-execution" %}✅ Distribute Task Execution{% /pill %} +{% pill url="/core-features/integrate-with-editors" %}✅ Integrate with Editors{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}✅ Automate Updating Nx{% /pill %} +{% pill url="/core-features/enforce-module-boundaries" %}✅ Enforce Module Boundaries{% /pill %} +{% pill url="/core-features/plugin-features/use-task-executors" %}🚫 Use Task Executors{% /pill %} +{% pill url="/core-features/plugin-features/use-code-generators" %}🚫 Use Code Generators{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}🚫 Automate Updating Framework Dependencies{% /pill %} + +## Install Solid and Other Dependencies + +{% tabs %} +{% tab label="npm" %} + +```shell +npm i solid-js +npm i --save-dev @nx/web solid-devtools vite-plugin-solid +``` + +{% /tab %} +{% tab label="yarn" %} + +```shell +yarn add solid-js +yarn add --dev @nx/web solid-devtools vite-plugin-solid +``` + +{% /tab %} +{% tab label="pnpm" %} + +```shell +pnpm i solid-js +pnpm i --save-dev @nx/web solid-devtools vite-plugin-solid +``` + +{% /tab %} +{% /tabs %} + +## Create an Application + +We'll start with a web application and then tweak the settings to match what we need. Add a new web application to your +workspace with the following command: + +```shell +nx g @nx/web:app my-solid-app --bundler=vite +``` + +The `@nx/web:app` generator will create some files that are unnecessary for our Solid application. + +The files to be deleted are: + +- `apps/my-solid-app/src/public` +- `apps/my-solid-app/src/app` +- `apps/my-solid-app/main.ts` +- `apps/my-solid-app/styles.css` +- `apps/my-solid-app/.babelrc` + +### Turn the Application into a Solid Application + +Now we'll create the files that are necessary to turn our application into a Solid application. + +**Add the following files** + +```tsx {% fileName="apps/my-solid-app/src/App.tsx" %} +import type { Component } from 'solid-js'; + +const App: Component = () => { + return ( +
+
+

+ Edit src/App.tsx and save to reload. +

+ + Learn Solid Now + +
+
+ ); +}; + +export default App; +``` + +```tsx {% fileName="apps/my-solid-app/src/index.tsx" %} +/* @refresh reload */ +import { render } from 'solid-js/web'; + +import App from './App'; + +const root = document.getElementById('root'); + +if (import.meta.env.DEV && !(root instanceof HTMLElement)) { + throw new Error( + 'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?' + ); +} + +render(() => , root!); +``` + +**Update the following files** + +```html {% fileName="apps/my-solid-app/index.html" %} + + + + + + + Solid App + + + +
+ + + + +``` + +```ts {% fileName="apps/my-solid-app/vite.config.ts" %} +/// +import { defineConfig } from 'vite'; +import solidPlugin from 'vite-plugin-solid'; +// import devtools from 'solid-devtools/vite'; + +import viteTsConfigPaths from 'vite-tsconfig-paths'; + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/my-solid-app', + + server: { + port: 3000, + }, + + build: { + target: 'esnext', + }, + + plugins: [ + viteTsConfigPaths({ + root: '../../', + }), + /* + Uncomment the following line to enable solid-devtools. + For more info see https://github.com/thetarnav/solid-devtools/tree/main/packages/extension#readme + */ + // devtools(), + solidPlugin(), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + test: { + globals: true, + cache: { + dir: '../../node_modules/.vitest', + }, + environment: 'jsdom', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + }, +}); +``` + +```json {% fileName="apps/my-solid-app/tsconfig.json" %} +{ + "extends": "../../tsconfig.base.json", + "files": [], + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "moduleResolution": "Node", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "skipLibCheck": true, + "types": ["vite/client", "vitest"] + }, + "include": ["src"], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} +``` + +You can now run `nx serve my-solid-app` and your Solid application can be viewed in your browser! + +## Create a Library + +Let's create a library that our Solid application is going to consume. To create a new library, install the `@nx/js` +package and run: + +```shell +nx g @nx/js:lib my-lib +``` + +Once the library is created, update the following files. + +Rename `libs/my-lib/src/lib/my-lib.ts` -> `libs/my-lib/src/lib/my-lib.tsx`, then edit the contents to: + +```tsx {% fileName="libs/my-lib/src/lib/my-lib.tsx" %} +export function MyLibComponent(props: { name: string }) { + return

Hello {props.name} from MyLib

; +} +``` + +```json {% fileName="libs/my-lib/tsconfig.json" %} +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vitest"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} +``` + +```tsx {% fileName="apps/my-solid-app/src/App.tsx" %} +import type { Component } from 'solid-js'; +import { MyLibComponent } from '@acme/my-lib'; + +const App: Component = () => { + return ( +
+
+

+ Edit src/App.tsx and save to reload. +

+ + + Learn Solid Now + +
+
+ ); +}; + +export default App; +``` + +Now when you serve your application, you'll see the content from the library being displayed. + +## More Documentation + +- [@nx/vite](/packages/vite) +- [@nx/js](/packages/js) +- [@nx/web](/packages/web) +- [Solid](https://www.solidjs.com/) diff --git a/docs/shared/recipes/azure-last-successful-commit.md b/docs/shared/recipes/azure-last-successful-commit.md deleted file mode 100644 index f8aa79bccf581..0000000000000 --- a/docs/shared/recipes/azure-last-successful-commit.md +++ /dev/null @@ -1,82 +0,0 @@ -# Get the Commit of the Last Successful Build in Azure Pipelines - -The idea is to use [Azure Devops CLI](https://learn.microsoft.com/en-us/cli/azure/pipelines?view=azure-cli-latest) -directly in the [Pipeline Yaml](https://learn.microsoft.com/en-us/azure/devops/cli/azure-devops-cli-in-yaml?view=azure-devops) - -First, we configure Devops CLI - -```yaml -# Set Azure Devops default settings -- bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject) - displayName: 'Configure Azure DevOps organization and project' -``` - -Then we can query the pipelines API (providing the auth token) - -```yaml -# Get last successfully commit infos from Azure Devops -- bash: | - LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\"ci.sourceSha\"") - echo "Last successful commit SHA: $LAST_SHA" - echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA" - displayName: 'Get last successful commit SHA' - env: - AZURE_DEVOPS_EXT_PAT: $(System.AccessToken) -``` - -We can target a specific build, in this example we specified: - -- The branch (--branch) -- The pipeline Id (--definition-ids) -- The result type (--result) -- The number of result (-top) - -By default the command returns an entire JSON object with all the information. But we can narrow it down to the desired result with the `--query` param that uses [JMESPath](https://jmespath.org/) format ([more details](https://learn.microsoft.com/en-us/cli/azure/query-azure-cli?tabs=concepts%2Cbash)) - -Finally we extract the result in a common [custom variable](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-variables-scripts?view=azure-devops&tabs=bash) named `BASE_SHA` used later by `nx affected` commands - -An example with a default SHA in case no commit is found: - -```yaml {% fileName="azure-pipelines.yml" %} -trigger: - - main -pr: - - main - -variables: - CI: 'true' - NX_BRANCH: $(Build.SourceBranchName) - DEFAULT_BASE_SHA: $(git rev-parse HEAD~1) - HEAD_SHA: $(git rev-parse HEAD) - -jobs: - - job: main - pool: - vmImage: 'ubuntu-latest' - steps: - # Set Azure Devops CLI default settings - - bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject) - displayName: 'Set default Azure DevOps organization and project' - - # Get last successfull commit from Azure Devops CLI - - bash: | - LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\"ci.sourceSha\"") - if [ -z "$LAST_SHA" ] - then - LAST_SHA=$DEFAULT_BASE_SHA - fi - echo "Last successful commit SHA: $LAST_SHA" - echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA" - displayName: 'Get last successful commit SHA' - env: - AZURE_DEVOPS_EXT_PAT: $(System.AccessToken) - - - script: npm ci - - - script: npx nx workspace-lint - - script: npx nx format:check - - - script: npx nx affected --base=$(BASE_SHA) -t lint --parallel=3 - - script: npx nx affected --base=$(BASE_SHA) -t test --parallel=3 --ci --code-coverage - - script: npx nx affected --base=$(BASE_SHA) -t build --parallel=3 -``` diff --git a/docs/shared/recipes/console-generate-command.md b/docs/shared/recipes/console-generate-command.md index 402cd0b5245f9..d0393ba635d7b 100644 --- a/docs/shared/recipes/console-generate-command.md +++ b/docs/shared/recipes/console-generate-command.md @@ -5,7 +5,7 @@ The `Generate` action allows you to choose a generator and then opens a form lis {% youtube src="https://www.youtube.com/embed/-nUr66MWRiE" title="Nx Console Generate UI Form" -width="100%" /%} +/%} **From the Command Palette** @@ -14,11 +14,11 @@ You can also launch the `Generate` action from the Command Palette (`⇧⌘P`) b {% youtube src="https://www.youtube.com/embed/Sk2XjFwF8Zo" title="Nx Console Generate UI from Command Palette" -width="100%" /%} +/%} You can even construct the generator options while staying entirely within the Command Palette. Use `⇧⌘P` to open the Command Palette, then select `nx: generate`. After choosing a generator, select any of the listed options to modify the generator command. When you're satisfied with the constructed command, choose the `Execute` command at the top of the list. {% youtube src="https://www.youtube.com/embed/q5NTTqRYq9c" title="Nx Console Generate with Command Palette" -width="100%" /%} +/%} diff --git a/docs/shared/recipes/console-project-pane.md b/docs/shared/recipes/console-project-pane.md index 5b7a791f524ad..416bd91b1acdf 100644 --- a/docs/shared/recipes/console-project-pane.md +++ b/docs/shared/recipes/console-project-pane.md @@ -11,4 +11,4 @@ Clicking the ![continue-light.svg](/shared/images/nx-console/continue-light.svg) {% youtube src="https://www.youtube.com/embed/ve_N3unDqAg" title="Nx Console Projects Pane" -width="100%" /%} +/%} diff --git a/docs/shared/recipes/console-run-command.md b/docs/shared/recipes/console-run-command.md index 67c0a07110399..f5daa755c2b5f 100644 --- a/docs/shared/recipes/console-run-command.md +++ b/docs/shared/recipes/console-run-command.md @@ -6,4 +6,4 @@ You can also use `Nx: Run Target` to select a target first and then a matching p {% youtube src="https://www.youtube.com/embed/CsUkSyQcxwQ" title="Nx Console Run from Command Palette" -width="100%" /%} +/%} diff --git a/docs/shared/recipes/deployment/node-server-fly-io.md b/docs/shared/recipes/deployment/node-server-fly-io.md index e428be140d58d..54b39883e25ec 100644 --- a/docs/shared/recipes/deployment/node-server-fly-io.md +++ b/docs/shared/recipes/deployment/node-server-fly-io.md @@ -72,7 +72,7 @@ That's is! Our server is now deployed for the world to use. You can also automate the deployment by adding a target to your project. In addition, that allows us to leverage the Nx [task pipeline](/concepts/task-pipeline-configuration) to make sure we first run the `build` and then the `deploy`. -By using [Nx run-commands](/recipes/executors/run-commands-executor), you can add a `deploy` target to the project. Go to the project's `project.json` file (under `"targets"`) and add the following: +By using [Nx run-commands](/recipes/tips-n-tricks/run-commands-executor), you can add a `deploy` target to the project. Go to the project's `project.json` file (under `"targets"`) and add the following: ```json {% fileName="project.json" %} "deploy": { diff --git a/docs/shared/recipes/export-project-graph.md b/docs/shared/recipes/export-project-graph.md deleted file mode 100644 index 6e8ec7ca1058a..0000000000000 --- a/docs/shared/recipes/export-project-graph.md +++ /dev/null @@ -1,9 +0,0 @@ -## Export Project Graph to JSON - -If you prefer to analyze the underlying data of the project graph with a script or some other tool, you can run: - -```shell -nx graph --file=output.json -``` - -This will give you all the information that is used to create the project graph visualization. diff --git a/docs/shared/recipes/generators/local-generators.md b/docs/shared/recipes/generators/local-generators.md index ffe2ba3511ce3..1d471b3509b2a 100644 --- a/docs/shared/recipes/generators/local-generators.md +++ b/docs/shared/recipes/generators/local-generators.md @@ -5,9 +5,10 @@ Local plugin generators provide a way to automate many tasks you regularly perfo Nx provides tooling around creating, and running custom generators from within your workspace. This guide shows you how to create, run, and customize generators within your Nx workspace. {% youtube -src="https://www.youtube.com/embed/ubgroK5T6cA" -title="Create a Nx Generator in 100 seconds" -width="100%" /%} +src="https://www.youtube.com/embed/myqfGDWC2go" +title="Scaffold new Pkgs in a PNPM Workspaces Monorepo" +caption="Demoes how to use Nx generators in a PNPM workspace to automate the creation of libraries" +/%} ## Creating a generator diff --git a/docs/shared/recipes/generators/modifying-files.md b/docs/shared/recipes/generators/modifying-files.md index 5d0f25c35c1af..83d3504a28aa8 100644 --- a/docs/shared/recipes/generators/modifying-files.md +++ b/docs/shared/recipes/generators/modifying-files.md @@ -4,7 +4,7 @@ Modifying existing files is an order of magnitude harder than creating new files ## Compose Existing Generators -If you can compose together existing generators to modify the files you need, you should take that approach. See [Composing Generators](/plugins/recipes/composing-generators) for more information. +If you can compose together existing generators to modify the files you need, you should take that approach. See [Composing Generators](/extending-nx/recipes/composing-generators) for more information. ## Modify JSON Files diff --git a/docs/shared/recipes/include-assets-in-build.md b/docs/shared/recipes/include-assets-in-build.md index 6de805226f2e3..d2749dc21b977 100644 --- a/docs/shared/recipes/include-assets-in-build.md +++ b/docs/shared/recipes/include-assets-in-build.md @@ -9,7 +9,7 @@ There are two ways to identify assets to be copied into the output bundle: ```jsonc {% fileName="project.json" %} "build": { - "executor": "@nx/node:package", + "executor": "@nx/js:tsc", // or any other Nx executor that supports the `assets` option "options": { // shortened... "assets": [ diff --git a/docs/shared/recipes/module-federation-with-ssr.md b/docs/shared/recipes/module-federation-with-ssr.md index f540c24b9c608..82ab3631076fa 100644 --- a/docs/shared/recipes/module-federation-with-ssr.md +++ b/docs/shared/recipes/module-federation-with-ssr.md @@ -133,5 +133,5 @@ To serve the `store` application and watch for changes on the `checkout` applica To learn more about Module Federation, we have some resources you might find useful: -- [Guide: Faster Builds with Module Federation](/recipes/module-federation/faster-builds) +- [Guide: Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) - [Video: Speed up your Angular serve and build times with Module Federation and Nx](https://www.youtube.com/watch?v=JkcaGzhRjkc) diff --git a/docs/shared/recipes/one-storybook-per-scope.md b/docs/shared/recipes/one-storybook-per-scope.md index 34cf3a5d23f83..305822470df17 100644 --- a/docs/shared/recipes/one-storybook-per-scope.md +++ b/docs/shared/recipes/one-storybook-per-scope.md @@ -3,7 +3,7 @@ This guide extends the [Using Storybook in a Nx workspace - Best practices](/packages/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](/more-concepts/library-types) documentation page, and also in the [Code Organization and Naming Conventions](/more-concepts/monorepo-nx-enterprise#code-organization-&-naming-conventions) documentation section. +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, and also in the [Code Organization and Naming Conventions](/concepts/more-concepts/monorepo-nx-enterprise#code-organization-&-naming-conventions) documentation section. 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. diff --git a/docs/shared/recipes/plugins/create-preset.md b/docs/shared/recipes/plugins/create-preset.md index 6d421da6f4f28..0948bcd82e32e 100644 --- a/docs/shared/recipes/plugins/create-preset.md +++ b/docs/shared/recipes/plugins/create-preset.md @@ -1,4 +1,4 @@ -## Preset +# Create a Custom Plugin Preset When you create a new nx workspace, you run the command: [`npx create-nx-workspace`](/packages/nx/documents/create-nx-workspace). This command accepts a `--preset` option, for example: `npx create-nx-workspace --preset=react-standalone`. @@ -7,32 +7,34 @@ This preset option is pointing to a special generator function (remember, a gene {% youtube src="https://www.youtube.com/embed/yGUrF0-uqaU" title="Develop a Nx Preset for your Nx Plugin" -width="100%" /%} +/%} -### Custom Preset +## What is a preset? -At its core a preset is a generator, which we can create inside of a plugin. +At its core, a preset is a special [generator](/core-features/plugin-features/use-code-generators) that is shipped as part of an Nx Plugin package. -All first-party Nx presets are built into nx itself, but you can [create your own plugin](/plugins/intro/getting-started) and create a generator with the magic name: `preset`. Once you've [published your plugin](/plugins/tutorials/publish-plugin) on npm, you can now run. the create-nx-workspace command with the preset option set to the name of your published package. +All first-party Nx presets are built into Nx itself, but you can [create your own plugin](/extending-nx/intro/getting-started) and create a generator with the magic name: `preset`. Once you've [published your plugin](/extending-nx/tutorials/publish-plugin) on npm, you can now run the `create-nx-workspace` command with the preset option set to the name of your published package. -For example, take +To use a concrete example, let's look at the [`qwik-nx`](https://www.npmjs.com/package/qwik-nx) Nx community plugin. They include a [preset generator](https://github.com/qwikifiers/qwik-nx/tree/main/packages/qwik-nx/src/generators/preset) that you can use to create a new Nx workspace with Qwik support. ```shell npx create-nx-workspace --preset=qwik-nx ``` -This command will create a new Qwik preset based on the [published npm package: `qwik-nx`](https://www.npmjs.com/package/qwik-nx). If we check this package's source code, we can see that it has a [generator named `preset`](https://github.com/qwikifiers/qwik-nx/tree/main/packages/qwik-nx/src/generators/preset). +## Create a new Nx plugin If you **don't** have an existing plugin you can create one by running ```shell - npx create-nx-plugin my-org --pluginName my-plugin +npx create-nx-plugin my-org --pluginName my-plugin ``` +## Creating a "Preset" generator + To create our preset inside of our plugin we can run ```shell - nx generate @nx/plugin:generator --name=preset --project=happynrwl +nx generate @nx/plugin:generator --name=preset --project=happynrwl ``` {% callout type="warning" title="Double check" %} @@ -88,9 +90,9 @@ export default async function (tree: Tree, options: PresetGeneratorSchema) { } ``` -To get an in-depth guide on customizing/running or debugging your generator see [local generators](/plugins/recipes/local-generators). +To get an in-depth guide on customizing/running or debugging your generator see [local generators](/extending-nx/recipes/local-generators). -#### Usage +## Usage Before you are able to use your newly created preset you must package and publish it to a registry. diff --git a/docs/shared/recipes/repo-types/integrated-in-package-based.md b/docs/shared/recipes/repo-types/integrated-in-package-based.md new file mode 100644 index 0000000000000..d868eca84f309 --- /dev/null +++ b/docs/shared/recipes/repo-types/integrated-in-package-based.md @@ -0,0 +1,34 @@ +# Add an Integrated Project in a Package-based Repository + +In a package-based repository, you've intentionally opted out of some of Nx's features in order to give yourself more flexibility. If you decide to add a new project using the integrated style, the process is straight-forward. + +To add an integrated project: + +1. Install the plugin you want to use (i.e. `npm install @nx/react`) +2. Generate an application or library using that plugin (i.e. `nx g @nx/react:app`) + +The integrated project is now ready to use. Next, we'll discuss some of the changes that were applied to your codebase. + +## 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](/core-features/automate-updating-dependencies) feature, we recommend using a [Single Version Policy](/concepts/more-concepts/dependency-management#single-version-policy) for integrated projects. + +## tsconfig.base.json + +Even if the project you added only uses javascript, a `tsconfig.base.json` file is generated in the root of the repo. This file is needed for the tooling that Nx provides. Nx creates a typescript `path` alias for each library and then uses that path (rather than npm/yarn/pnpm workspaces) to allow local projects to reference the library. + +## project.json + +The project itself will have a `project.json` file that defines all the tasks that can be run on the project. This includes tasks like `build`, `serve` and `test`. See [Use Task Executors](/core-features/plugin-features/use-task-executors) for more information. + +## Other Configuration Files + +Depending on the type of integrated project you created, there may be other configuration files. These could include files like `.eslintrc.json`, `jest.config.ts` and a project-level `tsconfig.json`. + +## Code Generators + +The Nx plugin you installed provides code generators that you can use to scaffold out your application quickly and in a consistent way. See [Use Code Generators](/core-features/plugin-features/use-code-generators) for more information. + +## Summary + +You can opt in to using Nx's integrated features on a per project basis. This allows you to experiment with the functionality to see if the value those features provide is worth giving up some of the flexibility a package-based repository gives you. diff --git a/docs/shared/recipes/repo-types/package-based-in-integrated.md b/docs/shared/recipes/repo-types/package-based-in-integrated.md new file mode 100644 index 0000000000000..9cd741b4874f8 --- /dev/null +++ b/docs/shared/recipes/repo-types/package-based-in-integrated.md @@ -0,0 +1,83 @@ +# Add a Package-Based Project in an Integrated Repository + +An integrated repo offers a lot of features at the cost of some flexibility, but sometimes you want to take back control of your build system or dependency management for a single project in the repo. This recipe shows you how to do that. + +A package-based project in an integrated repository is a project that has at least one of these characteristics: + +1. Maintains its own dependencies with a separate `package.json` file +2. Defines tasks in a `package.json` file that don't use Nx executors + +For this example, we'll implement all three, but you can also have a project that has only one of these characteristics and falls back to an integrated style for the others. + +## Create Your Project + +Because this is a package-based project, we won't use Nx to generate the project. We can create the project in whatever way is typical for the framework you're trying to add. This could mean using the framework's own CLI or manually adding files yourself. + +For Nx to be aware of your project, it needs: + +1. npm, yarn or pnpm workspaces set up in the root `package.json` file +2. A `package.json` file in the project folder with a `name` specified +3. Some scripts defined in the project's `package.json` file for Nx to run + +## Setup NPM/Yarn/PNPM Workspaces + +If you choose to have this project define its dependencies separately from the root `package.json` file, simply define those `dependencies` and `devDependencies` in the project's `package.json` file. + +With [npm](https://docs.npmjs.com/cli/v7/using-npm/workspaces)/[yarn](https://classic.yarnpkg.com/lang/en/docs/workspaces/)/[pnpm](https://pnpm.io/workspaces) workspaces set up, you can run the install command at the root of the repository and every project will have its dependencies installed. + +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. + +## Run Tasks Without the Use of an Nx Plugin + +Any task you define in the scripts section of the project's `package.json` can be executed by Nx. These scripts can be cached and orchestrated in the same way a `target` defined in `project.json` is. If you want to define some tasks in `project.json` and some tasks in `package.json`, Nx will read both and merge the configurations. + +A typical set up where the `test` task depends on the `build` task could look like this: + +{% tabs %} +{% tab label="package.json" %} + +```jsonc {% fileName="package.json"%} +{ + "scripts": { + "build": "tsc", + "test": "jest" + }, + "nx": { + "targets": { + "test": { + "dependsOn": ["build"] + } + } + } +} +``` + +{% /tab %} +{% tab label="project.json" %} + +```jsonc {% fileName="project.json"%} +{ + "targets": { + "build": { + "command": "tsc" + }, + "test": { + "command": "jest", + "dependsOn": ["build"] + } + } +} +``` + +{% /tab %} +{% /tabs %} + +## Updating Dependencies + +Because this is a package-based project, you'll be managing your own updates for this project. In addition, you'll need to be careful when running the `nx migrate` command on the rest of the repo. There may be times where a migration changes code in this package-based project when it shouldn't. You'll need to manually revert those changes before committing. + +## Summary + +An integrated Nx repo does not lock you into only using Nx plugins for all of your projects. You can always opt-out of using certain features and take on the responsibility of managing that functionality yourself. diff --git a/docs/shared/recipes/repo-types/standalone-to-integrated.md b/docs/shared/recipes/repo-types/standalone-to-integrated.md new file mode 100644 index 0000000000000..b2bb6df00b6c0 --- /dev/null +++ b/docs/shared/recipes/repo-types/standalone-to-integrated.md @@ -0,0 +1,95 @@ +# Convert from a Standalone Repository to an Integrated Repository + +In many ways, a standalone repository is an integrated repository, but with one primary app located at the root of the repository. Both types of repos use plugins to generate code and to keep dependencies and config files up to date. Both types of repos use executors to hide away unneeded complexity. + +You can always add another app to a standalone repository the same way you would in an integrated repo. But at some point, you may want to move the primary app out of the root of your repo because the repo is no longer primarily focused on that one app. There are other apps that are equally important and you want the folder structure to align with the new reality. + +## Strategy + +For this recipe, we'll assume that the root-level app is named `my-app`. The high-level process we'll go through to move the app involves four stages: + +1. Create a new app named `temp` under `apps/temp`. +2. Move source and config files from `my-app` into `apps/temp`. +3. Delete the files for `my-app`. +4. Rename `apps/temp` to `apps/my-app` + +## Steps + +1. Update the `workspaceLayout` property in `nx.json` to be: + + ```jsonc {% fileName="nx.json" %} + { + "workspaceLayout": { + "appsDir": "apps", + "libsDir": "libs" + } + } + ``` + + This will make sure that new apps are created under `apps` and new libraries are created under `libs`. + +2. If there is a `tsconfig.json` file in the root, rename it to `tsconfig.old.json` + + This step is to make sure that a `tsconfig.base.json` file is generated by the app generator in the next step. + +3. Create a new app using the appropriate plugin under `apps/temp` + + ```shell + nx g app temp + ``` + +4. Move the `/src` (and `/public`, if present) folders to `apps/temp/`, overwriting the folders already there. + +5. For each config file in `apps/temp`, copy over the corresponding file from the root of the repo. + + It can be difficult to know which files are root-level config files and which files are project-specific config files. Here is a non-exhaustive list of config files to help distinguish between the two. + + | Type of Config | Files | + | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | _Root-level_ | `.eslintignore`, `.eslintrc.base.json`, `.gitignore`, `.prettierignore`, `jest.config.ts`, `jest.preset.js`, `.prettierrc`, `nx.json`, `package.json`, `tsconfig.base.json` | + | _Project-level_ | `.eslintrc.json`, `index.html`, `project.json`, `jest.config.app.ts`, `tsconfig.app.json`, `tsconfig.json`, `tsconfig.spec.json`, `vite.config.ts`, `webpack.config.js` | + + {% callout title="jest.config.app.ts" type="note" %} + `jest.config.app.ts` in the root should be renamed to `jest.config.ts` when moved to `apps/temp`. Also update the `jestConfig` option in `project.json` to point to `jest.config.ts` instead of `jest.config.app.ts`. + {% /callout %} + +6. Update the paths of the project-specific config files that were copied into `apps/temp`. + + Here is a non-exhaustive list of properties that will need to be updated to have the correct path: + + | Config File(s) | Properties to Check | + | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | `project.json` | `$schema`, `sourceRoot`, `root`, `outputPath`, `reportsDirectory`, `cypressConfig`, `lintFilePatterns`, `index`, `main`, `tsConfig`, `assets`, `styles`, `jestConfig` | + | `tsconfig.json`, `tsconfig.app.json`, `tsconfig.spec.json` | `extends`, `outDir`, `files` | + | `.eslintrc.json` | `extends` | + | `jest.config.ts` | `preset`, `coverageDirectory` | + | `vite.config.ts` | `cacheDir`, `root`, `dir` | + +7. Doublecheck that all the tasks defined in the `apps/temp/project.json` file still work. + + ```shell + nx build temp + nx test temp + nx lint temp + ``` + +8. Move the `/e2e/src` folder to `/apps/temp-e2e`, overwriting the folder already there +9. For each config file in `apps/temp-e2e`, copy over the corresponding file from the root of the repo. Update the paths for these files in the same way you did for the `my-app` config files. +10. Update the `/apps/temp-e2e/project.json` `implicitDependencies` to be `temp` instead of `my-app` +11. Doublecheck that all the tasks defined in the `apps/temp-e2e/project.json` file still work. + + ```shell + nx lint temp-e2e + nx e2e temp-e2e + ``` + +12. Delete all the project specific config files in the root and under `e2e` +13. Once the `project.json` file has been deleted in the root, rename `temp-e2e` to `my-app-e2e` and rename `temp` to `my-app` + + ```shell + nx g move --projectName=temp-e2e --destination=my-app-e2e + nx g move --projectName=temp --destination=my-app + ``` + +14. Update the `defaultProject` in `nx.json` if needed +15. Check again that all the tasks still work and that the `nx graph` displays what you expect. diff --git a/docs/shared/recipes/root-level-scripts.md b/docs/shared/recipes/root-level-scripts.md index 1cc4c2669def5..346ce713f4223 100644 --- a/docs/shared/recipes/root-level-scripts.md +++ b/docs/shared/recipes/root-level-scripts.md @@ -5,7 +5,7 @@ There are often tasks in a codebase that apply to the whole codebase rather than {% youtube src="https://www.youtube.com/embed/PRURABLaS8s" title="Run root-level NPM scripts with Nx" -width="100%" /%} +/%} ## Example @@ -98,7 +98,7 @@ Documentation site generated in /docs Nx read the output from the cache instead of running the command for 1 out of 1 tasks. ``` -Read more about [cacheableOperations](/core-features/cache-task-results) and fine-tuning caching with [task inputs](/more-concepts/customizing-inputs). +Read more about [cacheableOperations](/core-features/cache-task-results) and fine-tuning caching with [task inputs](/concepts/more-concepts/customizing-inputs). ## Keep using NPM to run scripts rather than Nx diff --git a/docs/shared/recipes/set-up-a-new-workspace.md b/docs/shared/recipes/set-up-a-new-workspace.md deleted file mode 100644 index 985a0084e90e6..0000000000000 --- a/docs/shared/recipes/set-up-a-new-workspace.md +++ /dev/null @@ -1,31 +0,0 @@ -# Set up a New Nx Workspace - -Run the following command to create a new workspace. - -```shell -# pass @latest in case npx cached an older version of create-nx-workspace -npx create-nx-workspace@latest -``` - -When creating a workspace, you will have to choose a preset, which will preconfigure a few things for you. - -```shell -# create an empty workspace set up for building applications -npx create-nx-workspace --preset=apps - -# create an empty workspace set up for building packages -npx create-nx-workspace --preset=core - -# create an empty workspace set up for building packages with the @nx/js plugin installed -npx create-nx-workspace --preset=ts -``` - -Some presets set up applications, e2e tests, etc. - -```shell -npx create-nx-workspace --preset=react-standalone -npx create-nx-workspace --preset=react-native -npx create-nx-workspace --preset=angular -``` - -For more information about possible options see the [create-nx-workspace command](/packages/nx/documents/create-nx-workspace). diff --git a/docs/shared/recipes/standalone-ngrx-apis.md b/docs/shared/recipes/standalone-ngrx-apis.md deleted file mode 100644 index e50bec27bb2e3..0000000000000 --- a/docs/shared/recipes/standalone-ngrx-apis.md +++ /dev/null @@ -1,65 +0,0 @@ -# Standalone APIs with NgRx and Angular 15 - -Standalone APIs were added to version 15 of [NgRx](https://ngrx.io), allowing for easier usage of NgRx with Standalone Components in Angular. -They must be added to routes definitions as they need to be added to the Environment Injector (https://ngrx.io/api/store/provideStore). - -Nx will use these Standalone APIs when: - -1. Standalone APIs are supported -2. Angular 15 is installed - -This guide will show you how to leverage this using the NgRx generator. - -{% callout type="check" title="Prerequisites" %} -Before following along with this guide, ensure you have: - -1. An Nx >= 15.6.0 Workspace with `@nx/angular` installed -2. Angular 15 must be installed - -{% /callout %} - -## Steps - -1. Generate an Angular application with Standalone Components and routing - -```bash -nx g @nx/angular:app testapp --standalone --routing -``` - -2. Generate NgRx Root State - -{% tabs %} -{% tab label="Nx Standalone Repo" %} - -```bash -nx g @nx/angular:ngrx --root --parent=testapp/src/main.ts -``` - -{% /tab %} -{% tab label="Nx Integrated Monorepo" %} - -```bash -nx g @nx/angular:ngrx --root --parent=apps/testapp/src/main.ts -``` - -{% /tab %} -{% /tabs %} - -3. Generate NgRx Feature State - -{% tabs %} -{% tab label="Nx Standalone Repo" %} - -```bash -nx g @nx/angular:ngrx users --parent=testapp/src/app/app.routes.ts -``` - -{% /tab %} -{% tab label="Nx Integrated Monorepo" %} - -```bash -nx g @nx/angular:ngrx users --parent=apps/testapp/src/app/app.routes.ts -``` - -{% /tab %} -{% /tabs %} diff --git a/docs/shared/recipes/tag-multiple-dimensions.md b/docs/shared/recipes/tag-multiple-dimensions.md index 006800082a67a..5289309651412 100644 --- a/docs/shared/recipes/tag-multiple-dimensions.md +++ b/docs/shared/recipes/tag-multiple-dimensions.md @@ -139,7 +139,8 @@ Matching just a single source tag is sometimes not enough for solving complex re "allow": [], // update depConstraints based on your tags "depConstraints": [ - { // this constraint applies to all "admin" projects + { + // this constraint applies to all "admin" projects "sourceTag": "scope:admin", "onlyDependOnLibsWithTags": ["scope:shared", "scope:admin"] }, @@ -147,7 +148,9 @@ Matching just a single source tag is sometimes not enough for solving complex re "sourceTag": "type:ui", "onlyDependOnLibsWithTags": ["type:ui", "type:util"] }, - { // we don't want our admin ui components to depend on anything except utilities, and we also want to ban router imports + { + // we don't want our admin ui components to depend on anything except utilities, + // and we also want to ban router imports "allSourceTags": ["scope:admin", "type:ui"], "onlyDependOnLibsWithTags": ["type:util"], "bannedExternalImports": ["*router*"] @@ -158,8 +161,8 @@ Matching just a single source tag is sometimes not enough for solving complex re // ... more ESLint config here } +``` ## Further reading - [Article: Taming Code Organization with Module Boundaries in Nx](https://blog.nrwl.io/mastering-the-project-boundaries-in-nx-f095852f5bf4) -``` diff --git a/docs/shared/recipes/use-executor-configurations.md b/docs/shared/recipes/use-executor-configurations.md deleted file mode 100644 index 4a2a56b27bcb2..0000000000000 --- a/docs/shared/recipes/use-executor-configurations.md +++ /dev/null @@ -1,66 +0,0 @@ -# Use Executor Configurations - -The `configurations` property provides extra sets of values that will be merged into the options map. - -```json {% fileName="project.json" %} -{ - "build": { - "executor": "@nx/js:tsc", - "outputs": ["{workspaceRoot}/dist/libs/mylib"], - "dependsOn": ["^build"], - "options": { - "tsConfig": "libs/mylib/tsconfig.lib.json", - "main": "libs/mylib/src/main.ts" - }, - "configurations": { - "production": { - "tsConfig": "libs/mylib/tsconfig-prod.lib.json" - } - } - } -} -``` - -You can select a configuration like this: `nx build mylib --configuration=production` -or `nx run mylib:build:production`. - -The following code snippet shows how the executor options get constructed: - -```javascript -require(`@nx/jest`).executors['jest']({ - ...options, - ...selectedConfiguration, - ...commandLineArgs, -}); // Pseudocode -``` - -The selected configuration adds/overrides the default options, and the provided command line args add/override the -configuration options. - -## Default Configuration - -When using multiple configurations for a given target, it's helpful to provide a default configuration. -For example, running e2e tests for multiple environments. By default it would make sense to use a `dev` configuration for day to day work, but having the ability to run against an internal staging environment for the QA team. - -```json {% fileName="project.json" %} -{ - "e2e": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/my-app-e2e/cypress.config.ts" - }, - "configurations": { - "dev": { - "devServerTarget": "my-app:serve" - }, - "qa": { - "baseUrl": "https://some-internal-url.example.com" - } - }, - "defaultConfiguration": "dev" - } -} -``` - -When running `nx e2e my-app-e2e`, the _dev_ configuration will be used. In this case using the local dev server for `my-app`. -You can always run the other configurations by explicitly providing the configuration i.e. `nx e2e my-app-e2e --configuration=qa` or `nx run my-app-e2e:e2e:qa` diff --git a/docs/shared/reference/commands.md b/docs/shared/reference/commands.md deleted file mode 100644 index 3d5a0ae438944..0000000000000 --- a/docs/shared/reference/commands.md +++ /dev/null @@ -1,26 +0,0 @@ -# Nx CLI Commands - -- [create-nx-workspace](/packages/nx/documents/create-nx-workspace) -- [init](/packages/nx/documents/init) -- [generate](/packages/nx/documents/generate) -- [run](/packages/nx/documents/run) -- [daemon](/packages/nx/documents/daemon) -- [graph](/packages/nx/documents/dep-graph) -- [run-many](/packages/nx/documents/run-many) -- [affected](/packages/nx/documents/affected) -- [affected:graph](/packages/nx/documents/affected-dep-graph) -- [print-affected](/packages/nx/documents/print-affected) -- [format:check](/packages/nx/documents/format-check) -- [format:write](/packages/nx/documents/format-write) -- [migrate](/packages/nx/documents/migrate) -- [report](/packages/nx/documents/report) -- [list](/packages/nx/documents/list) -- [workspace-lint](/packages/nx/documents/workspace-lint) -- [workspace-generator](/packages/nx/documents/workspace-generator) -- [connect-to-nx-cloud](/packages/nx/documents/connect-to-nx-cloud) -- [reset](/packages/nx/documents/reset) -- [repair](/packages/nx/documents/repair) -- [exec](/packages/nx/documents/exec) -- [watch](/packages/nx/documents/watch) -- [show](/packages/nx/documents/show) -- [view-logs](/packages/nx/documents/view-logs) diff --git a/docs/shared/reference/environment-variables.md b/docs/shared/reference/environment-variables.md index 7321ac424153a..18b0cda6a09d0 100644 --- a/docs/shared/reference/environment-variables.md +++ b/docs/shared/reference/environment-variables.md @@ -2,27 +2,27 @@ The following environment variables are ones that you can set to change the behavior of Nx in different environments. -| Property | Type | Description | -| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| NX_BASE | string | The default base branch to use when calculating the affected projects. Can be overridden on the command line with `--base`. | -| NX_CACHE_DIRECTORY | string | The cache for task outputs is stored in `node_modules/.cache/nx` by default. Set this variable to use a different directory. | -| NX_CACHE_PROJECT_GRAPH | boolean | If set to `false`, disables the project graph cache. Most useful when developing a plugin that modifies the project graph. | -| NX_DAEMON | boolean | If set to `false`, disables the Nx daemon process. Disable the daemon to print `console.log` statements in plugin code you are developing. | -| NX_DEFAULT_PROJECT | string | The default project used for commands which require a project. e.g. `nx build`, `nx g component`, etc. | -| NX_HEAD | string | The default head branch to use when calculating the affected projects. Can be overridden on the command line with `--head`. | -| NX_PERF_LOGGING | boolean | If set to `true`, will print debug information useful for for profiling executors and Nx itself | -| NX_PROFILE | string | Prepend `NX_PROFILE=profile.json` before running targets with Nx to generate a file that be [loaded in Chrome dev tools](/recipes/other/performance-profiling) to visualize the performance of Nx across multiple processes. | -| NX_PROJECT_GRAPH_CACHE_DIRECTORY | string | The project graph cache is stored in `node_modules/.cache/nx` by default. Set this variable to use a different directory. | -| NX_PROJECT_GRAPH_MAX_WORKERS | number | The number of workers to use when calculating the project graph. | -| NX_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Not read if NX_TASKS_RUNNER is set. | -| NX_SKIP_NX_CACHE | boolean | Rerun the tasks even when the results are available in the cache | -| NX_TASKS_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Preferred over NX_RUNNER. | -| NX_TASKS_RUNNER_DYNAMIC_OUTPUT | boolean | If set to `false`, will use non-dynamic terminal output strategy (what you see in CI), even when you terminal can support the dynamic version | -| NX_VERBOSE_LOGGING | boolean | If set to `true`, will print debug information useful for troubleshooting | -| NX_DRY_RUN | boolean | If set to `true`, will perform a dry run of the generator. No files will be created and no packages will be installed. | -| NX_INTERACTIVE | boolean | If set to `true`, will allow Nx to prompt you in the terminal to answer some further questions when running generators. | -| NX_GENERATE_QUIET | boolean | If set to `true`, will prevent Nx logging file operations during generate | -| NX_PREFER_TS_NODE | boolean | If set to `true`, Nx will use ts-node for local execution of plugins even if `@swc-node/register` is installed. | +| Property | Type | Description | +| -------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| NX_BASE | string | The default base branch to use when calculating the affected projects. Can be overridden on the command line with `--base`. | +| NX_CACHE_DIRECTORY | string | The cache for task outputs is stored in `node_modules/.cache/nx` by default. Set this variable to use a different directory. | +| NX_CACHE_PROJECT_GRAPH | boolean | If set to `false`, disables the project graph cache. Most useful when developing a plugin that modifies the project graph. | +| NX_DAEMON | boolean | If set to `false`, disables the Nx daemon process. Disable the daemon to print `console.log` statements in plugin code you are developing. | +| NX_DEFAULT_PROJECT | string | The default project used for commands which require a project. e.g. `nx build`, `nx g component`, etc. | +| NX_HEAD | string | The default head branch to use when calculating the affected projects. Can be overridden on the command line with `--head`. | +| NX_PERF_LOGGING | boolean | If set to `true`, will print debug information useful for for profiling executors and Nx itself | +| NX_PROFILE | string | Prepend `NX_PROFILE=profile.json` before running targets with Nx to generate a file that be [loaded in Chrome dev tools](/recipes/troubleshooting/performance-profiling) to visualize the performance of Nx across multiple processes. | +| NX_PROJECT_GRAPH_CACHE_DIRECTORY | string | The project graph cache is stored in `node_modules/.cache/nx` by default. Set this variable to use a different directory. | +| NX_PROJECT_GRAPH_MAX_WORKERS | number | The number of workers to use when calculating the project graph. | +| NX_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Not read if NX_TASKS_RUNNER is set. | +| NX_SKIP_NX_CACHE | boolean | Rerun the tasks even when the results are available in the cache | +| NX_TASKS_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Preferred over NX_RUNNER. | +| NX_TASKS_RUNNER_DYNAMIC_OUTPUT | boolean | If set to `false`, will use non-dynamic terminal output strategy (what you see in CI), even when you terminal can support the dynamic version | +| NX_VERBOSE_LOGGING | boolean | If set to `true`, will print debug information useful for troubleshooting | +| NX_DRY_RUN | boolean | If set to `true`, will perform a dry run of the generator. No files will be created and no packages will be installed. | +| NX_INTERACTIVE | boolean | If set to `true`, will allow Nx to prompt you in the terminal to answer some further questions when running generators. | +| NX_GENERATE_QUIET | boolean | If set to `true`, will prevent Nx logging file operations during generate | +| NX_PREFER_TS_NODE | boolean | If set to `true`, Nx will use ts-node for local execution of plugins even if `@swc-node/register` is installed. | Nx will set the following environment variables so they can be accessible within the process even outside of executors and generators diff --git a/docs/shared/reference/glossary.md b/docs/shared/reference/glossary.md index 43bdc5a452e20..fa5be788ea5cc 100644 --- a/docs/shared/reference/glossary.md +++ b/docs/shared/reference/glossary.md @@ -8,13 +8,13 @@ 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). -> See: [Applications and Libraries](/more-concepts/applications-and-libraries) +> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries) ### Buildable Library 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](/more-concepts/buildable-and-publishable-libraries) +> See: [Publishable and Buildable Nx Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) ### Cache @@ -32,7 +32,7 @@ When the [cache inputs](#cache-inputs) for a [task](#task) match an existing ent Everything that might change the output of a [task](#task). This may include source code, task options, environment variables and other settings determined at run time. These values are combined as a hash to serve as a key for an entry in the [cache](#cache). -> See: [Customizing Inputs and Named Inputs](/more-concepts/customizing-inputs) +> See: [Customizing Inputs and Named Inputs](/concepts/more-concepts/customizing-inputs) ### Cache Miss @@ -48,21 +48,21 @@ The terminal output and any file artifacts created by running a [task](#task). T ### Command -Anything you run in the terminal. An example commmand that invokes a [task](#task) is `nx build my-app`. +Anything you run in the terminal. An example command that invokes a [task](#task) is `nx build my-app`. > See: [Run Tasks](/core-features/run-tasks) ### Configurations -A set of preconfigured options for a [target](#target) that should be enabled all together. For example, a `production` configuration would set all the options needed for a build that could be deployed to production. +A set of preconfigured options for a [target](#target) that should be enabled altogether. For example, a `production` configuration would set all the options needed for a build that could be deployed to production. -> See: [Use Executor Configurations](/recipes/executors/use-executor-configurations) +> See: [Use Executor Configurations](/core-features/plugin-features/use-task-executors#use-executor-configurations) ### Distributed Cache A [cache](#cache) that can be shared between all developers using the repo and the CI system. -> See: [Share Your Cache](/core-features/share-your-cache) +> See: [Share Your Cache](/core-features/remote-cache) ### Distributed Task Execution @@ -74,13 +74,13 @@ A system for running [tasks](#task) in CI across multiple agent processes in the A script that performs some action on your code. This can include building, linting, testing, serving and many other actions. A [target](#target) configuration specifies an executor and a set of options. Executors can be found in [plugins](#plugin). -> See: [Use Task Executors](/plugin-features/use-task-executors) +> See: [Use Task Executors](/core-features/plugin-features/use-task-executors) ### Generator A script that creates or modifies your code. Generators can be found in [plugins](#plugin). -> See: [Use Code Generators](/plugin-features/use-code-generators) +> See: [Use Code Generators](/core-features/plugin-features/use-code-generators) ### Graph @@ -98,13 +98,13 @@ A repository using Nx [plugins](#plugin) to boost efficiency and ease of mainten A [project](#project) that is used by [applications](#application) or other [libraries](#library). -> See: [Applications and Libraries](/more-concepts/applications-and-libraries) +> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries) ### Monolith A large [application](#application) that is difficult to separate into smaller pieces. -> See: [Applications and Libraries](/more-concepts/applications-and-libraries) +> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries) ### Monorepo @@ -136,7 +136,7 @@ A repository using Nx without [plugins](#plugin) that prioritizes the independen A set of [executors](#executor), [generators](#generator) and other code that extends the functionality of Nx. May be installed from a package manager like NPM or developed directly in the repository. -> See: [Create Your Own Plugin](/plugins/intro/getting-started) +> See: [Create Your Own Plugin](/extending-nx/intro/getting-started) ### Polyrepo @@ -146,13 +146,13 @@ 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). -> See: [Applications and Libraries](/more-concepts/applications-and-libraries) +> See: [Applications and Libraries](/concepts/more-concepts/applications-and-libraries) ### Publishable Library 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](/more-concepts/buildable-and-publishable-libraries) +> See: [Publishable and Buildable Nx Libraries](/concepts/more-concepts/buildable-and-publishable-libraries) ### Root-Level Project diff --git a/docs/shared/reference/nx-json.md b/docs/shared/reference/nx-json.md index befab44d638d8..b3970ab57248a 100644 --- a/docs/shared/reference/nx-json.md +++ b/docs/shared/reference/nx-json.md @@ -116,7 +116,7 @@ In this case Nx will use the right `production` input for each project. {% cards %} {% card title="Project Configuration reference" type="documentation" description="inputs and namedInputs are also described in the project configuration reference" url="/reference/project-configuration#inputs-&-namedinputs" /%} -{% card title="Customizing inputs and namedInputs" type="documentation" description="This guide walks through a few examples of how to customize inputs and namedInputs" url="/more-concepts/customizing-inputs" /%} +{% card title="Customizing inputs and namedInputs" type="documentation" description="This guide walks through a few examples of how to customize inputs and namedInputs" url="/concepts/more-concepts/customizing-inputs" /%} {% /cards %} ### Target Defaults diff --git a/docs/shared/reference/project-configuration.md b/docs/shared/reference/project-configuration.md index a4a80a51931e3..fcf796b68d2cf 100644 --- a/docs/shared/reference/project-configuration.md +++ b/docs/shared/reference/project-configuration.md @@ -1,7 +1,7 @@ # Project Configuration Projects can be configured in `package.json` (if you use npm scripts and not Nx executors) and `project.json` (if you -[use task executors](/plugin-features/use-task-executors)). Both `package.json` and `project.json` files are located in each project's folder. Nx merges the two +[use task executors](/core-features/plugin-features/use-task-executors)). Both `package.json` and `project.json` files are located in each project's folder. Nx merges the two files to get each project's configuration. The following configuration creates `build` and `test` targets for Nx. @@ -123,7 +123,7 @@ You can add Nx-specific configuration as follows: The `inputs` array tells Nx what to consider to determine whether a particular invocation of a script should be a cache hit or not. There are three types of inputs: -_Filesets_ +#### Filesets Examples: @@ -142,7 +142,7 @@ The `inputs` and `namedInputs` are parsed with the following rules: {% /callout %} -_Runtime Inputs_ +#### Runtime Inputs Examples: @@ -150,7 +150,7 @@ Examples: Note the result value is hashed, so it is never displayed. -_Env Variables_ +#### Env Variables Examples: @@ -158,7 +158,7 @@ Examples: Note the result value is hashed, so it is never displayed. -_External Dependencies_ +#### External Dependencies For official plugins, Nx intelligently finds a set of external dependencies which it hashes for the target. `nx:run-commands` is an exception to this. Because you may specify any command to be run, it is not possible to determine which, if any, external dependencies are used by the target. @@ -204,7 +204,7 @@ If a target uses a command from an npm package, that package should be listed. } ``` -_Dependent tasks output_ +#### Dependent tasks output This input allows us to depend on the output, rather than the input of the dependent tasks. We can specify the glob pattern to match only the subset of the output files. The `transitive` parameter defines whether the check and the pattern should be recursively applied to the dependent tasks of the child tasks. @@ -227,7 +227,7 @@ Examples: } ``` -_Named Inputs_ +#### Named Inputs Examples: @@ -263,10 +263,10 @@ sources (non-test sources) of its dependencies. In other words, it treats test s {% cards %} {% card title="nx.json reference" type="documentation" description="inputs and namedInputs are also described in the nx.json reference" url="/reference/nx-json#inputs-&-namedinputs" /%} -{% card title="Customizing inputs and namedInputs" type="documentation" description="This guide walks through a few examples of how to customize inputs and namedInputs" url="/more-concepts/customizing-inputs" /%} +{% card title="Customizing inputs and namedInputs" type="documentation" description="This guide walks through a few examples of how to customize inputs and namedInputs" url="/concepts/more-concepts/customizing-inputs" /%} {% /cards %} -### outputs +### Outputs Targets may define outputs to tell Nx where the target is going to create file artifacts that Nx should cache. `"outputs": ["{workspaceRoot}/dist/libs/mylib"]` tells Nx where the `build` target is going to create file artifacts. @@ -313,13 +313,13 @@ Sometimes, multiple targets might write to the same directory. When possible it } ``` -But if the above is not possible, globs (parsed with the [minimatch](https://github.com/isaacs/minimatch) library) can be specified as outputs to only cache a set of files rather than the whole directory. +But if the above is not possible, globs (parsed by the [GlobSet](https://docs.rs/globset/0.4.5/globset/#syntax) Rust library) can be specified as outputs to only cache a set of files rather than the whole directory. ```json { "targets": { "build-js": { - "outputs": ["{workspaceRoot}/dist/libs/mylib/**/*.js"] + "outputs": ["{workspaceRoot}/dist/libs/mylib/**/*.{js,map}"] }, "build-css": { "outputs": ["{workspaceRoot}/dist/libs/mylib/**/*.css"] @@ -328,6 +328,21 @@ But if the above is not possible, globs (parsed with the [minimatch](https://git } ``` +More advanced patterns can be used to exclude files and folders in a single line + +```json +{ + "targets": { + "build-js": { + "outputs": ["{workspaceRoot}/dist/libs/!(cache|.next)/**/*.{js,map}"] + }, + "build-css": { + "outputs": ["{workspaceRoot}/dist/libs/mylib/**/!(secondary).css"] + } + } +} +``` + ### dependsOn Targets can depend on other targets. This is the relevant portion of the configuration file: @@ -621,7 +636,7 @@ You can annotate your projects with `tags` as follows: {% /tab %} {% /tabs %} -You can [configure lint rules using these tags](/core-features/enforce-project-boundaries) to, for instance, ensure that libraries +You can [configure lint rules using these tags](/core-features/enforce-module-boundaries) to, for instance, ensure that libraries belonging to `myteam` are not depended on by libraries belong to `theirteam`. ### implicitDependencies diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 00974a9797dec..7d8cb73e7d885 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -51,15 +51,15 @@ - [Core Features](/core-features) - [Run Tasks](/core-features/run-tasks) - [Cache Task Results](/core-features/cache-task-results) - - [Share Your Cache](/core-features/share-your-cache) - - [Explore the Graph](/core-features/explore-graph) + - [Use Remote Caching](/core-features/remote-cache) - [Distribute Task Execution](/core-features/distribute-task-execution) - - [Integrate with Editors](/core-features/integrate-with-editors) + - [Explore the Graph](/core-features/explore-graph) - [Automate Updating Dependencies](/core-features/automate-updating-dependencies) - - [Enforce Project Boundaries](/core-features/enforce-project-boundaries) - - [Plugin Features](/plugin-features) - - [Use Task Executors](/plugin-features/use-task-executors) - - [Use Code Generators](/plugin-features/use-code-generators) + - [Enforce Module Boundaries](/core-features/enforce-module-boundaries) + - [Integrate with Editors](/core-features/integrate-with-editors) + - [Plugin Features](/core-features/plugin-features) + - [Use Task Executors](/core-features/plugin-features/use-task-executors) + - [Use Code Generators](/core-features/plugin-features/use-code-generators) - [Concepts](/concepts) - [Integrated Repos vs. Package-Based Repos vs. Standalone Apps](/concepts/integrated-vs-package-based) - [Mental Model](/concepts/mental-model) @@ -67,35 +67,129 @@ - [Improve Worst Case CI Times](/concepts/dte) - [Task Pipeline Configuration](/concepts/task-pipeline-configuration) - [Affected](/concepts/affected) - - [More Concept Guides »](/more-concepts) - - [More Concepts](/more-concepts) - - [Customizing Inputs](/more-concepts/customizing-inputs) - - [Incremental Builds](/more-concepts/incremental-builds) - - [Illustrated Distributed Task Execution](/more-concepts/illustrated-dte) - - [Nx and Turborepo](/more-concepts/turbo-and-nx) - - [Monorepos](/more-concepts/why-monorepos) - - [Dependency Management](/more-concepts/dependency-management) - - [Code Sharing](/more-concepts/code-sharing) - - [Using Nx at Enterprises](/more-concepts/monorepo-nx-enterprise) - - [Nx Daemon](/more-concepts/nx-daemon) - - [Nx and the Angular CLI](/more-concepts/nx-and-angular) - - [Folder Structure](/more-concepts/folder-structure) - - [Nx Devkit and Angular Devkit](/more-concepts/nx-devkit-angular-devkit) - - [Micro Frontend Architecture](/more-concepts/micro-frontend-architecture) - - [Applications and Libraries](/more-concepts/applications-and-libraries) - - [Creating Libraries](/more-concepts/creating-libraries) - - [Library Types](/more-concepts/library-types) - - [Grouping Libraries](/more-concepts/grouping-libraries) - - [Buildable and Publishable Libraries](/more-concepts/buildable-and-publishable-libraries) - - [How the Project Graph is Built](/more-concepts/how-project-graph-is-built) - - [Nx and the Nx Wrapper](/more-concepts/nx-and-the-wrapper) - - [Managing your Global Nx Installation](/more-concepts/global-nx) - - [All Recipes »](/recipes) - - [CI Setup](/recipes/ci/ci-setup) + - [More Concepts](/concepts/more-concepts) + - [Customizing Inputs](/concepts/more-concepts/customizing-inputs) + - [Incremental Builds](/concepts/more-concepts/incremental-builds) + - [Illustrated Distributed Task Execution](/concepts/more-concepts/illustrated-dte) + - [Nx and Turborepo](/concepts/more-concepts/turbo-and-nx) + - [Monorepos](/concepts/more-concepts/why-monorepos) + - [Dependency Management](/concepts/more-concepts/dependency-management) + - [Code Sharing](/concepts/more-concepts/code-sharing) + - [Using Nx at Enterprises](/concepts/more-concepts/monorepo-nx-enterprise) + - [Nx Daemon](/concepts/more-concepts/nx-daemon) + - [Nx and the Angular CLI](/concepts/more-concepts/nx-and-angular) + - [Folder Structure](/concepts/more-concepts/folder-structure) + - [Nx Devkit and Angular Devkit](/concepts/more-concepts/nx-devkit-angular-devkit) + - [Micro Frontend Architecture](/concepts/more-concepts/micro-frontend-architecture) + - [Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) + - [Applications and Libraries](/concepts/more-concepts/applications-and-libraries) + - [Creating Libraries](/concepts/more-concepts/creating-libraries) + - [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) + - [How the Project Graph is Built](/concepts/more-concepts/how-project-graph-is-built) + - [Nx and the Nx Wrapper](/concepts/more-concepts/nx-and-the-wrapper) + - [Managing your Global Nx Installation](/concepts/more-concepts/global-nx) + - [Recipes](/recipes) - [Adopting Nx](/recipes/adopting-nx) + - [NPM/Yarn/PNPM workspaces](/recipes/adopting-nx/adding-to-monorepo) + - [Add to any Project](/recipes/adopting-nx/adding-to-existing-project) + - [Nx and Lerna](/recipes/adopting-nx/lerna-and-nx) + - [Preserving Git Histories](/recipes/adopting-nx/preserving-git-histories) + - [Manual migration](/recipes/adopting-nx/manual) + - [React](/recipes/react) + - [Migrating from CRA](/recipes/react/migration-cra) + - [React 18 Migration](/recipes/react/react-18) + - [React Native with Nx](/recipes/react/react-native) + - [Remix with Nx](/recipes/react/remix) + - [Use Environment Variables in React](/recipes/react/use-environment-variables-in-react) + - [Using Tailwind CSS in React](/recipes/react/using-tailwind-css-in-react) + - [Adding Images, Fonts, and Files](/recipes/react/adding-assets-react) + - [Setup Module Federation with SSR for React](/recipes/react/module-federation-with-ssr) + - [Deploying Next.js applications to Vercel](/recipes/react/deploy-nextjs-to-vercel) + - [Angular](/recipes/angular) + - [Migration](/recipes/angular/migration) + - [Migrating from Angular CLI](/recipes/angular/migration/angular) + - [Migrating From Multiple Angular CLI Repos](/recipes/angular/migration/angular-multiple) + - [Migrating Angular Application manually](/recipes/angular/migration/angular-manual) + - [Migrating from AngularJS](/recipes/angular/migration/angularjs) + - [Use Environment Variables in Angular](/recipes/angular/use-environment-variables-in-angular) + - [Using Tailwind CSS with Angular projects](/recipes/angular/using-tailwind-css-with-angular-projects) + - [Setup Module Federation with SSR for Angular](/recipes/angular/module-federation-with-ssr) + - [Advanced Micro Frontends with Angular using Dynamic Federation](/recipes/angular/dynamic-module-federation-with-angular) + - [Setup incremental builds for Angular applications](/recipes/angular/setup-incremental-builds-angular) + - [Node](/recipes/node) + - [Deploying a Node App to Fly.io](/recipes/node/node-server-fly-io) + - [Add and Deploy Netlify Edge Functions with Node](/recipes/node/node-serverless-functions-netlify) + - [Deploying AWS lambda in Node.js](/recipes/node/node-aws-lambda) + - [Storybook](/recipes/storybook) + - [One main Storybook instance for all projects](/recipes/storybook/one-storybook-for-all) + - [One Storybook instance per scope](/recipes/storybook/one-storybook-per-scope) + - [One main Storybook instance using Storybook Composition](/recipes/storybook/one-storybook-with-composition) + - [Enforce Module Boundaries](/recipes/enforce-module-boundaries) + - [Ban Dependencies with Certain Tags](/recipes/enforce-module-boundaries/ban-dependencies-with-tags) + - [Tag in Multiple Dimensions](/recipes/enforce-module-boundaries/tag-multiple-dimensions) + - [Ban External Imports](/recipes/enforce-module-boundaries/ban-external-imports) + - [Tags Allow List](/recipes/enforce-module-boundaries/tags-allow-list) + - [CI](/recipes/ci) + - [CI Setup](/recipes/ci/ci-setup) + - [Prepare applications for deployment via CI](/recipes/ci/ci-deployment) + - [Setting up Azure Pipelines](/recipes/ci/monorepo-ci-azure) + - [Setting up CircleCI](/recipes/ci/monorepo-ci-circle-ci) + - [Setting up GitHub Actions](/recipes/ci/monorepo-ci-github-actions) + - [Setting up Jenkins](/recipes/ci/monorepo-ci-jenkins) + - [Setting up GitLab](/recipes/ci/monorepo-ci-gitlab) + - [Setting up Bitbucket](/recipes/ci/monorepo-ci-bitbucket-pipelines) + - [Tips and tricks](/recipes/tips-n-tricks) + - [Add a Package-based Project in an Integrated Repo](/recipes/tips-n-tricks/package-based-in-integrated) + - [Add an Integrated Project in a Package-based Repo](/recipes/tips-n-tricks/integrated-in-package-based) + - [Configuring ESLint with Typescript](/recipes/tips-n-tricks/eslint) + - [Define Environment Variables](/recipes/tips-n-tricks/define-environment-variables) + - [Configuring Browser Support](/recipes/tips-n-tricks/browser-support) + - [Include Assets in Build](/recipes/tips-n-tricks/include-assets-in-build) + - [Include All package.json Files as Projects](/recipes/tips-n-tricks/include-all-packagejson) + - [Identify Dependencies Between Folders](/recipes/tips-n-tricks/identify-dependencies-between-folders) + - [Run Root-Level NPM Scripts with Nx](/recipes/tips-n-tricks/root-level-scripts) + - [Disable Graph Links Created from Analyzing Source Files](/recipes/tips-n-tricks/analyze-source-files) + - [Workspace Watching](/recipes/tips-n-tricks/workspace-watching) + - [Convert from a Standalone Repository to an Integrated Repository](/recipes/tips-n-tricks/standalone-to-integrated) + - [Use JavaScript instead TypeScript](/recipes/tips-n-tricks/js-and-ts) + - [Altering Migration Process](/recipes/tips-n-tricks/advanced-update) + - [Running Custom Commands](/recipes/tips-n-tricks/run-commands-executor) + - [Troubleshooting](/recipes/troubleshooting) + - [Resolve Circular Dependencies](/recipes/troubleshooting/resolve-circular-dependencies) + - [Troubleshooting Nx Install Issues](/recipes/troubleshooting/troubleshoot-nx-install-issues) + - [Troubleshoot Cache Misses](/recipes/troubleshooting/troubleshoot-cache-misses) + - [Unknown Local Cache Error](/recipes/troubleshooting/unknown-local-cache) + - [Profiling Build Performance](/recipes/troubleshooting/performance-profiling) + - [Nx Console](/recipes/nx-console) + - [Telemetry](/recipes/nx-console/console-telemetry) + - [Generate Command](/recipes/nx-console/console-generate-command) + - [Run Command](/recipes/nx-console/console-run-command) + - [Add Dependency Command](/recipes/nx-console/console-add-dependency-command) + - [Project Pane](/recipes/nx-console/console-project-pane) + - [Keyboard Shortcuts](/recipes/nx-console/console-shortcuts) + - [Other](/recipes/other) + - [Serverless deployment with Deno Deploy](/recipes/other/deno-deploy) + - [Add and Deploy Netlify Edge Functions with Deno](/recipes/other/deno-netlify-functions) + - [Rescope Packages from @nrwl to @nx](/recipes/other/rescope) + - [Showcase](/showcase) + - [Example Repos](/showcase/example-repos) + - [Add a Lit Project](/showcase/example-repos/add-lit) + - [Add a Solid Project](/showcase/example-repos/add-solid) + - [Add a Qwik Project](/showcase/example-repos/add-qwik) + - [Powering Up React Development With Nx](/showcase/example-repos/react-nx) + - [Using Apollo GraphQL](/showcase/example-repos/apollo-react) + - [Using Prisma with NestJS](/showcase/example-repos/nestjs-prisma) + - [Using Mongo with Fastify](/showcase/example-repos/mongo-fastify) + - [Using Redis with Fastify](/showcase/example-repos/redis-fastify) + - [Using Postgres with Fastify](/showcase/example-repos/postgres-fastify) + - [Using PlanetScale with Serverless Fastify](/showcase/example-repos/serverless-fastify-planetscale) + - [Large Repo and Caching](/showcase/example-repos/caching) + - [Large Repo and DTE](/showcase/example-repos/dte) + - [Nx Micro-Frontend Example](/showcase/example-repos/mfe) - [Reference](/reference) - - [Commands](/reference/commands) - - [nx.json](/reference/nx-json) + - [Nx Configuration](/reference/nx-json) - [Project Configuration](/reference/project-configuration) - [.nxignore](/reference/nxignore) - [Environment Variables](/reference/environment-variables) @@ -118,128 +212,26 @@ - [See Also](/see-also) - [Site Map](/see-also/sitemap) -- Recipes - - - [Getting Started](/recipes/getting-started) - - [Set up a new workspace](/recipes/getting-started/set-up-a-new-workspace) - - [Nx Console](/recipes/nx-console) - - [Nx Console Telemetry](/recipes/nx-console/console-telemetry) - - [Nx Console Generate Command](/recipes/nx-console/console-generate-command) - - [Nx Console Run Command](/recipes/nx-console/console-run-command) - - [Nx Console Add Dependency Command](/recipes/nx-console/console-add-dependency-command) - - [Nx Console Project Pane](/recipes/nx-console/console-project-pane) - - [Nx Console Keyboard Shortcuts](/recipes/nx-console/console-shortcuts) - - [CI](/recipes/ci) - - [CI Setup](/recipes/ci/ci-setup) - - [Prepare applications for deployment via CI](/recipes/ci/ci-deployment) - - [Setting up Azure Pipelines](/recipes/ci/monorepo-ci-azure) - - [Setting up CircleCI](/recipes/ci/monorepo-ci-circle-ci) - - [Setting up GitHub Actions](/recipes/ci/monorepo-ci-github-actions) - - [Setting up Jenkins](/recipes/ci/monorepo-ci-jenkins) - - [Setting up GitLab](/recipes/ci/monorepo-ci-gitlab) - - [Setting up Bitbucket](/recipes/ci/monorepo-ci-bitbucket-pipelines) - - [Troubleshooting Nx Install Issues](/recipes/ci/troubleshoot-nx-install-issues) - - [Adopting Nx](/recipes/adopting-nx) - - [NPM/Yarn/PNPM workspaces](/recipes/adopting-nx/adding-to-monorepo) - - [Add to any Project](/recipes/adopting-nx/adding-to-existing-project) - - [From CRA](/recipes/adopting-nx/migration-cra) - - [From Angular CLI](/recipes/adopting-nx/migration-angular) - - [Nx and Lerna](/recipes/adopting-nx/lerna-and-nx) - - [From AngularJS](/recipes/adopting-nx/migration-angularjs) - - [Preserving Git Histories](/recipes/adopting-nx/preserving-git-histories) - - [Manual migration](/recipes/adopting-nx/manual) - - [Adopting Nx From Angular CLI](/recipes/adopting-nx-angular) - - [From Angular CLI](/recipes/adopting-nx-angular/migration-angular) - - [From Angular CLI to Integrated](/recipes/adopting-nx-angular/angular-integrated) - - [From Angular CLI Manually](/recipes/adopting-nx-angular/angular-manual) - - [From Multiple Angular CLI Repos](/recipes/adopting-nx-angular/angular-multiple) - - [Executors](/recipes/executors) - - [Use Executor Configurations](/recipes/executors/use-executor-configurations) - - [Running Custom Commands](/recipes/executors/run-commands-executor) - - [Environment Variables](/recipes/environment-variables) - - [Define Environment Variables](/recipes/environment-variables/define-environment-variables) - - [Use Environment Variables in React](/recipes/environment-variables/use-environment-variables-in-react) - - [Use Environment Variables in Angular](/recipes/environment-variables/use-environment-variables-in-angular) - - [Module Federation and Micro Frontends](/recipes/module-federation) - - [Faster Builds with Module Federation](/recipes/module-federation/faster-builds) - - [Setup Module Federation with SSR for Angular and React](/recipes/module-federation/module-federation-with-ssr) - - [Advanced Micro Frontends with Angular using Dynamic Federation](/recipes/module-federation/dynamic-module-federation-with-angular) - - [Nx Micro-Frontend Example](/recipes/module-federation/nx-examples) - - [Storybook](/recipes/storybook) - - [Publishing Storybook: One main Storybook instance for all projects](/recipes/storybook/one-storybook-for-all) - - [Publishing Storybook: One Storybook instance per scope](/recipes/storybook/one-storybook-per-scope) - - [Publishing Storybook: One main Storybook instance using Storybook Composition](/recipes/storybook/one-storybook-with-composition) - - [Deployment](/recipes/deployment) - - [Deploying a Node App to Fly.io](/recipes/deployment/node-server-fly-io) - - [Add and Deploy Netlify Edge Functions with Node](/recipes/deployment/node-serverless-functions-netlify) - - [Deploying AWS lambda in Node.js](/recipes/deployment/node-aws-lambda) - - [Serverless deployment with Deno Deploy](/recipes/deployment/deno-deploy) - - [Add and Deploy Netlify Edge Functions with Deno](/recipes/deployment/deno-netlify-functions) - - [Deploying Next.js applications to Vercel](/recipes/deployment/deploy-nextjs-to-vercel) - - [Database](/recipes/database) - - [Using Prisma with NestJS](/recipes/database/nestjs-prisma) - - [Using Mongo with Fastify](/recipes/database/mongo-fastify) - - [Using Redis with Fastify](/recipes/database/redis-fastify) - - [Using Postgres with Fastify](/recipes/database/postgres-fastify) - - [Using PlanetScale with Serverless Fastify](/recipes/database/serverless-fastify-planetscale) - - [Enforce Module Boundaries](/recipes/enforce-module-boundaries) - - [Ban Dependencies with Certain Tags](/recipes/enforce-module-boundaries/ban-dependencies-with-tags) - - [Tag in Multiple Dimensions](/recipes/enforce-module-boundaries/tag-multiple-dimensions) - - [Ban External Imports](/recipes/enforce-module-boundaries/ban-external-imports) - - [Tags Allow List](/recipes/enforce-module-boundaries/tags-allow-list) - - [Example Repos](/recipes/example-repos) - - [Powering Up React Development With Nx](/recipes/example-repos/react-nx) - - [Using Apollo GraphQL](/recipes/example-repos/apollo-react) - - [Large Repo and Caching](/recipes/example-repos/caching) - - [Large Repo and DTE](/recipes/example-repos/dte) - - [Other](/recipes/other) - - [Run Root-Level NPM Scripts with Nx](/recipes/other/root-level-scripts) - - [Disable Graph Links Created from Analyzing Source Files](/recipes/other/analyze-source-files) - - [Workspace Watching](/recipes/other/workspace-watching) - - [Advanced Update Process](/recipes/other/advanced-update) - - [JavaScript and TypeScript](/recipes/other/js-and-ts) - - [React Native with Nx](/recipes/other/react-native) - - [Remix with Nx](/recipes/other/remix) - - [Adding Images, Fonts, and Files](/recipes/other/adding-assets-react) - - [Setup incremental builds for Angular applications](/recipes/other/setup-incremental-builds-angular) - - [Profiling Build Performance](/recipes/other/performance-profiling) - - [Using ESLint in Nx Workspaces](/recipes/other/eslint) - - [Configuring Browser Support](/recipes/other/browser-support) - - [Using Tailwind CSS in React](/recipes/other/using-tailwind-css-in-react) - - [React 18 Migration](/recipes/other/react-18) - - [Using Tailwind CSS with Angular projects](/recipes/other/using-tailwind-css-with-angular-projects) - - [Using NgRx](/recipes/other/misc-ngrx) - - [Using Data Persistence operators](/recipes/other/misc-data-persistence) - - [Find the Last Successful Commit in Azure Pipelines](/recipes/other/azure-last-successful-commit) - - [Troubleshoot Cache Misses](/recipes/other/troubleshoot-cache-misses) - - [Export Project Graph](/recipes/other/export-project-graph) - - [Resolve Circular Dependencies](/recipes/other/resolve-circular-dependencies) - - [Include All package.json Files as Projects](/recipes/other/include-all-packagejson) - - [Include Assets in Build](/recipes/other/include-assets-in-build) - - [Identify Dependencies Between Folders](/recipes/other/identify-dependencies-between-folders) - - [Rescope Packages from @nrwl to @nx](/recipes/other/rescope) - - [Standalone NgRx APIs](/recipes/other/standalone-ngrx-apis) - -- Plugins +- Extending-nx - - [Intro](/plugins/intro) - - [Getting Started with Plugins](/plugins/intro/getting-started) - - [Plugin Registry](/plugins/registry) - - [5 Min Tutorials](/plugins/tutorials) - - [Create a Local Plugin](/plugins/tutorials/create-plugin) - - [Maintain a Published Plugin](/plugins/tutorials/publish-plugin) - - [Recipes](/plugins/recipes) - - [Write a Simple Executor](/plugins/recipes/local-executors) - - [Compose Executors](/plugins/recipes/compose-executors) - - [Write a Simple Generator](/plugins/recipes/local-generators) - - [Compose Generators](/plugins/recipes/composing-generators) - - [Provide Options for Generators](/plugins/recipes/generator-options) - - [Create Files](/plugins/recipes/creating-files) - - [Modify Files](/plugins/recipes/modifying-files) - - [Write a Migration](/plugins/recipes/migration-generators) - - [Create a Preset](/plugins/recipes/create-preset) - - [Modify the Project Graph](/plugins/recipes/project-graph-plugins) - - [Identify Custom Projects](/plugins/recipes/project-inference-plugins) + - [Intro](/extending-nx/intro) + - [Getting Started with Plugins](/extending-nx/intro/getting-started) + - [Plugin Registry](/extending-nx/registry) + - [5 Min Tutorials](/extending-nx/tutorials) + - [Create a Local Plugin](/extending-nx/tutorials/create-plugin) + - [Maintain a Published Plugin](/extending-nx/tutorials/publish-plugin) + - [Recipes](/extending-nx/recipes) + - [Write a Simple Executor](/extending-nx/recipes/local-executors) + - [Compose Executors](/extending-nx/recipes/compose-executors) + - [Write a Simple Generator](/extending-nx/recipes/local-generators) + - [Compose Generators](/extending-nx/recipes/composing-generators) + - [Provide Options for Generators](/extending-nx/recipes/generator-options) + - [Create Files](/extending-nx/recipes/creating-files) + - [Modify Files](/extending-nx/recipes/modifying-files) + - [Write a Migration](/extending-nx/recipes/migration-generators) + - [Create a Preset](/extending-nx/recipes/create-preset) + - [Modify the Project Graph](/extending-nx/recipes/project-graph-plugins) + - [Identify Custom Projects](/extending-nx/recipes/project-inference-plugins) - Cloud @@ -256,16 +248,15 @@ - [Access Tokens](/nx-cloud/account/access-tokens) - [Security Scenarios](/nx-cloud/account/scenarios) - [End to End Encryption](/nx-cloud/account/encryption) - - [On Prem](/nx-cloud/private-cloud) + - [Enterprise + On Prem](/nx-cloud/private-cloud) - [Get Started](/nx-cloud/private-cloud/get-started) - [Authenticate with a Single Admin](/nx-cloud/private-cloud/auth-single-admin) - [Authenticate with GitHub](/nx-cloud/private-cloud/auth-github) + - [On-Prem VM Setup](/nx-cloud/private-cloud/ami-setup) - [Authenticate with GitLab](/nx-cloud/private-cloud/auth-gitlab) - [Authenticate with BitBucket](/nx-cloud/private-cloud/auth-bitbucket) - [Authenticate via SAML](/nx-cloud/private-cloud/auth-saml) - [Advanced Configuration](/nx-cloud/private-cloud/advanced-config) - - [Kubernetes Setup](/nx-cloud/private-cloud/kubernetes-setup) - - [Standalone](/nx-cloud/private-cloud/standalone) - [Reference](/nx-cloud/reference) - [Configuration Options](/nx-cloud/reference/config) - [nx-cloud CLI](/nx-cloud/reference/nx-cloud-cli) @@ -282,6 +273,7 @@ - [delegate-build](/packages/angular/executors/delegate-build) - [ng-packagr-lite](/packages/angular/executors/ng-packagr-lite) - [package](/packages/angular/executors/package) + - [browser-esbuild](/packages/angular/executors/browser-esbuild) - [webpack-browser](/packages/angular/executors/webpack-browser) - [webpack-dev-server](/packages/angular/executors/webpack-dev-server) - [webpack-server](/packages/angular/executors/webpack-server) @@ -331,8 +323,8 @@ - [generators](/packages/cypress/generators) - [init](/packages/cypress/generators/init) - [cypress-project](/packages/cypress/generators/cypress-project) - - [cypress-e2e-configuration](/packages/cypress/generators/cypress-e2e-configuration) - - [cypress-component-configuration](/packages/cypress/generators/cypress-component-configuration) + - [configuration](/packages/cypress/generators/configuration) + - [component-configuration](/packages/cypress/generators/component-configuration) - [migrate-to-cypress-11](/packages/cypress/generators/migrate-to-cypress-11) - [detox](/packages/detox) - [documents](/packages/detox/documents) @@ -354,11 +346,12 @@ - [esbuild](/packages/esbuild/executors/esbuild) - [generators](/packages/esbuild/generators) - [init](/packages/esbuild/generators/init) - - [esbuild-project](/packages/esbuild/generators/esbuild-project) + - [configuration](/packages/esbuild/generators/configuration) - [eslint-plugin](/packages/eslint-plugin) - [documents](/packages/eslint-plugin/documents) - [Overview](/packages/eslint-plugin/documents/overview) - [The `enforce-module-boundaries` rule](/packages/eslint-plugin/documents/enforce-module-boundaries) + - [The `dependency-checks` rule](/packages/eslint-plugin/documents/dependency-checks) - [expo](/packages/expo) - [documents](/packages/expo/documents) - [Overview](/packages/expo/documents/overview) @@ -393,7 +386,7 @@ - [jest](/packages/jest/executors/jest) - [generators](/packages/jest/generators) - [init](/packages/jest/generators/init) - - [jest-project](/packages/jest/generators/jest-project) + - [configuration](/packages/jest/generators/configuration) - [js](/packages/js) - [documents](/packages/js/documents) - [Overview](/packages/js/documents/overview) @@ -493,6 +486,14 @@ - [noop](/packages/nx/executors/noop) - [run-commands](/packages/nx/executors/run-commands) - [run-script](/packages/nx/executors/run-script) + - [playwright](/packages/playwright) + - [documents](/packages/playwright/documents) + - [Overview](/packages/playwright/documents/overview) + - [executors](/packages/playwright/executors) + - [playwright](/packages/playwright/executors/playwright) + - [generators](/packages/playwright/generators) + - [configuration](/packages/playwright/generators/configuration) + - [init](/packages/playwright/generators/init) - [plugin](/packages/plugin) - [documents](/packages/plugin/documents) - [Overview](/packages/plugin/documents/overview) @@ -558,7 +559,7 @@ - [rollup](/packages/rollup/executors/rollup) - [generators](/packages/rollup/generators) - [init](/packages/rollup/generators/init) - - [rollup-project](/packages/rollup/generators/rollup-project) + - [configuration](/packages/rollup/generators/configuration) - [storybook](/packages/storybook) - [documents](/packages/storybook/documents) - [Nx Storybook Plugin Overview](/packages/storybook/documents/overview) @@ -568,6 +569,7 @@ - [Storybook 7 overview](/packages/storybook/documents/storybook-7-setup) - [Configuring Storybook on Nx](/packages/storybook/documents/configuring-storybook) - [How to configure Webpack and Vite for Storybook](/packages/storybook/documents/custom-builder-configs) + - [Setting up Storybook Interaction Tests with Nx](/packages/storybook/documents/storybook-interaction-tests) - [Setting up Storybook Composition with Nx](/packages/storybook/documents/storybook-composition-setup) - [Angular: Set up Compodoc for Storybook on Nx](/packages/storybook/documents/angular-storybook-compodoc) - [Angular: Configuring styles and preprocessor options](/packages/storybook/documents/angular-configuring-styles) @@ -613,7 +615,7 @@ - [ssr-dev-server](/packages/webpack/executors/ssr-dev-server) - [generators](/packages/webpack/generators) - [init](/packages/webpack/generators/init) - - [webpack-project](/packages/webpack/generators/webpack-project) + - [configuration](/packages/webpack/generators/configuration) - [workspace](/packages/workspace) - [documents](/packages/workspace/documents) - [Overview](/packages/workspace/documents/overview) @@ -624,6 +626,7 @@ - [preset](/packages/workspace/generators/preset) - [move](/packages/workspace/generators/move) - [remove](/packages/workspace/generators/remove) + - [convert-to-monorepo](/packages/workspace/generators/convert-to-monorepo) - [new](/packages/workspace/generators/new) - [workspace-generator](/packages/workspace/generators/workspace-generator) - [run-commands](/packages/workspace/generators/run-commands) diff --git a/docs/shared/workspace/applications-and-libraries.md b/docs/shared/workspace/applications-and-libraries.md index 3023073331404..a1cbd48390814 100644 --- a/docs/shared/workspace/applications-and-libraries.md +++ b/docs/shared/workspace/applications-and-libraries.md @@ -28,8 +28,8 @@ As such, if we follow a _80/20 approach_: Note, these libraries don’t 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](/more-concepts/buildable-and-publishable-libraries#buildable-libraries)"_ for enabling incremental builds as -well as _"[publishable libraries](/more-concepts/buildable-and-publishable-libraries#publishable-libraries)"_ for those scenarios where not only you want to +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). @@ -45,6 +45,6 @@ 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](/more-concepts/creating-libraries) -- [Learn more about the different types of libraries we think you should follow](/more-concepts/library-types) -- [Learn more about how to group libraries between each other](/more-concepts/grouping-libraries) +- [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) diff --git a/docs/shared/workspace/buildable-and-publishable-libraries.md b/docs/shared/workspace/buildable-and-publishable-libraries.md index 1de51c427035b..efc87fea5ba14 100644 --- a/docs/shared/workspace/buildable-and-publishable-libraries.md +++ b/docs/shared/workspace/buildable-and-publishable-libraries.md @@ -29,7 +29,7 @@ For more details on the mechanics, remember that Nx is an open source project, s Buildable libraries are similar to "publishable libraries" described above. Their scope however is not to distribute or publish them to some external registry. Thus they might not be optimized for bundling and distribution. -Buildable libraries are mostly used for producing some pre-compiled output that can be directly referenced from an Nx workspace application without the need to again compile it. A typical scenario is to leverage Nx’s [incremental building](/more-concepts/incremental-builds) capabilities. +Buildable libraries are mostly used for producing some pre-compiled output that can be directly referenced from an Nx workspace application without the need to again compile it. A typical scenario is to leverage Nx’s [incremental building](/concepts/more-concepts/incremental-builds) capabilities. {% callout type="warning" title="More details" %} In order for a buildable library to be pre-compiled, it can only depend on other buildable libraries. This allows you to take full advantage of incremental builds. diff --git a/docs/shared/workspace/creating-libraries.md b/docs/shared/workspace/creating-libraries.md index 60d63d4f70b17..531feb25e0f14 100644 --- a/docs/shared/workspace/creating-libraries.md +++ b/docs/shared/workspace/creating-libraries.md @@ -16,7 +16,7 @@ The `nx graph` command generates a graph of how apps and libraries depend on eac ### 3. Enforcing Constraints -You can enforce constraints on how different types of libraries depend on each other [using tags](/core-features/enforce-project-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. +You can enforce constraints on how different types of libraries depend on each other [using tags](/core-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. diff --git a/e2e/angular-core/project.json b/e2e/angular-core/project.json index 5a6db503760a9..cf952873663a9 100644 --- a/e2e/angular-core/project.json +++ b/e2e/angular-core/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/angular-core", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["angular"] } diff --git a/e2e/angular-core/src/projects.test.ts b/e2e/angular-core/src/projects.test.ts index 6470236c604c3..3a42a5dc736ab 100644 --- a/e2e/angular-core/src/projects.test.ts +++ b/e2e/angular-core/src/projects.test.ts @@ -106,11 +106,21 @@ describe('Angular Projects', () => { const appPort = 4207; const process = await runCommandUntil( `serve ${app1} -- --port=${appPort}`, - (output) => output.includes(`listening on localhost:4207`) + (output) => output.includes(`listening on localhost:${appPort}`) ); // port and process cleanup await killProcessAndPorts(process.pid, appPort); + + const esbProcess = await runCommandUntil( + `serve my-dir-${esbuildApp} -- --port=${appPort}`, + (output) => + output.includes(`Application bundle generation complete`) && + output.includes(`localhost:${appPort}`) + ); + + // port and process cleanup + await killProcessAndPorts(esbProcess.pid, appPort); }, 1000000); it('should lint correctly with eslint and handle external HTML files and inline templates', async () => { @@ -164,6 +174,11 @@ describe('Angular Projects', () => { it('should build the dependent buildable lib and its child lib, as well as the app', async () => { // ARRANGE + const esbuildApp = uniq('esbuild-app'); + runCLI( + `generate @nx/angular:app ${esbuildApp} --bundler=esbuild --no-interactive` + ); + const buildableLib = uniq('buildlib1'); const buildableChildLib = uniq('buildlib2'); @@ -196,6 +211,27 @@ describe('Angular Projects', () => { export class AppModule {} ` ); + updateFile( + `apps/${esbuildApp}/src/app/app.module.ts`, + ` + import { BrowserModule } from '@angular/platform-browser'; + import { NgModule } from '@angular/core'; + import {${ + names(buildableLib).className + }Module} from '@${proj}/${buildableLib}'; + + import { AppComponent } from './app.component'; + import { NxWelcomeComponent } from './nx-welcome.component'; + + @NgModule({ + declarations: [AppComponent, NxWelcomeComponent], + imports: [BrowserModule, ${names(buildableLib).className}Module], + providers: [], + bootstrap: [AppComponent], + }) + export class AppModule {} + ` + ); // update the buildable lib module to include a ref to the buildable child lib updateFile( @@ -224,9 +260,20 @@ describe('Angular Projects', () => { }; return config; }); + updateProjectConfig(esbuildApp, (config) => { + config.targets.build.executor = '@nx/angular:browser-esbuild'; + config.targets.build.options = { + ...config.targets.build.options, + buildLibsFromSource: false, + }; + return config; + }); // ACT const libOutput = runCLI(`build ${app1} --configuration=development`); + const esbuildLibOutput = runCLI( + `build ${esbuildApp} --configuration=development` + ); // ASSERT expect(libOutput).toContain( @@ -238,6 +285,9 @@ describe('Angular Projects', () => { // the path to dist const mainBundle = readFile(`dist/apps/${app1}/main.js`); expect(mainBundle).toContain(`dist/libs/${buildableLib}`); + + const mainEsBuildBundle = readFile(`dist/apps/${esbuildApp}/main.js`); + expect(mainEsBuildBundle).toContain(`dist/libs/${buildableLib}`); }); it('should build publishable libs successfully', () => { diff --git a/e2e/angular-extensions/project.json b/e2e/angular-extensions/project.json index 209c8a3eb427b..411e48cde0e80 100644 --- a/e2e/angular-extensions/project.json +++ b/e2e/angular-extensions/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/angular-extensions", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["angular"] } diff --git a/e2e/cypress/project.json b/e2e/cypress/project.json index 136ae96328289..70dc45b433d48 100644 --- a/e2e/cypress/project.json +++ b/e2e/cypress/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/cypress", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["cypress", "react"] } diff --git a/e2e/detox/project.json b/e2e/detox/project.json index 87352a58253bf..ccacb9fb97042 100644 --- a/e2e/detox/project.json +++ b/e2e/detox/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/detox", "projectType": "application", "targets": { - "e2e-macos": {}, - "run-e2e-tests": {} + "e2e-macos": {} }, "implicitDependencies": ["detox"] } diff --git a/e2e/esbuild/project.json b/e2e/esbuild/project.json index 31bb726c66f4e..3e4973fbe8f71 100644 --- a/e2e/esbuild/project.json +++ b/e2e/esbuild/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/esbuild", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["esbuild"] } diff --git a/e2e/esbuild/src/esbuild.test.ts b/e2e/esbuild/src/esbuild.test.ts index 66e0f983b611f..0eba36bc83d5a 100644 --- a/e2e/esbuild/src/esbuild.test.ts +++ b/e2e/esbuild/src/esbuild.test.ts @@ -42,28 +42,27 @@ describe('EsBuild Plugin', () => { name: `@proj/${myPkg}`, version: '0.0.1', type: 'commonjs', + main: './index.cjs', + dependencies: {}, }); // Build normally with package.json generation. runCLI(`build ${myPkg}`); - expect(runCommand(`node dist/libs/${myPkg}/index.js`)).toMatch(/Hello/); + expect(runCommand(`node dist/libs/${myPkg}/index.cjs`)).toMatch(/Hello/); // main field should be set correctly in package.json - checkFilesExist(`dist/libs/${myPkg}/package.json`); + checkFilesExist( + `dist/libs/${myPkg}/package.json`, + `dist/libs/${myPkg}/pnpm-lock.yaml` + ); expect(runCommand(`node dist/libs/${myPkg}`)).toMatch(/Hello/); - expect(runCommand(`node dist/libs/${myPkg}/index.js`)).toMatch(/Hello/); + expect(runCommand(`node dist/libs/${myPkg}/index.cjs`)).toMatch(/Hello/); // main field should be set correctly in package.json expect(readFile(`dist/libs/${myPkg}/assets/a.md`)).toMatch(/file a/); expect(readFile(`dist/libs/${myPkg}/assets/b.md`)).toMatch(/file b/); - /* CJS format is not used by default, but passing --format=esm,cjs generates with it. - */ - checkFilesDoNotExist(`dist/libs/${myPkg}/index.cjs`); - runCLI(`build ${myPkg} --format=esm,cjs`); - checkFilesExist(`dist/libs/${myPkg}/index.cjs`); - /* Metafile is not generated by default, but passing --metafile generates it. */ checkFilesDoNotExist(`dist/libs/${myPkg}/meta.json`); @@ -81,7 +80,7 @@ describe('EsBuild Plugin', () => { ); expect(() => runCLI(`build ${myPkg}`)).toThrow(); expect(() => runCLI(`build ${myPkg} --skipTypeCheck`)).not.toThrow(); - expect(runCommand(`node dist/libs/${myPkg}/index.js`)).toMatch(/Bye/); + expect(runCommand(`node dist/libs/${myPkg}/index.cjs`)).toMatch(/Bye/); // Reset file updateFile( `libs/${myPkg}/src/index.ts`, @@ -141,7 +140,7 @@ describe('EsBuild Plugin', () => { expect( readJson(`dist/libs/${parentLib}/package.json`).dependencies?.['dayjs'] ).not.toBeDefined(); - let runResult = runCommand(`node dist/libs/${parentLib}/index.js`); + let runResult = runCommand(`node dist/libs/${parentLib}/index.cjs`); expect(runResult).toMatch(/Hello world/); expect(runResult).toMatch(/Hello from child lib/); @@ -155,7 +154,7 @@ describe('EsBuild Plugin', () => { rambda: expect.any(String), lodash: expect.any(String), }); - runResult = runCommand(`node dist/libs/${parentLib}/index.js`); + runResult = runCommand(`node dist/libs/${parentLib}/index.cjs`); expect(runResult).toMatch(/Hello world/); expect(runResult).toMatch(/Hello from child lib/); }, 300_000); @@ -164,16 +163,18 @@ describe('EsBuild Plugin', () => { const myPkg = uniq('my-pkg'); runCLI(`generate @nx/js:lib ${myPkg} --bundler=esbuild`); updateFile(`libs/${myPkg}/src/lib/${myPkg}.ts`, `console.log('Hello');\n`); - updateFile(`libs/${myPkg}/src/index.ts`, `import './lib/${myPkg}.js';\n`); + updateFile(`libs/${myPkg}/src/index.ts`, `import './lib/${myPkg}.cjs';\n`); runCLI(`build ${myPkg} --bundle=false`); checkFilesExist( - `dist/libs/${myPkg}/lib/${myPkg}.js`, - `dist/libs/${myPkg}/index.js` + `dist/libs/${myPkg}/libs/${myPkg}/src/lib/${myPkg}.cjs`, + `dist/libs/${myPkg}/index.cjs` ); // Test files are excluded in tsconfig (e.g. tsconfig.lib.json) - checkFilesDoNotExist(`dist/libs/${myPkg}/lib/${myPkg}.spec.js`); + checkFilesDoNotExist( + `dist/libs/${myPkg}/libs/${myPkg}/src/lib/${myPkg}.spec.cjs` + ); // Can run package (package.json fields are correctly generated) expect(runCommand(`node dist/libs/${myPkg}`)).toMatch(/Hello/); }, 300_000); @@ -190,10 +191,18 @@ describe('EsBuild Plugin', () => { return json; }); - runCommand(`build ${myPkg}`); + runCLI(`build ${myPkg}`); - expect(runCommand(`node dist/libs/${myPkg}/main.js`)).toMatch(/main/); - expect(runCommand(`node dist/libs/${myPkg}/extra.js`)).toMatch(/extra/); + checkFilesExist( + `dist/libs/${myPkg}/index.cjs`, + `dist/libs/${myPkg}/extra.cjs` + ); + expect( + runCommand(`node dist/libs/${myPkg}/index.cjs`, { failOnError: true }) + ).toMatch(/main/); + expect( + runCommand(`node dist/libs/${myPkg}/extra.cjs`, { failOnError: true }) + ).toMatch(/extra/); }, 120_000); it('should support external esbuild.config.js file', async () => { diff --git a/e2e/expo/project.json b/e2e/expo/project.json index f660ac0090db7..8ca70e7e297b1 100644 --- a/e2e/expo/project.json +++ b/e2e/expo/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/expo", "projectType": "application", "targets": { - "e2e-macos": {}, - "run-e2e-tests": {} + "e2e-macos": {} }, "implicitDependencies": ["expo"] } diff --git a/e2e/expo/src/expo.test.ts b/e2e/expo/src/expo.test.ts index 139fb29b112ff..cb9f8a02f9cfe 100644 --- a/e2e/expo/src/expo.test.ts +++ b/e2e/expo/src/expo.test.ts @@ -2,6 +2,7 @@ import { checkFilesExist, cleanupProject, expectTestsPass, + getPackageManagerCommand, killPorts, newProject, promisifiedTreeKill, @@ -9,9 +10,11 @@ import { readResolvedConfiguration, runCLI, runCLIAsync, + runCommand, runCommandUntil, uniq, updateFile, + updateJson, } from '@nx/e2e/utils'; import { join } from 'path'; @@ -22,6 +25,16 @@ describe('expo', () => { beforeAll(() => { proj = newProject(); + // we create empty preset above which skips creation of `production` named input + updateJson('nx.json', (nxJson) => { + nxJson.namedInputs = { + default: ['{projectRoot}/**/*', 'sharedGlobals'], + production: ['default'], + sharedGlobals: [], + }; + nxJson.targetDefaults.build.inputs = ['production', '^production']; + return nxJson; + }); runCLI(`generate @nx/expo:application ${appName} --no-interactive`); runCLI( `generate @nx/expo:library ${libName} --buildable --publishable --importPath=${proj}/${libName}` @@ -92,15 +105,13 @@ describe('expo', () => { expect(prebuildResult.combinedOutput).toContain('Config synced'); }); - // TODO(emily): expo-cli always fetches the latest version of react native - // re-enable it when expo-cli is fixed - xit('should install', async () => { + it('should install', async () => { // run install command const installResults = await runCLIAsync( - `install ${appName} --no-interactive --check` + `install ${appName} --no-interactive` ); expect(installResults.combinedOutput).toContain( - 'Dependencies are up to date' + 'Successfully ran target install' ); }); @@ -125,8 +136,23 @@ describe('expo', () => { it('should build publishable library', async () => { expect(() => { runCLI(`build ${libName}`); - checkFilesExist(`dist/libs/${libName}/index.js`); + checkFilesExist(`dist/libs/${libName}/index.esm.js`); checkFilesExist(`dist/libs/${libName}/src/index.d.ts`); }).not.toThrow(); }); + + it('should tsc app', async () => { + expect(() => { + const pmc = getPackageManagerCommand(); + runCommand( + `${pmc.runUninstalledPackage} tsc -p apps/${appName}/tsconfig.app.json` + ); + checkFilesExist( + `dist/out-tsc/apps/${appName}/src/app/App.js`, + `dist/out-tsc/apps/${appName}/src/app/App.d.ts`, + `dist/out-tsc/libs/${libName}/src/index.js`, + `dist/out-tsc/libs/${libName}/src/index.d.ts` + ); + }).not.toThrow(); + }); }); diff --git a/e2e/jest/project.json b/e2e/jest/project.json index 0fd12e8e48f6d..697d2702d33bf 100644 --- a/e2e/jest/project.json +++ b/e2e/jest/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/jest", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["jest"] } diff --git a/e2e/js/project.json b/e2e/js/project.json index 3b391463c1638..f69517637a885 100644 --- a/e2e/js/project.json +++ b/e2e/js/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/js", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["jest"] } diff --git a/e2e/js/src/js-bundling.test.ts b/e2e/js/src/js-bundling.test.ts deleted file mode 100644 index d2ad326b6c202..0000000000000 --- a/e2e/js/src/js-bundling.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - checkFilesExist, - cleanupProject, - newProject, - runCLI, - uniq, -} from '@nx/e2e/utils'; - -describe('bundling libs', () => { - let scope: string; - - beforeEach(() => { - scope = newProject(); - }); - - afterEach(() => cleanupProject()); - - it('should support esbuild and vite bundlers for building libs', () => { - const esbuildLib = uniq('esbuildlib'); - const viteLib = uniq('vitelib'); - - runCLI( - `generate @nx/js:lib ${esbuildLib} --bundler=esbuild --no-interactive` - ); - runCLI(`generate @nx/js:lib ${viteLib} --bundler=vite --no-interactive`); - - runCLI(`build ${esbuildLib}`); - runCLI(`build ${viteLib}`); - - checkFilesExist(`dist/libs/${esbuildLib}/index.js`); - checkFilesExist(`dist/libs/${viteLib}/index.js`); - }, 240_000); -}); diff --git a/e2e/js/src/js-packaging.test.ts b/e2e/js/src/js-packaging.test.ts new file mode 100644 index 0000000000000..68470b8874de5 --- /dev/null +++ b/e2e/js/src/js-packaging.test.ts @@ -0,0 +1,273 @@ +import { + updateJson, + updateProjectConfig, + cleanupProject, + newProject, + runCLI, + tmpProjPath, + runCommand, + createFile, + uniq, + getPackageManagerCommand, + readJson, + updateFile, +} from '@nx/e2e/utils'; +import { join } from 'path'; +import { ensureDirSync } from 'fs-extra'; + +describe('bundling libs', () => { + let scope: string; + + beforeEach(() => { + scope = newProject(); + }); + + afterEach(() => cleanupProject()); + + it('should support esbuild, rollup, vite bundlers for building libs', () => { + const esbuildLib = uniq('esbuildlib'); + const viteLib = uniq('vitelib'); + const rollupLib = uniq('rolluplib'); + + runCLI( + `generate @nx/js:lib ${esbuildLib} --bundler=esbuild --no-interactive` + ); + runCLI(`generate @nx/js:lib ${viteLib} --bundler=vite --no-interactive`); + runCLI( + `generate @nx/js:lib ${rollupLib} --bundler=rollup --no-interactive` + ); + + runCLI(`build ${esbuildLib}`); + runCLI(`build ${viteLib}`); + runCLI(`build ${rollupLib}`); + + const pmc = getPackageManagerCommand(); + let output: string; + + // Make sure outputs in commonjs project + createFile( + 'test-cjs/package.json', + JSON.stringify( + { + name: 'test-cjs', + private: true, + type: 'commonjs', + dependencies: { + [`@proj/${esbuildLib}`]: `file:../dist/libs/${esbuildLib}`, + [`@proj/${viteLib}`]: `file:../dist/libs/${viteLib}`, + [`@proj/${rollupLib}`]: `file:../dist/libs/${rollupLib}`, + }, + }, + null, + 2 + ) + ); + createFile( + 'test-cjs/index.js', + ` + const { ${esbuildLib} } = require('@proj/${esbuildLib}'); + const { ${viteLib} } = require('@proj/${viteLib}'); + const { ${rollupLib} } = require('@proj/${rollupLib}'); + console.log(${esbuildLib}()); + console.log(${viteLib}()); + console.log(${rollupLib}()); + ` + ); + runCommand(pmc.install, { + cwd: join(tmpProjPath(), 'test-cjs'), + }); + output = runCommand('node index.js', { + cwd: join(tmpProjPath(), 'test-cjs'), + }); + expect(output).toContain(esbuildLib); + expect(output).toContain(viteLib); + expect(output).toContain(rollupLib); + + // Make sure outputs in esm project + createFile( + 'test-esm/package.json', + JSON.stringify( + { + name: 'test-esm', + private: true, + type: 'module', + dependencies: { + [`@proj/${esbuildLib}`]: `file:../dist/libs/${esbuildLib}`, + [`@proj/${viteLib}`]: `file:../dist/libs/${viteLib}`, + [`@proj/${rollupLib}`]: `file:../dist/libs/${rollupLib}`, + }, + }, + null, + 2 + ) + ); + createFile( + 'test-esm/index.js', + ` + import { ${esbuildLib} } from '@proj/${esbuildLib}'; + import { ${viteLib} } from '@proj/${viteLib}'; + import { ${rollupLib} } from '@proj/${rollupLib}'; + console.log(${esbuildLib}()); + console.log(${viteLib}()); + console.log(${rollupLib}()); + ` + ); + runCommand(pmc.install, { + cwd: join(tmpProjPath(), 'test-esm'), + }); + output = runCommand('node index.js', { + cwd: join(tmpProjPath(), 'test-esm'), + }); + expect(output).toContain(esbuildLib); + expect(output).toContain(viteLib); + expect(output).toContain(rollupLib); + }, 500_000); + + it('should support tsc and swc for building libs', () => { + const tscLib = uniq('tsclib'); + const swcLib = uniq('swclib'); + const tscEsmLib = uniq('tscesmlib'); + const swcEsmLib = uniq('swcesmlib'); + + runCLI(`generate @nx/js:lib ${tscLib} --bundler=tsc --no-interactive`); + runCLI(`generate @nx/js:lib ${swcLib} --bundler=swc --no-interactive`); + runCLI(`generate @nx/js:lib ${tscEsmLib} --bundler=tsc --no-interactive`); + runCLI(`generate @nx/js:lib ${swcEsmLib} --bundler=swc --no-interactive`); + + // Change module format to ESM + updateJson(`libs/${tscEsmLib}/tsconfig.json`, (json) => { + json.compilerOptions.module = 'esnext'; + return json; + }); + updateJson(`libs/${swcEsmLib}/.swcrc`, (json) => { + json.module.type = 'es6'; + return json; + }); + // Node ESM requires file extensions in imports so must add them before building + updateFile( + `libs/${tscEsmLib}/src/index.ts`, + `export * from './lib/${tscEsmLib}.js';` + ); + updateFile( + `libs/${swcEsmLib}/src/index.ts`, + `export * from './lib/${swcEsmLib}.js';` + ); + + // Add additional entry points for `exports` field + updateProjectConfig(tscLib, (json) => { + json.targets.build.options.additionalEntryPoints = [ + `libs/${tscLib}/src/foo/*.ts`, + ]; + return json; + }); + updateFile(`libs/${tscLib}/src/foo/bar.ts`, `export const bar = 'bar';`); + updateFile(`libs/${tscLib}/src/foo/faz.ts`, `export const faz = 'faz';`); + updateProjectConfig(swcLib, (json) => { + json.targets.build.options.additionalEntryPoints = [ + `libs/${swcLib}/src/foo/*.ts`, + ]; + return json; + }); + updateFile(`libs/${swcLib}/src/foo/bar.ts`, `export const bar = 'bar';`); + updateFile(`libs/${swcLib}/src/foo/faz.ts`, `export const faz = 'faz';`); + + runCLI(`build ${tscLib} --generateExportsField`); + runCLI(`build ${swcLib} --generateExportsField`); + runCLI(`build ${tscEsmLib} --generateExportsField`); + runCLI(`build ${swcEsmLib} --generateExportsField`); + + expect(readJson(`dist/libs/${tscLib}/package.json`).exports).toEqual({ + './package.json': './package.json', + '.': './src/index.js', + './foo/bar': './src/foo/bar.js', + './foo/faz': './src/foo/faz.js', + }); + + expect(readJson(`dist/libs/${swcLib}/package.json`).exports).toEqual({ + './package.json': './package.json', + '.': './src/index.js', + './foo/bar': './src/foo/bar.js', + './foo/faz': './src/foo/faz.js', + }); + + const pmc = getPackageManagerCommand(); + let output: string; + + // Make sure CJS output is correct + createFile( + 'test-cjs/package.json', + JSON.stringify( + { + name: 'test-cjs', + private: true, + type: 'commonjs', + dependencies: { + [`@proj/${tscLib}`]: `file:../dist/libs/${tscLib}`, + [`@proj/${swcLib}`]: `file:../dist/libs/${swcLib}`, + }, + }, + null, + 2 + ) + ); + createFile( + 'test-cjs/index.js', + ` + const { ${tscLib} } = require('@proj/${tscLib}'); + const { ${swcLib} } = require('@proj/${swcLib}'); + // additional entry-points + const { bar } = require('@proj/${tscLib}/foo/bar'); + const { faz } = require('@proj/${swcLib}/foo/faz'); + console.log(${tscLib}()); + console.log(${swcLib}()); + console.log(bar); + console.log(faz); + ` + ); + runCommand(pmc.install, { + cwd: join(tmpProjPath(), 'test-cjs'), + }); + output = runCommand('node index.js', { + cwd: join(tmpProjPath(), 'test-cjs'), + }); + expect(output).toContain(tscLib); + expect(output).toContain(swcLib); + expect(output).toContain('bar'); + expect(output).toContain('faz'); + + // Make sure ESM output is correct + createFile( + 'test-esm/package.json', + JSON.stringify( + { + name: 'test-esm', + private: true, + type: 'module', + dependencies: { + [`@proj/${tscEsmLib}`]: `file:../dist/libs/${tscEsmLib}`, + [`@proj/${swcEsmLib}`]: `file:../dist/libs/${swcEsmLib}`, + }, + }, + null, + 2 + ) + ); + createFile( + 'test-esm/index.js', + ` + import { ${tscEsmLib} } from '@proj/${tscEsmLib}'; + import { ${swcEsmLib} } from '@proj/${swcEsmLib}'; + console.log(${tscEsmLib}()); + console.log(${swcEsmLib}()); + ` + ); + runCommand(pmc.install, { + cwd: join(tmpProjPath(), 'test-esm'), + }); + output = runCommand('node index.js', { + cwd: join(tmpProjPath(), 'test-esm'), + }); + expect(output).toContain(tscEsmLib); + expect(output).toContain(swcEsmLib); + }, 500_000); +}); diff --git a/e2e/js/src/js-swc.test.ts b/e2e/js/src/js-swc.test.ts index 502abcf3ffaba..128509947fb3c 100644 --- a/e2e/js/src/js-swc.test.ts +++ b/e2e/js/src/js-swc.test.ts @@ -91,7 +91,15 @@ describe('js e2e', () => { return json; }); - runCLI(`build ${lib} --generateLockfile=true`); + updateJson(`libs/${lib}/package.json`, (json) => { + // Delete automatically generated helper dependency to test legacy behavior. + delete json.dependencies['@swc/helpers']; + return json; + }); + + runCLI( + `build ${lib} --generateLockfile=true --updateBuildableProjectDepsInPackageJson` + ); checkFilesExist( `dist/libs/${lib}/package.json`, `dist/libs/${lib}/${ diff --git a/e2e/js/src/js-tsc.test.ts b/e2e/js/src/js-tsc.test.ts index 7c33ab06a7837..487fa1344505c 100644 --- a/e2e/js/src/js-tsc.test.ts +++ b/e2e/js/src/js-tsc.test.ts @@ -129,9 +129,13 @@ describe('js e2e', () => { return json; }); - runCLI(`build ${lib}`); + updateJson(`libs/${lib}/package.json`, (json) => { + // Delete automatically generated helper dependency to test legacy behavior. + delete json.dependencies.tslib; + return json; + }); - const rootPackageJson = readJson(`package.json`); + runCLI(`build ${lib} --updateBuildableProjectDepsInPackageJson`); expect(readJson(`dist/libs/${lib}/package.json`)).toHaveProperty( 'peerDependencies.tslib' @@ -189,6 +193,15 @@ describe('js e2e', () => { `dist/libs/${lib}/src/lib/${lib}.js`, `dist/libs/${lib}/src/lib/${lib}.d.ts` ); + + // run a second time skipping the nx cache and with the outputs present + const secondBatchBuildOutput = runCLI( + `build ${parentLib} --skip-nx-cache`, + { env: { NX_BATCH_MODE: 'true' } } + ); + expect(secondBatchBuildOutput).toContain( + `Successfully ran target build for project ${parentLib} and 1 task it depends on` + ); }, 240_000); it('should not create a `.babelrc` file when creating libs with js executors (--compiler=tsc)', () => { @@ -221,7 +234,13 @@ describe('package.json updates', () => { `; }); - runCLI(`build ${lib}`); + updateJson(`libs/${lib}/package.json`, (json) => { + // Delete automatically generated helper dependency to test legacy behavior. + delete json.dependencies.tslib; + return json; + }); + + runCLI(`build ${lib} --updateBuildableProjectDepsInPackageJson`); // Check that only 'react' exists, don't care about version expect(readJson(`dist/libs/${lib}/package.json`).dependencies).toEqual({ diff --git a/e2e/js/src/js.test.ts b/e2e/js/src/js.test.ts index aabb81df37d13..b0227237541d7 100644 --- a/e2e/js/src/js.test.ts +++ b/e2e/js/src/js.test.ts @@ -4,7 +4,9 @@ import { cleanupProject, createFile, newProject, + readFile, readJson, + rmDist, runCLI, runCLIAsync, uniq, @@ -160,4 +162,72 @@ export function ${lib}Wildcard() { runCLI(`build ${nonBuildable}`); checkFilesExist(`dist/libs/${nonBuildable}/src/index.js`); }); + + it('should build buildable libraries using the task graph and handle more scenarios than current implementation', () => { + const lib1 = uniq('lib1'); + const lib2 = uniq('lib2'); + runCLI(`generate @nx/js:lib ${lib1} --bundler=tsc --no-interactive`); + runCLI(`generate @nx/js:lib ${lib2} --bundler=tsc --no-interactive`); + + // add dep between lib1 and lib2 + updateFile( + `libs/${lib1}/src/index.ts`, + `export { ${lib2} } from '@${scope}/${lib2}';` + ); + + // check current implementation + expect(runCLI(`build ${lib1} --skip-nx-cache`)).toContain( + 'Done compiling TypeScript files' + ); + checkFilesExist(`dist/libs/${lib1}/src/index.js`); + checkFilesExist(`dist/libs/${lib2}/src/index.js`); + + // cleanup dist + rmDist(); + + // check task graph implementation + expect( + runCLI(`build ${lib1} --skip-nx-cache`, { + env: { NX_BUILDABLE_LIBRARIES_TASK_GRAPH: 'true' }, + }) + ).toContain('Done compiling TypeScript files'); + checkFilesExist(`dist/libs/${lib1}/src/index.js`); + checkFilesExist(`dist/libs/${lib2}/src/index.js`); + + // change build target name of lib2 and update target dependencies + updateJson(`libs/${lib2}/project.json`, (json) => { + json.targets['my-custom-build'] = json.targets.build; + delete json.targets.build; + return json; + }); + const originalNxJson = readFile('nx.json'); + updateJson('nx.json', (json) => { + json.targetDefaults.build = { + ...json.targetDefaults.build, + dependsOn: [...json.targetDefaults.build.dependsOn, '^my-custom-build'], + }; + return json; + }); + + // cleanup dist + rmDist(); + + // check current implementation, it doesn't support a different build target name + expect(() => runCLI(`build ${lib1} --skip-nx-cache`)).toThrow(); + + // cleanup dist + rmDist(); + + // check task graph implementation + expect( + runCLI(`build ${lib1} --skip-nx-cache`, { + env: { NX_BUILDABLE_LIBRARIES_TASK_GRAPH: 'true' }, + }) + ).toContain('Done compiling TypeScript files'); + checkFilesExist(`dist/libs/${lib1}/src/index.js`); + checkFilesExist(`dist/libs/${lib2}/src/index.js`); + + // restore nx.json + updateFile('nx.json', () => originalNxJson); + }); }); diff --git a/e2e/lerna-smoke-tests/project.json b/e2e/lerna-smoke-tests/project.json index be96e4daf6fbb..c0c1f38643de8 100644 --- a/e2e/lerna-smoke-tests/project.json +++ b/e2e/lerna-smoke-tests/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/lerna-smoke-tests", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["nx", "devkit"] } diff --git a/e2e/linter/src/linter.test.ts b/e2e/linter/src/linter.test.ts index 54d90f741fbd9..01e83670d880c 100644 --- a/e2e/linter/src/linter.test.ts +++ b/e2e/linter/src/linter.test.ts @@ -246,6 +246,21 @@ describe('Linter', () => { 'A project tagged with "validtag" can only depend on libs tagged with "validtag"' ); }, 1000000); + + it('should print the effective configuration for a file specified using --printConfig', () => { + const eslint = readJson('.eslintrc.json'); + eslint.overrides.push({ + files: ['src/index.ts'], + rules: { + 'specific-rule': 'off', + }, + }); + updateFile('.eslintrc.json', JSON.stringify(eslint, null, 2)); + const out = runCLI(`lint ${myapp} --printConfig src/index.ts`, { + silenceError: true, + }); + expect(out).toContain('"specific-rule": ['); + }, 1000000); }); describe('workspace boundary rules', () => { @@ -465,8 +480,7 @@ describe('Linter', () => { it('should report dependency check issues', () => { const rootPackageJson = readJson('package.json'); const nxVersion = rootPackageJson.devDependencies.nx; - const swcCoreVersion = rootPackageJson.devDependencies['@swc/core']; - const swcHelpersVersion = rootPackageJson.dependencies['@swc/helpers']; + const tslibVersion = rootPackageJson.dependencies['tslib']; let out = runCLI(`lint ${mylib}`, { silenceError: true }); expect(out).toContain('All files pass linting'); @@ -479,13 +493,12 @@ describe('Linter', () => { content.replace(/return .*;/, `return names(${mylib}).className;`) ); - // output should now report missing dependencies section + // output should now report missing dependency out = runCLI(`lint ${mylib}`, { silenceError: true }); - expect(out).toContain( - 'Dependency sections are missing from the "package.json"' - ); + expect(out).toContain('they are missing'); + expect(out).toContain('@nx/devkit'); - // should fix the missing section issue + // should fix the missing dependency issue out = runCLI(`lint ${mylib} --fix`, { silenceError: true }); expect(out).toContain( `Successfully ran target lint for project ${mylib}` @@ -495,12 +508,12 @@ describe('Linter', () => { { "dependencies": { "@nx/devkit": "${nxVersion}", - "@swc/core": "${swcCoreVersion}", - "@swc/helpers": "${swcHelpersVersion}", - "nx": "${nxVersion}", + "tslib": "${tslibVersion}", }, + "main": "./src/index.js", "name": "@proj/${mylib}", "type": "commonjs", + "typings": "./src/index.d.ts", "version": "0.0.1", } `); @@ -512,7 +525,7 @@ describe('Linter', () => { }); out = runCLI(`lint ${mylib}`, { silenceError: true }); expect(out).toContain( - `The version specifier does not contain the installed version of "@nx/devkit" package: ${nxVersion}` + 'version specifier does not contain the installed version of "@nx/devkit"' ); // should fix the version mismatch issue diff --git a/e2e/next/project.json b/e2e/next/project.json index 11e9c919ce706..71081e6cd49f3 100644 --- a/e2e/next/project.json +++ b/e2e/next/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/next", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["next"] } diff --git a/e2e/next/src/next-appdir.test.ts b/e2e/next/src/next-appdir.test.ts index bc21eb5f3d641..33b833da65cb1 100644 --- a/e2e/next/src/next-appdir.test.ts +++ b/e2e/next/src/next-appdir.test.ts @@ -1,5 +1,6 @@ import { cleanupProject, + isNotWindows, newProject, runCLI, uniq, @@ -22,7 +23,7 @@ describe('Next.js App Router', () => { const appName = uniq('app'); const jsLib = uniq('tslib'); - runCLI(`generate @nx/next:app ${appName}`); + runCLI(`generate @nx/next:app ${appName} --e2eTestRunner=playwright`); runCLI(`generate @nx/js:lib ${jsLib} --no-interactive`); updateFile( @@ -42,7 +43,7 @@ describe('Next.js App Router', () => { await checkApp(appName, { checkUnitTest: false, checkLint: true, - checkE2E: false, + checkE2E: isNotWindows(), checkExport: false, }); }, 300_000); diff --git a/e2e/next/src/utils.ts b/e2e/next/src/utils.ts index 90307fae2852c..343f6116e8775 100644 --- a/e2e/next/src/utils.ts +++ b/e2e/next/src/utils.ts @@ -1,7 +1,6 @@ -import { execSync } from 'child_process'; import { checkFilesExist, - killPort, + killPorts, readJson, runCLI, runCLIAsync, @@ -43,10 +42,10 @@ export async function checkApp( if (opts.checkE2E && runCypressTests()) { const e2eResults = runCLI( - `e2e ${appName}-e2e --no-watch --configuration=production --port=9000` + `e2e ${appName}-e2e --no-watch --configuration=production` ); - expect(e2eResults).toContain('All specs passed!'); - expect(await killPort(9000)).toBeTruthy(); + expect(e2eResults).toContain('Successfully ran target e2e for project'); + expect(await killPorts()).toBeTruthy(); } if (opts.checkExport) { diff --git a/e2e/node/project.json b/e2e/node/project.json index b6abdf7b72b13..5bd0ba8505153 100644 --- a/e2e/node/project.json +++ b/e2e/node/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/node", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["node", "nest"] } diff --git a/e2e/node/src/node-webpack.test.ts b/e2e/node/src/node-webpack.test.ts index c1ecda50cad9f..ed023a0cc622e 100644 --- a/e2e/node/src/node-webpack.test.ts +++ b/e2e/node/src/node-webpack.test.ts @@ -5,9 +5,12 @@ import { readFile, runCLI, runCLIAsync, + runCommandUntil, + waitUntil, tmpProjPath, uniq, updateFile, + updateProjectConfig, } from '@nx/e2e/utils'; import { execSync } from 'child_process'; @@ -47,5 +50,54 @@ describe('Node Applications + webpack', () => { await runCLIAsync(`build ${app} --optimization`); const optimizedContent = readFile(`dist/apps/${app}/main.js`); expect(optimizedContent).toContain('console.log("foo "+"bar")'); + + // Test that serve can re-run dependency builds. + const lib = uniq('nodelib'); + runCLI(`generate @nx/js:lib ${lib} --bundler=esbuild --no-interactive`); + + updateProjectConfig(app, (config) => { + // Since we read from lib from dist, we should re-build it when lib changes. + config.targets.build.options.buildLibsFromSource = false; + config.targets.serve.options.runBuildTargetDependencies = true; + return config; + }); + + updateFile( + `apps/${app}/src/main.ts`, + ` + import { ${lib} } from '@proj/${lib}'; + console.log('Hello ' + ${lib}()); + ` + ); + + const serveProcess = await runCommandUntil( + `serve ${app} --watch --runBuildTargetDependencies`, + (output) => { + return output.includes(`Hello`); + } + ); + + // Update library source and check that it triggers rebuild. + const terminalOutputs: string[] = []; + serveProcess.stdout.on('data', (chunk) => { + const data = chunk.toString(); + terminalOutputs.push(data); + }); + + updateFile( + `libs/${lib}/src/index.ts`, + `export function ${lib}() { return 'should rebuild lib'; }` + ); + + await waitUntil( + () => { + return terminalOutputs.some((output) => + output.includes(`should rebuild lib`) + ); + }, + { timeout: 30_000, ms: 200 } + ); + + serveProcess.kill(); }, 300_000); }); diff --git a/e2e/nx-init/project.json b/e2e/nx-init/project.json index 925231f7559f7..5ac6aed235574 100644 --- a/e2e/nx-init/project.json +++ b/e2e/nx-init/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/nx-init", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["nx"] } diff --git a/e2e/nx-misc/project.json b/e2e/nx-misc/project.json index d714187245f70..68722dafadb72 100644 --- a/e2e/nx-misc/project.json +++ b/e2e/nx-misc/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/nx-misc", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["js"] } diff --git a/e2e/nx-misc/src/watch.test.ts b/e2e/nx-misc/src/watch.test.ts index 3729923eab48f..c38ce31bbc89e 100644 --- a/e2e/nx-misc/src/watch.test.ts +++ b/e2e/nx-misc/src/watch.test.ts @@ -1,6 +1,5 @@ import { cleanupProject, - createFile, newProject, runCLI, uniq, @@ -10,13 +9,23 @@ import { isVerboseE2ERun, } from '@nx/e2e/utils'; import { spawn } from 'child_process'; +import { join } from 'path'; +import { writeFileSync } from 'fs'; + +async function writeFileForWatcher(path: string, content: string) { + const e2ePath = join(tmpProjPath(), path); + + console.log(`writing to: ${e2ePath}`); + writeFileSync(e2ePath, content); + await wait(10); +} describe('Nx Commands', () => { let proj1 = uniq('proj1'); let proj2 = uniq('proj2'); let proj3 = uniq('proj3'); beforeAll(() => { - newProject({ packageManager: 'npm' }); + newProject(); runCLI(`generate @nx/js:lib ${proj1}`); runCLI(`generate @nx/js:lib ${proj2}`); runCLI(`generate @nx/js:lib ${proj3}`); @@ -28,22 +37,22 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--projects=${proj1} -- echo \\$NX_PROJECT_NAME` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); expect(await getOutput()).toEqual([proj1]); }); it('should watch for all projects and output the project name', async () => { const getOutput = await runWatch(`--all -- echo \\$NX_PROJECT_NAME`); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let content = await getOutput(); let results = content.sort(); @@ -53,10 +62,10 @@ describe('Nx Commands', () => { it('should watch for all project changes and output the file name changes', async () => { const getOutput = await runWatch(`--all -- echo \\$NX_FILE_CHANGES`); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = (await getOutput())[0]; let results = output.split(' ').sort(); @@ -72,10 +81,10 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--all --includeGlobalWorkspaceFiles -- echo \\$NX_FILE_CHANGES` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = (await getOutput())[0]; let results = output.split(' ').sort(); @@ -92,11 +101,11 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--projects=${proj1},${proj3} -- echo \\$NX_PROJECT_NAME` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = await getOutput(); let results = output.sort(); @@ -113,11 +122,11 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--projects=${proj3} --includeDependentProjects -- echo \\$NX_PROJECT_NAME` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = await getOutput(); let results = output.sort(); diff --git a/e2e/nx-misc/src/workspace.test.ts b/e2e/nx-misc/src/workspace.test.ts index e96d28420e66c..4fa85faae2cb0 100644 --- a/e2e/nx-misc/src/workspace.test.ts +++ b/e2e/nx-misc/src/workspace.test.ts @@ -15,11 +15,36 @@ import { getPackageManagerCommand, getSelectedPackageManager, runCommand, - runCreateWorkspace, } from '@nx/e2e/utils'; let proj: string; +describe('@nx/workspace:convert-to-monorepo', () => { + beforeEach(() => { + proj = newProject(); + }); + + afterEach(() => cleanupProject()); + + it('should convert a standalone project to a monorepo', async () => { + const reactApp = uniq('reactapp'); + runCLI( + `generate @nx/react:app ${reactApp} --rootProject=true --bundler=webpack --unitTestRunner=jest --e2eTestRunner=cypress --no-interactive` + ); + + runCLI('generate @nx/workspace:convert-to-monorepo --no-interactive'); + + checkFilesExist( + `apps/${reactApp}/src/main.tsx`, + `apps/e2e/cypress.config.ts` + ); + + expect(() => runCLI(`build ${reactApp}`)).not.toThrow(); + expect(() => runCLI(`test ${reactApp}`)).not.toThrow(); + expect(() => runCLI(`e2e e2e`)).not.toThrow(); + }); +}); + describe('Workspace Tests', () => { beforeAll(() => { proj = newProject(); @@ -176,6 +201,7 @@ describe('Workspace Tests', () => { expect(project.sourceRoot).toBe(`${newPath}/src`); expect(project.targets.lint.options.lintFilePatterns).toEqual([ `libs/shared/${lib1}/data-access/**/*.ts`, + `libs/shared/${lib1}/data-access/package.json`, ]); /** @@ -306,6 +332,7 @@ describe('Workspace Tests', () => { expect(project.targets.lint.options.lintFilePatterns).toEqual([ `libs/shared/${lib1}/data-access/**/*.ts`, + `libs/shared/${lib1}/data-access/package.json`, ]); /** @@ -434,6 +461,7 @@ describe('Workspace Tests', () => { expect(project.sourceRoot).toBe(`${newPath}/src`); expect(project.targets.lint.options.lintFilePatterns).toEqual([ `packages/shared/${lib1}/data-access/**/*.ts`, + `packages/shared/${lib1}/data-access/package.json`, ]); expect(project.tags).toEqual([]); @@ -569,6 +597,7 @@ describe('Workspace Tests', () => { expect(project.sourceRoot).toBe(`${newPath}/src`); expect(project.targets.lint.options.lintFilePatterns).toEqual([ `libs/${lib1}/data-access/**/*.ts`, + `libs/${lib1}/data-access/package.json`, ]); /** @@ -682,6 +711,7 @@ describe('Workspace Tests', () => { expect(project.sourceRoot).toBe(`${newPath}/src`); expect(project.targets.lint.options.lintFilePatterns).toEqual([ `libs/shared/${lib1}/data-access/**/*.ts`, + `libs/shared/${lib1}/data-access/package.json`, ]); /** diff --git a/e2e/nx-run/project.json b/e2e/nx-run/project.json index 4422fe23fce4c..33f0016d33f37 100644 --- a/e2e/nx-run/project.json +++ b/e2e/nx-run/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/nx-run", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["js"] } diff --git a/e2e/nx-run/src/affected-graph.test.ts b/e2e/nx-run/src/affected-graph.test.ts index 93f2349f95b90..fd6e0890ac005 100644 --- a/e2e/nx-run/src/affected-graph.test.ts +++ b/e2e/nx-run/src/affected-graph.test.ts @@ -384,7 +384,6 @@ describe('Nx Affected and Graph Tests', () => { target: mylib, type: 'static', }, - { source: myapp, target: mylib2, type: 'dynamic' }, ], [myappE2e]: [ { diff --git a/e2e/nx-run/src/cache.test.ts b/e2e/nx-run/src/cache.test.ts index d571676106d29..af2a0a044c718 100644 --- a/e2e/nx-run/src/cache.test.ts +++ b/e2e/nx-run/src/cache.test.ts @@ -1,10 +1,12 @@ import { cleanupProject, + directoryExists, listFiles, newProject, readFile, rmDist, runCLI, + tmpProjPath, uniq, updateFile, updateJson, @@ -157,17 +159,23 @@ describe('cache', () => { updateProjectConfig(mylib, (c) => { c.targets.build = { executor: 'nx:run-commands', - outputs: ['{workspaceRoot}/dist/*.txt'], + outputs: ['{workspaceRoot}/dist/!(.next)/**/!(z|x).(txt|md)'], options: { commands: [ 'rm -rf dist', 'mkdir dist', - 'echo a > dist/a.txt', - 'echo b > dist/b.txt', - 'echo c > dist/c.txt', - 'echo d > dist/d.txt', - 'echo e > dist/e.txt', - 'echo f > dist/f.txt', + 'mkdir dist/apps', + 'mkdir dist/.next', + 'echo a > dist/apps/a.txt', + 'echo b > dist/apps/b.txt', + 'echo c > dist/apps/c.txt', + 'echo d > dist/apps/d.txt', + 'echo e > dist/apps/e.txt', + 'echo f > dist/apps/f.md', + 'echo g > dist/apps/g.html', + 'echo h > dist/.next/h.txt', + 'echo x > dist/apps/x.txt', + 'echo z > dist/apps/z.md', ], parallel: false, }, @@ -182,27 +190,43 @@ describe('cache', () => { // Rerun without touching anything const rerunWithUntouchedOutputs = runCLI(`build ${mylib}`); expect(rerunWithUntouchedOutputs).toContain('local cache'); - const outputsWithUntouchedOutputs = listFiles('dist'); + const outputsWithUntouchedOutputs = [ + ...listFiles('dist/apps'), + ...listFiles('dist/.next').map((f) => `.next/${f}`), + ]; expect(outputsWithUntouchedOutputs).toContain('a.txt'); expect(outputsWithUntouchedOutputs).toContain('b.txt'); expect(outputsWithUntouchedOutputs).toContain('c.txt'); expect(outputsWithUntouchedOutputs).toContain('d.txt'); expect(outputsWithUntouchedOutputs).toContain('e.txt'); - expect(outputsWithUntouchedOutputs).toContain('f.txt'); + expect(outputsWithUntouchedOutputs).toContain('f.md'); + expect(outputsWithUntouchedOutputs).toContain('g.html'); + expect(outputsWithUntouchedOutputs).toContain('.next/h.txt'); + expect(outputsWithUntouchedOutputs).toContain('x.txt'); + expect(outputsWithUntouchedOutputs).toContain('z.md'); // Create a file in the dist that does not match output glob - updateFile('dist/c.ts', ''); + updateFile('dist/apps/c.ts', ''); // Rerun const rerunWithNewUnrelatedFile = runCLI(`build ${mylib}`); expect(rerunWithNewUnrelatedFile).toContain('local cache'); - const outputsAfterAddingUntouchedFileAndRerunning = listFiles('dist'); + const outputsAfterAddingUntouchedFileAndRerunning = [ + ...listFiles('dist/apps'), + ...listFiles('dist/.next').map((f) => `.next/${f}`), + ]; expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('a.txt'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('b.txt'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('c.txt'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('d.txt'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('e.txt'); - expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('f.txt'); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('f.md'); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('g.html'); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain( + '.next/h.txt' + ); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('x.txt'); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('z.md'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('c.ts'); // Clear Dist @@ -211,14 +235,18 @@ describe('cache', () => { // Rerun const rerunWithoutOutputs = runCLI(`build ${mylib}`); expect(rerunWithoutOutputs).toContain('read the output from the cache'); - const outputsWithoutOutputs = listFiles('dist'); + const outputsWithoutOutputs = listFiles('dist/apps'); + expect(directoryExists(`${tmpProjPath()}/dist/.next`)).toBe(false); expect(outputsWithoutOutputs).toContain('a.txt'); expect(outputsWithoutOutputs).toContain('b.txt'); expect(outputsWithoutOutputs).toContain('c.txt'); expect(outputsWithoutOutputs).toContain('d.txt'); expect(outputsWithoutOutputs).toContain('e.txt'); - expect(outputsWithoutOutputs).toContain('f.txt'); + expect(outputsWithoutOutputs).toContain('f.md'); expect(outputsWithoutOutputs).not.toContain('c.ts'); + expect(outputsWithoutOutputs).not.toContain('g.html'); + expect(outputsWithoutOutputs).not.toContain('x.txt'); + expect(outputsWithoutOutputs).not.toContain('z.md'); }); it('should use consider filesets when hashing', async () => { diff --git a/e2e/playwright/jest.config.ts b/e2e/playwright/jest.config.ts new file mode 100644 index 0000000000000..7c27da3d36d24 --- /dev/null +++ b/e2e/playwright/jest.config.ts @@ -0,0 +1,13 @@ +/* eslint-disable */ +export default { + transform: { + '^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], + maxWorkers: 1, + globals: {}, + globalSetup: '../utils/global-setup.ts', + globalTeardown: '../utils/global-teardown.ts', + displayName: 'e2e-playwright', + preset: '../../jest.preset.js', +}; diff --git a/e2e/playwright/project.json b/e2e/playwright/project.json new file mode 100644 index 0000000000000..d03e06e77984c --- /dev/null +++ b/e2e/playwright/project.json @@ -0,0 +1,10 @@ +{ + "name": "e2e-playwright", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "e2e/playwright", + "projectType": "application", + "targets": { + "e2e": {} + }, + "implicitDependencies": ["playwright"] +} diff --git a/e2e/playwright/src/playwright.test.ts b/e2e/playwright/src/playwright.test.ts new file mode 100644 index 0000000000000..18e94142d6d5d --- /dev/null +++ b/e2e/playwright/src/playwright.test.ts @@ -0,0 +1,50 @@ +import { + cleanupProject, + newProject, + uniq, + runCLI, + ensurePlaywrightBrowsersInstallation, +} from '@nx/e2e/utils'; + +const TEN_MINS_MS = 600_000; +describe('Playwright E2E Test runner', () => { + beforeAll(() => { + newProject({ name: uniq('playwright') }); + }); + + afterAll(() => cleanupProject()); + + it( + 'should test and lint example app', + () => { + runCLI(`g @nx/js:lib demo-e2e --unitTestRunner none --bundler none`); + runCLI(`g @nx/playwright:configuration --project demo-e2e`); + ensurePlaywrightBrowsersInstallation(); + + const e2eResults = runCLI(`e2e demo-e2e`); + expect(e2eResults).toContain('Successfully ran target e2e for project'); + + const lintResults = runCLI(`lint demo-e2e`); + expect(lintResults).toContain('All files pass linting'); + }, + TEN_MINS_MS + ); + + it( + 'should test and lint example app with js', + () => { + runCLI( + `g @nx/js:lib demo-js-e2e --unitTestRunner none --bundler none --js` + ); + runCLI(`g @nx/playwright:configuration --project demo-js-e2e --js`); + ensurePlaywrightBrowsersInstallation(); + + const e2eResults = runCLI(`e2e demo-js-e2e`); + expect(e2eResults).toContain('Successfully ran target e2e for project'); + + const lintResults = runCLI(`lint demo-e2e`); + expect(lintResults).toContain('All files pass linting'); + }, + TEN_MINS_MS + ); +}); diff --git a/e2e/playwright/tsconfig.json b/e2e/playwright/tsconfig.json new file mode 100644 index 0000000000000..6d5abf8483200 --- /dev/null +++ b/e2e/playwright/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node", "jest"] + }, + "include": [], + "files": [], + "references": [ + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/e2e/playwright/tsconfig.spec.json b/e2e/playwright/tsconfig.spec.json new file mode 100644 index 0000000000000..1a24bfb0a1353 --- /dev/null +++ b/e2e/playwright/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.test.ts", + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/e2e/plugin/project.json b/e2e/plugin/project.json index 4dc98bec8998a..88c18ab5f0b19 100644 --- a/e2e/plugin/project.json +++ b/e2e/plugin/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/plugin", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["create-nx-plugin"] } diff --git a/e2e/plugin/src/nx-plugin.test.ts b/e2e/plugin/src/nx-plugin.test.ts index 13c5f07269680..bca4be24b3ebe 100644 --- a/e2e/plugin/src/nx-plugin.test.ts +++ b/e2e/plugin/src/nx-plugin.test.ts @@ -76,7 +76,6 @@ describe('Nx Plugin', () => { [`update-${version}`]: { version, description: `update-${version}`, - cli: `nx`, implementation: `./src/migrations/update-${version}/update-${version}`, }, }), diff --git a/e2e/react-core/project.json b/e2e/react-core/project.json index 45e531ced35df..f08fea409c85f 100644 --- a/e2e/react-core/project.json +++ b/e2e/react-core/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/react-core", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["react"] } diff --git a/e2e/react-core/src/react-package.test.ts b/e2e/react-core/src/react-package.test.ts index 17f33f546e70e..8a61dad360b07 100644 --- a/e2e/react-core/src/react-package.test.ts +++ b/e2e/react-core/src/react-package.test.ts @@ -119,9 +119,9 @@ describe('Build React libraries and apps', () => { runCLI(`build ${childLib}`); runCLI(`build ${childLib2}`); - checkFilesExist(`dist/libs/${childLib}/index.js`); + checkFilesExist(`dist/libs/${childLib}/index.esm.js`); - checkFilesExist(`dist/libs/${childLib2}/index.js`); + checkFilesExist(`dist/libs/${childLib2}/index.esm.js`); checkFilesExist(`dist/libs/${childLib}/assets/hello.txt`); checkFilesExist(`dist/libs/${childLib2}/README.md`); @@ -129,9 +129,9 @@ describe('Build React libraries and apps', () => { /* * 2. With dependencies */ - runCLI(`build ${parentLib}`); + runCLI(`build ${parentLib} --updateBuildableProjectDepsInPackageJson`); - checkFilesExist(`dist/libs/${parentLib}/index.js`); + checkFilesExist(`dist/libs/${parentLib}/index.esm.js`); const jsonFile = readJson(`dist/libs/${parentLib}/package.json`); expect(jsonFile.peerDependencies).toEqual( @@ -148,14 +148,14 @@ describe('Build React libraries and apps', () => { runCLI(`build ${parentLib} --skip-nx-cache`); - checkFilesExist(`dist/libs/${parentLib}/index.js`); - checkFilesExist(`dist/libs/${childLib}/index.js`); - checkFilesExist(`dist/libs/${childLib2}/index.js`); + checkFilesExist(`dist/libs/${parentLib}/index.esm.js`); + checkFilesExist(`dist/libs/${childLib}/index.esm.js`); + checkFilesExist(`dist/libs/${childLib2}/index.esm.js`); - expect(readFile(`dist/libs/${childLib}/index.js`)).not.toContain( + expect(readFile(`dist/libs/${childLib}/index.esm.js`)).not.toContain( 'react/jsx-dev-runtime' ); - expect(readFile(`dist/libs/${childLib}/index.js`)).toContain( + expect(readFile(`dist/libs/${childLib}/index.esm.js`)).toContain( 'react/jsx-runtime' ); }); @@ -172,14 +172,14 @@ export async function h() { return 'c'; } runCLI(`build ${childLib} --format cjs,esm`); - checkFilesExist(`dist/libs/${childLib}/index.cjs`); - checkFilesExist(`dist/libs/${childLib}/index.js`); + checkFilesExist(`dist/libs/${childLib}/index.cjs.js`); + checkFilesExist(`dist/libs/${childLib}/index.esm.js`); const cjsPackageSize = getSize( - tmpProjPath(`dist/libs/${childLib}/index.cjs`) + tmpProjPath(`dist/libs/${childLib}/index.cjs.js`) ); const esmPackageSize = getSize( - tmpProjPath(`dist/libs/${childLib}/index.js`) + tmpProjPath(`dist/libs/${childLib}/index.esm.js`) ); // This is a loose requirement that ESM should be smaller than CJS output. @@ -228,7 +228,7 @@ export async function h() { return 'c'; } // What we're testing runCLI(`build ${myLib}`); // Assertion - const content = readFile(`dist/libs/${myLib}/index.js`); + const content = readFile(`dist/libs/${myLib}/index.esm.js`); /** * Then check if the result contains this "promise" polyfill? diff --git a/e2e/react-extensions/project.json b/e2e/react-extensions/project.json index c2b16e92266eb..f67fb84c4e18f 100644 --- a/e2e/react-extensions/project.json +++ b/e2e/react-extensions/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/react-extensions", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["react"] } diff --git a/e2e/react-native/project.json b/e2e/react-native/project.json index d4824959940f5..2c6f1c02861a6 100644 --- a/e2e/react-native/project.json +++ b/e2e/react-native/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/react-native", "projectType": "application", "targets": { - "e2e-macos": {}, - "run-e2e-tests": {} + "e2e-macos": {} }, "implicitDependencies": ["react-native"] } diff --git a/e2e/react-native/src/react-native.test.ts b/e2e/react-native/src/react-native.test.ts index cae7ddc61ff0b..67286404b7c42 100644 --- a/e2e/react-native/src/react-native.test.ts +++ b/e2e/react-native/src/react-native.test.ts @@ -14,6 +14,7 @@ import { runCommandUntil, uniq, updateFile, + updateJson, } from '@nx/e2e/utils'; import { ChildProcess } from 'child_process'; import { join } from 'path'; @@ -25,6 +26,16 @@ describe('react native', () => { beforeAll(() => { proj = newProject(); + // we create empty preset above which skips creation of `production` named input + updateJson('nx.json', (nxJson) => { + nxJson.namedInputs = { + default: ['{projectRoot}/**/*', 'sharedGlobals'], + production: ['default'], + sharedGlobals: [], + }; + nxJson.targetDefaults.build.inputs = ['production', '^production']; + return nxJson; + }); runCLI( `generate @nx/react-native:application ${appName} --install=false --no-interactive` ); @@ -161,7 +172,7 @@ describe('react native', () => { ); expect(() => { runCLI(`build ${libName}`); - checkFilesExist(`dist/libs/${libName}/index.js`); + checkFilesExist(`dist/libs/${libName}/index.esm.js`); checkFilesExist(`dist/libs/${libName}/src/index.d.ts`); }).not.toThrow(); }); @@ -194,4 +205,21 @@ describe('react native', () => { }, }); }); + + it('should tsc app', async () => { + expect(() => { + const pmc = getPackageManagerCommand(); + runCommand( + `${pmc.runUninstalledPackage} tsc -p apps/${appName}/tsconfig.app.json` + ); + checkFilesExist( + `dist/out-tsc/apps/${appName}/src/main.js`, + `dist/out-tsc/apps/${appName}/src/main.d.ts`, + `dist/out-tsc/apps/${appName}/src/app/App.js`, + `dist/out-tsc/apps/${appName}/src/app/App.d.ts`, + `dist/out-tsc/libs/${libName}/src/index.js`, + `dist/out-tsc/libs/${libName}/src/index.d.ts` + ); + }).not.toThrow(); + }); }); diff --git a/e2e/rollup/project.json b/e2e/rollup/project.json index edf2df464a84e..995aa0f5edb16 100644 --- a/e2e/rollup/project.json +++ b/e2e/rollup/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/rollup", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["rollup", "js"] } diff --git a/e2e/rollup/src/rollup.test.ts b/e2e/rollup/src/rollup.test.ts index 85777bab98801..59f81d4d1c162 100644 --- a/e2e/rollup/src/rollup.test.ts +++ b/e2e/rollup/src/rollup.test.ts @@ -1,6 +1,8 @@ import { + checkFilesExist, cleanupProject, newProject, + readJson, rmDist, runCLI, runCommand, @@ -20,11 +22,19 @@ describe('Rollup Plugin', () => { // babel (default) runCLI( - `generate @nx/rollup:rollup-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` ); rmDist(); - runCLI(`build ${myPkg}`); - let output = runCommand(`node dist/libs/${myPkg}/index.cjs`); + runCLI(`build ${myPkg} --format=cjs,esm --generateExportsField`); + checkFilesExist(`dist/libs/${myPkg}/index.cjs.d.ts`); + expect(readJson(`dist/libs/${myPkg}/package.json`).exports).toEqual({ + '.': { + import: './index.esm.js', + default: './index.cjs.js', + }, + './package.json': './package.json', + }); + let output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`); expect(output).toMatch(/Hello/); updateProjectConfig(myPkg, (config) => { @@ -34,11 +44,11 @@ describe('Rollup Plugin', () => { // swc runCLI( - `generate @nx/rollup:rollup-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` ); rmDist(); runCLI(`build ${myPkg}`); - output = runCommand(`node dist/libs/${myPkg}/index.cjs`); + output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`); expect(output).toMatch(/Hello/); updateProjectConfig(myPkg, (config) => { @@ -48,14 +58,57 @@ describe('Rollup Plugin', () => { // tsc runCLI( - `generate @nx/rollup:rollup-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` ); rmDist(); runCLI(`build ${myPkg}`); - output = runCommand(`node dist/libs/${myPkg}/index.cjs`); + output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`); expect(output).toMatch(/Hello/); }, 500000); + it('should support additional entry-points', () => { + const myPkg = uniq('my-pkg'); + runCLI(`generate @nx/js:lib ${myPkg} --bundler=none`); + runCLI( + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` + ); + updateProjectConfig(myPkg, (config) => { + config.targets.build.options.format = ['cjs', 'esm']; + config.targets.build.options.generateExportsField = true; + config.targets.build.options.additionalEntryPoints = [ + `libs/${myPkg}/src/{foo,bar}.ts`, + ]; + return config; + }); + updateFile(`libs/${myPkg}/src/foo.ts`, `export const foo = 'foo';`); + updateFile(`libs/${myPkg}/src/bar.ts`, `export const bar = 'bar';`); + + runCLI(`build ${myPkg}`); + + checkFilesExist(`dist/libs/${myPkg}/index.esm.js`); + checkFilesExist(`dist/libs/${myPkg}/index.cjs.js`); + checkFilesExist(`dist/libs/${myPkg}/index.cjs.d.ts`); + checkFilesExist(`dist/libs/${myPkg}/foo.esm.js`); + checkFilesExist(`dist/libs/${myPkg}/foo.cjs.js`); + checkFilesExist(`dist/libs/${myPkg}/bar.esm.js`); + checkFilesExist(`dist/libs/${myPkg}/bar.cjs.js`); + expect(readJson(`dist/libs/${myPkg}/package.json`).exports).toEqual({ + './package.json': './package.json', + '.': { + import: './index.esm.js', + default: './index.cjs.js', + }, + './bar': { + import: './bar.esm.js', + default: './bar.cjs.js', + }, + './foo': { + import: './foo.esm.js', + default: './foo.cjs.js', + }, + }); + }); + it('should be able to build libs generated with @nx/js:lib --bundler rollup', () => { const jsLib = uniq('jslib'); runCLI(`generate @nx/js:lib ${jsLib} --bundler rollup`); diff --git a/e2e/storybook-angular/project.json b/e2e/storybook-angular/project.json index 543913e6b3097..70e055134e309 100644 --- a/e2e/storybook-angular/project.json +++ b/e2e/storybook-angular/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/storybook-angular", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["storybook"] } diff --git a/e2e/storybook-angular/src/storybook-angular.test.ts b/e2e/storybook-angular/src/storybook-angular.test.ts index 01c008d9d55bb..49b68a1366ee4 100644 --- a/e2e/storybook-angular/src/storybook-angular.test.ts +++ b/e2e/storybook-angular/src/storybook-angular.test.ts @@ -5,11 +5,8 @@ import { newProject, runCLI, runCommandUntil, - runCypressTests, - tmpProjPath, uniq, } from '@nx/e2e/utils'; -import { writeFileSync } from 'fs'; describe('Storybook executors for Angular', () => { const angularStorybookLib = uniq('test-ui-ng-lib'); @@ -17,7 +14,7 @@ describe('Storybook executors for Angular', () => { newProject(); runCLI(`g @nx/angular:library ${angularStorybookLib} --no-interactive`); runCLI( - `generate @nx/angular:storybook-configuration ${angularStorybookLib} --configureCypress --generateStories --generateCypressSpecs --no-interactive` + `generate @nx/angular:storybook-configuration ${angularStorybookLib} --generateStories --no-interactive` ); }); @@ -43,80 +40,4 @@ describe('Storybook executors for Angular', () => { checkFilesExist(`dist/storybook/${angularStorybookLib}/index.html`); }, 200_000); }); - - // However much I increase the timeout, this takes forever? - xdescribe('run cypress tests using storybook', () => { - it('should execute e2e tests using Cypress running against Storybook', async () => { - if (runCypressTests()) { - addTestButtonToUILib(angularStorybookLib); - writeFileSync( - tmpProjPath( - `apps/${angularStorybookLib}-e2e/src/e2e/test-button/test-button.component.cy.ts` - ), - ` - describe('${angularStorybookLib}, () => { - - it('should render the correct text', () => { - cy.visit( - '/iframe.html?id=testbuttoncomponent--primary&args=text:Click+me;color:#ddffdd;disabled:false;' - ) - cy.get('button').should('contain', 'Click me'); - cy.get('button').should('not.be.disabled'); - }); - - it('should adjust the controls', () => { - cy.visit( - '/iframe.html?id=testbuttoncomponent--primary&args=text:Click+me;color:#ddffdd;disabled:true;' - ) - cy.get('button').should('be.disabled'); - }); - }); - ` - ); - - const e2eResults = runCLI(`e2e ${angularStorybookLib}-e2e --no-watch`); - expect(e2eResults).toContain('All specs passed!'); - expect(await killPorts()).toBeTruthy(); - } - }, 1000_000); - }); }); - -function addTestButtonToUILib(libName: string): void { - runCLI( - `g @nx/angular:component test-button --project=${libName} --no-interactive` - ); - - writeFileSync( - tmpProjPath(`libs/${libName}/src/lib/test-button/test-button.component.ts`), - ` - import { Component, Input } from '@angular/core'; - - @Component({ - selector: 'proj-test-button', - templateUrl: './test-button.component.html', - styleUrls: ['./test-button.component.css'], - }) - export class TestButtonComponent { - @Input() text = 'Click me'; - @Input() color = '#ddffdd'; - @Input() disabled = false; - } - ` - ); - - writeFileSync( - tmpProjPath( - `libs/${libName}/src/lib/test-button/test-button.component.html` - ), - ` - - ` - ); -} diff --git a/e2e/storybook/project.json b/e2e/storybook/project.json index 5fa173962577b..93bb0f8c180aa 100644 --- a/e2e/storybook/project.json +++ b/e2e/storybook/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/storybook", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["storybook"] } diff --git a/e2e/storybook/src/storybook-nested.test.ts b/e2e/storybook/src/storybook-nested.test.ts index dc581dffcaa9d..a40db2abfcd3f 100644 --- a/e2e/storybook/src/storybook-nested.test.ts +++ b/e2e/storybook/src/storybook-nested.test.ts @@ -40,8 +40,8 @@ describe('Storybook generators and executors for standalone workspaces - using R describe('Storybook generated files', () => { it('should generate storybook files', () => { checkFilesExist( - '.storybook/main.js', - '.storybook/preview.js', + '.storybook/main.ts', + '.storybook/preview.ts', 'tsconfig.storybook.json' ); }); @@ -79,7 +79,7 @@ describe('Storybook generators and executors for standalone workspaces - using R writeFileSync( tmpProjPath(`src/app/test-button.tsx`), ` - import { MyLib } from '@${appName}/my-lib'; + import { MyLib } from 'my-lib'; export function TestButton() { return ( diff --git a/e2e/utils/command-utils.ts b/e2e/utils/command-utils.ts index 3e609435b2513..f87350f610353 100644 --- a/e2e/utils/command-utils.ts +++ b/e2e/utils/command-utils.ts @@ -6,6 +6,7 @@ import { getNpmMajorVersion, getPublishedVersion, getStrippedEnvironmentVariables, + getYarnMajorVersion, isVerboseE2ERun, } from './get-env-info'; import { TargetConfiguration } from '@nx/devkit'; @@ -119,6 +120,7 @@ export function getPackageManagerCommand({ runLerna: string; } { const npmMajorVersion = getNpmMajorVersion(); + const yarnMajorVersion = getYarnMajorVersion(path); const publishedVersion = getPublishedVersion(); const isYarnWorkspace = fileExists(join(path, 'package.json')) ? readJson('package.json').workspaces @@ -147,14 +149,14 @@ export function getPackageManagerCommand({ } create-nx-workspace@${publishedVersion}`, run: (script: string, args: string) => `yarn ${script} ${args}`, runNx: `yarn nx`, - runNxSilent: `yarn --silent nx`, + runNxSilent: +yarnMajorVersion >= 2 ? 'yarn nx' : `yarn --silent nx`, runUninstalledPackage: 'npx --yes', install: 'yarn', ciInstall: 'yarn --frozen-lockfile', addProd: isYarnWorkspace ? 'yarn add -W' : 'yarn add', addDev: isYarnWorkspace ? 'yarn add -DW' : 'yarn add -D', list: 'yarn list --pattern', - runLerna: `yarn --silent lerna`, + runLerna: +yarnMajorVersion >= 2 ? 'yarn lerna' : `yarn --silent lerna`, }, // Pnpm 3.5+ adds nx to pnpm: { diff --git a/e2e/utils/create-project-utils.ts b/e2e/utils/create-project-utils.ts index e38f554fa4696..45f6e55213ec7 100644 --- a/e2e/utils/create-project-utils.ts +++ b/e2e/utils/create-project-utils.ts @@ -72,6 +72,7 @@ export function newProject({ `@nx/next`, `@nx/node`, `@nx/plugin`, + `@nx/playwright`, `@nx/rollup`, `@nx/react`, `@nx/storybook`, @@ -201,11 +202,19 @@ export function runCreateWorkspace( command += ` ${extraArgs}`; } + if (isCI) { + command += ` --verbose`; + } + try { const create = execSync(`${command}${isVerbose() ? ' --verbose' : ''}`, { cwd, stdio: 'pipe', - env: { CI: 'true', ...process.env }, + env: { + CI: 'true', + NX_VERBOSE_LOGGING: isCI ? 'true' : 'false', + ...process.env, + }, encoding: 'utf-8', }); diff --git a/e2e/utils/get-env-info.ts b/e2e/utils/get-env-info.ts index c607ff0eea101..da3fc57361cbe 100644 --- a/e2e/utils/get-env-info.ts +++ b/e2e/utils/get-env-info.ts @@ -73,6 +73,22 @@ export function getNpmMajorVersion(): string { return npmMajorVersion; } +export function getYarnMajorVersion(path: string): string { + try { + // this fails if path is not yet created + const [yarnMajorVersion] = execSync(`yarn -v`, { + cwd: path, + encoding: 'utf-8', + }).split('.'); + return yarnMajorVersion; + } catch { + const [yarnMajorVersion] = execSync(`yarn -v`, { encoding: 'utf-8' }).split( + '.' + ); + return yarnMajorVersion; + } +} + export function getLatestLernaVersion(): string { const lernaVersion = execSync(`npm view lerna version`, { encoding: 'utf-8', @@ -111,6 +127,19 @@ export function ensureCypressInstallation() { } } +export function ensurePlaywrightBrowsersInstallation() { + execSync('npx playwright install --with-deps --force', { + stdio: isVerbose() ? 'inherit' : 'pipe', + encoding: 'utf-8', + cwd: tmpProjPath(), + }); + e2eConsoleLogger( + `Playwright browsers ${execSync('npx playwright --version') + .toString() + .trim()} installed.` + ); +} + export function getStrippedEnvironmentVariables() { return Object.fromEntries( Object.entries(process.env).filter(([key, value]) => { @@ -122,6 +151,10 @@ export function getStrippedEnvironmentVariables() { return false; } + if (key === 'JEST_WORKER_ID') { + return false; + } + return true; }) ); diff --git a/e2e/utils/global-setup.ts b/e2e/utils/global-setup.ts index f2a732b237709..5f78d7e7dbf42 100644 --- a/e2e/utils/global-setup.ts +++ b/e2e/utils/global-setup.ts @@ -24,8 +24,9 @@ export default async function (globalConfig: Config.ConfigGlobals) { !existsSync('./build') ) { console.log('Publishing packages to local registry'); + const publishVersion = process.env.PUBLISHED_VERSION ?? 'major'; await new Promise((res, rej) => { - const publishProcess = exec('pnpm nx-release --local major', { + const publishProcess = exec(`pnpm nx-release --local ${publishVersion}`, { env: process.env, }); let logs = Buffer.from(''); diff --git a/e2e/vite/project.json b/e2e/vite/project.json index 93ea588285aa3..06f2359776dfe 100644 --- a/e2e/vite/project.json +++ b/e2e/vite/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/vite", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["vite"] } diff --git a/e2e/vite/src/vite.test.ts b/e2e/vite/src/vite.test.ts index d1087fd689919..28ca5d8133c17 100644 --- a/e2e/vite/src/vite.test.ts +++ b/e2e/vite/src/vite.test.ts @@ -1,3 +1,4 @@ +import { names } from '@nx/devkit'; import { cleanupProject, createFile, @@ -240,6 +241,74 @@ describe('Vite Plugin', () => { 100_000; }); + describe('incremental building', () => { + const app = uniq('demo'); + const lib = uniq('my-lib'); + beforeAll(() => { + proj = newProject({ name: uniq('vite-incr-build') }); + runCLI(`generate @nx/react:app ${app} --bundler=vite --no-interactive`); + + // only this project will be directly used from dist + runCLI( + `generate @nx/react:lib ${lib}-buildable --unitTestRunner=none --bundler=vite --importPath="@acme/buildable" --no-interactive` + ); + + runCLI( + `generate @nx/react:lib ${lib} --unitTestRunner=none --bundler=none --importPath="@acme/non-buildable" --no-interactive` + ); + + // because the default js lib builds as cjs it cannot be loaded from dist + // so the paths plugin should always resolve to the libs source + runCLI( + `generate @nx/js:lib ${lib}-js --bundler=tsc --importPath="@acme/js-lib" --no-interactive` + ); + const buildableLibCmp = names(`${lib}-buildable`).className; + const nonBuildableLibCmp = names(lib).className; + const buildableJsLibFn = names(`${lib}-js`).propertyName; + + updateFile(`apps/${app}/src/app/app.tsx`, () => { + return `// eslint-disable-next-line @typescript-eslint/no-unused-vars +import styles from './app.module.css'; + +import NxWelcome from './nx-welcome'; +import { ${buildableLibCmp} } from '@acme/buildable'; +import { ${buildableJsLibFn} } from '@acme/js-lib'; +import { ${nonBuildableLibCmp} } from '@acme/non-buildable'; + +export function App() { + return ( +
+ <${buildableLibCmp} /> + <${nonBuildableLibCmp} /> +

{${buildableJsLibFn}()}

+ +
+ ); +} +export default App; +`; + }); + }); + + afterAll(() => { + cleanupProject(); + }); + + it('should build app from libs source', () => { + const results = runCLI(`build ${app} --buildLibsFromSource=true`); + expect(results).toContain('Successfully ran target build for project'); + // this should be more modules than build from dist + expect(results).toContain('40 modules transformed'); + }); + + it('should build app from libs dist', () => { + const results = runCLI(`build ${app} --buildLibsFromSource=false`); + expect(results).toContain('Successfully ran target build for project'); + // this should be less modules than building from source + expect(results).toContain('38 modules transformed'); + }); + }); + describe('should be able to create libs that use vitest', () => { const lib = uniq('my-lib'); beforeEach(() => { @@ -255,7 +324,6 @@ describe('Vite Plugin', () => { `Successfully ran target test for project ${lib}` ); - // TODO(caleb): run tests from project root and make sure they still work const nestedResults = await runCLIAsync(`test ${lib} --skip-nx-cache`, { cwd: `${tmpProjPath()}/libs/${lib}`, }); @@ -270,7 +338,7 @@ describe('Vite Plugin', () => { return `/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; - import viteTsConfigPaths from 'vite-tsconfig-paths'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ server: { @@ -279,9 +347,7 @@ describe('Vite Plugin', () => { }, plugins: [ react(), - viteTsConfigPaths({ - root: './', - }), + nxViteTsPaths() ], test: { globals: true, @@ -321,7 +387,8 @@ describe('Vite Plugin', () => { updateFile(`libs/${lib}/vite.config.ts`, () => { return `import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + export default defineConfig({ server: { @@ -330,9 +397,7 @@ export default defineConfig({ }, plugins: [ react(), - viteTsConfigPaths({ - root: './', - }), + nxViteTsPaths() ], test: { globals: true, diff --git a/e2e/web/project.json b/e2e/web/project.json index 616109787110e..d5bc86d7d972f 100644 --- a/e2e/web/project.json +++ b/e2e/web/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/web", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["web"] } diff --git a/e2e/web/src/web.test.ts b/e2e/web/src/web.test.ts index 7a8ce867e593b..34bb1e3e4a004 100644 --- a/e2e/web/src/web.test.ts +++ b/e2e/web/src/web.test.ts @@ -3,6 +3,7 @@ import { checkFilesExist, cleanupProject, createFile, + ensurePlaywrightBrowsersInstallation, isNotWindows, killPorts, listFiles, @@ -98,6 +99,26 @@ describe('Web Components Applications', () => { ); }, 500000); + it('should generate working playwright e2e app', async () => { + const appName = uniq('app'); + runCLI( + `generate @nx/web:app ${appName} --bundler=webpack --e2eTestRunner=playwright --no-interactive` + ); + + const lintE2eResults = runCLI(`lint ${appName}-e2e`); + + expect(lintE2eResults).toContain('All files pass linting.'); + + if (isNotWindows() && runCypressTests()) { + ensurePlaywrightBrowsersInstallation(); + const e2eResults = runCLI(`e2e ${appName}-e2e`); + expect(e2eResults).toContain( + `Successfully ran target e2e for project ${appName}-e2e` + ); + expect(await killPorts()).toBeTruthy(); + } + }, 500000); + it('should remove previous output before building', async () => { const appName = uniq('app'); const libName = uniq('lib'); @@ -125,7 +146,7 @@ describe('Web Components Applications', () => { checkFilesExist(`dist/apps/_should_not_remove.txt`); // Asset that React runtime is imported - expect(readFile(`dist/libs/${libName}/index.js`)).toMatch( + expect(readFile(`dist/libs/${libName}/index.esm.js`)).toMatch( /react\/jsx-runtime/ ); diff --git a/e2e/webpack/project.json b/e2e/webpack/project.json index 07cc297f74d08..14d8f86381cfd 100644 --- a/e2e/webpack/project.json +++ b/e2e/webpack/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/webpack", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["webpack"] } diff --git a/e2e/webpack/src/webpack.test.ts b/e2e/webpack/src/webpack.test.ts index 16073e79f84d5..b1d8a094868fe 100644 --- a/e2e/webpack/src/webpack.test.ts +++ b/e2e/webpack/src/webpack.test.ts @@ -19,7 +19,7 @@ describe('Webpack Plugin', () => { updateFile(`libs/${myPkg}/src/index.ts`, `console.log('Hello');\n`); runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` + `generate @nx/webpack:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` ); // Test `scriptType` later during during. @@ -52,7 +52,7 @@ module.exports = composePlugins(withNx(), (config) => { // swc runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` + `generate @nx/webpack:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` ); rmDist(); runCLI(`build ${myPkg}`); @@ -66,7 +66,7 @@ module.exports = composePlugins(withNx(), (config) => { // tsc runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` + `generate @nx/webpack:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` ); rmDist(); runCLI(`build ${myPkg}`); @@ -80,7 +80,7 @@ module.exports = composePlugins(withNx(), (config) => { updateFile(`libs/${myPkg}/src/index.ts`, `console.log('Hello');\n`); runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --compiler=babel --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` + `generate @nx/webpack:configuration ${myPkg} --target=node --compiler=babel --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` ); updateFile( diff --git a/e2e/workspace-create-npm/project.json b/e2e/workspace-create-npm/project.json index 0a105367b60fd..49c3ca6f63490 100644 --- a/e2e/workspace-create-npm/project.json +++ b/e2e/workspace-create-npm/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/workspace-create-npm", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["create-nx-workspace"] } diff --git a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts index f54ece8d56281..2a11dc1031cbb 100644 --- a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts +++ b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts @@ -37,6 +37,17 @@ describe('create-nx-workspace --preset=npm', () => { cleanupProject({ skipReset: true }); }); + it('should setup package-based workspace', () => { + const packageJson = readJson('package.json'); + expect(packageJson.dependencies).toEqual({}); + + if (getSelectedPackageManager() === 'pnpm') { + checkFilesExist('pnpm-workspace.yaml'); + } else { + expect(packageJson.workspaces).toEqual(['packages/*']); + } + }); + it('should add angular application', () => { packageInstall('@nx/angular', wsName); const appName = uniq('my-app'); diff --git a/e2e/workspace-create/project.json b/e2e/workspace-create/project.json index bc1c332c49715..529857fed2993 100644 --- a/e2e/workspace-create/project.json +++ b/e2e/workspace-create/project.json @@ -4,8 +4,7 @@ "sourceRoot": "e2e/workspace-create", "projectType": "application", "targets": { - "e2e": {}, - "run-e2e-tests": {} + "e2e": {} }, "implicitDependencies": ["create-nx-workspace"] } diff --git a/e2e/workspace-create/src/create-nx-plugin.test.ts b/e2e/workspace-create/src/create-nx-plugin.test.ts index 5348a90e4a238..299b2580c79f9 100644 --- a/e2e/workspace-create/src/create-nx-plugin.test.ts +++ b/e2e/workspace-create/src/create-nx-plugin.test.ts @@ -20,7 +20,7 @@ describe('create-nx-plugin', () => { runCreatePlugin(pluginName, { packageManager, - extraArgs: `--createPackageName='false'`, + extraArgs: `--createPackageName=false`, }); checkFilesExist( @@ -62,14 +62,14 @@ describe('create-nx-plugin', () => { runCLI(`build ${pluginName}`); checkFilesExist( - `dist/${pluginName}/package.json`, - `dist/${pluginName}/generators.json`, - `e2e/tests/${pluginName}.spec.ts` + `dist/packages/${pluginName}/package.json`, + `dist/packages/${pluginName}/generators.json`, + `packages/${pluginName}-e2e/tests/${pluginName}.spec.ts` ); runCLI(`build create-${pluginName}-package`); - checkFilesExist(`dist/create-${pluginName}-package/bin/index.js`); + checkFilesExist(`dist/packages/create-${pluginName}-package/bin/index.js`); - expect(() => runCLI(`e2e e2e`)).not.toThrow(); + expect(() => runCLI(`e2e ${pluginName}-e2e`)).not.toThrow(); }); }); diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index 8a85a39a520a5..fc78558f8b863 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -9,10 +9,12 @@ import { getSelectedPackageManager, packageManagerLockFile, readJson, + runCommand, runCreateWorkspace, uniq, } from '@nx/e2e/utils'; -import { existsSync, mkdirSync } from 'fs-extra'; +import { readFileSync } from 'fs'; +import { existsSync, mkdirSync, rmSync } from 'fs-extra'; describe('create-nx-workspace', () => { const packageManager = getSelectedPackageManager() || 'pnpm'; @@ -414,7 +416,7 @@ describe('create-nx-workspace', () => { }); }); -describe('create-nx-workspace custom parent folder', () => { +describe('create-nx-workspace parent folder', () => { const tmpDir = `${e2eCwd}/${uniq('with space')}`; const wsName = uniq('parent'); const packageManager = getSelectedPackageManager() || 'pnpm'; @@ -433,3 +435,59 @@ describe('create-nx-workspace custom parent folder', () => { expect(existsSync(`${tmpDir}/${wsName}/package.json`)).toBeTruthy(); }); }); + +describe('create-nx-workspace yarn berry', () => { + const tmpDir = `${e2eCwd}/${uniq('yarn-berry')}`; + let wsName: string; + + beforeAll(() => { + mkdirSync(tmpDir, { recursive: true }); + runCommand('corepack prepare yarn@stable --activate', { cwd: tmpDir }); + runCommand('yarn set version stable', { cwd: tmpDir }); + // previous command creates a package.json file which we don't want + rmSync(`${tmpDir}/package.json`); + process.env.YARN_ENABLE_IMMUTABLE_INSTALLS = 'false'; + }); + + afterEach(() => cleanupProject({ cwd: `${tmpDir}/${wsName}` })); + + it('should create a workspace with yarn berry', () => { + wsName = uniq('apps'); + + runCreateWorkspace(wsName, { + preset: 'apps', + packageManager: 'yarn', + cwd: tmpDir, + }); + + expect(existsSync(`${tmpDir}/${wsName}/.yarnrc.yml`)).toBeTruthy(); + expect( + readFileSync(`${tmpDir}/${wsName}/.yarnrc.yml`, { encoding: 'utf-8' }) + ).toMatchInlineSnapshot(` + "nodeLinker: node-modules + + yarnPath: .yarn/releases/yarn-3.6.1.cjs + " + `); + }); + + it('should create a js workspace with yarn berry', () => { + wsName = uniq('ts'); + + runCreateWorkspace(wsName, { + preset: 'ts', + packageManager: 'yarn', + cwd: tmpDir, + }); + + expect(existsSync(`${tmpDir}/${wsName}/.yarnrc.yml`)).toBeTruthy(); + expect( + readFileSync(`${tmpDir}/${wsName}/.yarnrc.yml`, { encoding: 'utf-8' }) + ).toMatchInlineSnapshot(` + "nodeLinker: node-modules + + yarnPath: .yarn/releases/yarn-3.6.1.cjs + " + `); + }); +}); diff --git a/graph/client/src/app/external-api.ts b/graph/client/src/app/external-api.ts index c6fa8f7f51451..0a02689800799 100644 --- a/graph/client/src/app/external-api.ts +++ b/graph/client/src/app/external-api.ts @@ -1,6 +1,7 @@ import { getRouter } from './get-router'; import { getProjectGraphService } from './machines/get-services'; import { ProjectGraphMachineEvents } from './feature-projects/machines/interfaces'; +import { getGraphService } from './machines/graph.service'; export class ExternalApi { _projectGraphService = getProjectGraphService(); @@ -13,6 +14,7 @@ export class ExternalApi { }); router = getRouter(); + graphService = getGraphService(); projectGraphService = { send: (event: ProjectGraphMachineEvents) => { @@ -20,10 +22,33 @@ export class ExternalApi { }, }; + private fileClickCallbackListeners: ((url: string) => void)[] = []; + private openProjectConfigCallbackListeners: (( + projectName: string + ) => void)[] = []; + private runTaskCallbackListeners: ((taskId: string) => void)[] = []; + get depGraphService() { return this.projectGraphService; } + constructor() { + this.graphService.listen((event) => { + if (event.type === 'FileLinkClick') { + const url = `${event.sourceRoot}/${event.file}`; + this.fileClickCallbackListeners.forEach((cb) => cb(url)); + } + if (event.type === 'ProjectOpenConfigClick') { + this.openProjectConfigCallbackListeners.forEach((cb) => + cb(event.projectName) + ); + } + if (event.type === 'RunTaskClick') { + this.runTaskCallbackListeners.forEach((cb) => cb(event.taskId)); + } + }); + } + focusProject(projectName: string) { this.router.navigate(`/projects/${encodeURIComponent(projectName)}`); } @@ -42,6 +67,16 @@ export class ExternalApi { window.appConfig.showExperimentalFeatures = false; } + registerFileClickCallback(callback: (url: string) => void) { + this.fileClickCallbackListeners.push(callback); + } + registerOpenProjectConfigCallback(callback: (projectName: string) => void) { + this.openProjectConfigCallbackListeners.push(callback); + } + registerRunTaskCallback(callback: (taskId: string) => void) { + this.runTaskCallbackListeners.push(callback); + } + private handleLegacyProjectGraphEvent(event: ProjectGraphMachineEvents) { switch (event.type) { case 'focusProject': diff --git a/graph/client/src/app/feature-projects/machines/project-graph.spec.ts b/graph/client/src/app/feature-projects/machines/project-graph.spec.ts index 69986d8e04ed2..d71cfe7eca2e2 100644 --- a/graph/client/src/app/feature-projects/machines/project-graph.spec.ts +++ b/graph/client/src/app/feature-projects/machines/project-graph.spec.ts @@ -7,6 +7,7 @@ import type { /* eslint-enable @nx/enforce-module-boundaries */ import { interpret } from 'xstate'; import { projectGraphMachine } from './project-graph.machine'; +import { AppConfig } from '../../interfaces'; export const mockProjects: ProjectGraphProjectNode[] = [ { @@ -96,7 +97,24 @@ export const mockDependencies: Record = { 'auth-lib': [], }; +const mockAppConfig: AppConfig = { + showDebugger: false, + showExperimentalFeatures: false, + workspaces: [ + { + id: 'local', + label: 'local', + projectGraphUrl: 'assets/project-graphs/e2e.json', + taskGraphUrl: 'assets/task-graphs/e2e.json', + }, + ], + defaultWorkspaceId: 'local', +}; + describe('dep-graph machine', () => { + beforeEach(() => { + window.appConfig = mockAppConfig; + }); describe('initGraph', () => { it('should set projects, dependencies, and workspaceLayout', () => { const result = projectGraphMachine.transition( diff --git a/graph/client/src/app/feature-projects/panels/collapse-edges-panel.stories.tsx b/graph/client/src/app/feature-projects/panels/collapse-edges-panel.stories.tsx index 4215a20561c46..40ca508fa8842 100644 --- a/graph/client/src/app/feature-projects/panels/collapse-edges-panel.stories.tsx +++ b/graph/client/src/app/feature-projects/panels/collapse-edges-panel.stories.tsx @@ -1,20 +1,20 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { CollapseEdgesPanel } from './collapse-edges-panel'; -export default { +const meta: Meta = { component: CollapseEdgesPanel, title: 'Project Graph/CollapseEdgesPanel', argTypes: { collapseEdges: Boolean, collapseEdgesChanged: { action: 'collapseEdgesChanged' }, }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - collapseEdges: false, +export const Primary: Story = { + args: { + collapseEdges: false, + }, }; diff --git a/graph/client/src/app/feature-projects/panels/rankdir-panel.stories.tsx b/graph/client/src/app/feature-projects/panels/rankdir-panel.stories.tsx index a643b5f71e1f4..374b4703c4094 100644 --- a/graph/client/src/app/feature-projects/panels/rankdir-panel.stories.tsx +++ b/graph/client/src/app/feature-projects/panels/rankdir-panel.stories.tsx @@ -1,12 +1,14 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import RankDirPanel from './rankdir-panel'; +import type { Meta, StoryObj } from '@storybook/react'; +import { RankdirPanel } from './rankdir-panel'; -export default { - component: RankDirPanel, - title: 'Project Graph/RankDirPanel', -} as ComponentMeta; +const meta: Meta = { + component: RankdirPanel, + title: 'Project Graph/RankdirPanel', +}; -const Template: ComponentStory = () => ; +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = {}; +export const Primary: Story = { + args: {}, +}; diff --git a/graph/client/src/app/feature-projects/panels/search-depth.stories.tsx b/graph/client/src/app/feature-projects/panels/search-depth.stories.tsx index 7c4dd825a35d7..3f656d5b9736b 100644 --- a/graph/client/src/app/feature-projects/panels/search-depth.stories.tsx +++ b/graph/client/src/app/feature-projects/panels/search-depth.stories.tsx @@ -1,7 +1,7 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { SearchDepth } from './search-depth'; -export default { +const meta: Meta = { component: SearchDepth, title: 'Project Graph/SearchDepth', argTypes: { @@ -11,14 +11,14 @@ export default { decrementDepthFilter: { action: 'decrementDepthFilter' }, incrementDepthFilter: { action: 'incrementDepthFilter' }, }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - searchDepthEnabled: false, - searchDepth: 1, +export const Primary: Story = { + args: { + searchDepthEnabled: false, + searchDepth: 1, + }, }; diff --git a/graph/client/src/app/feature-projects/panels/text-filter-panel.stories.tsx b/graph/client/src/app/feature-projects/panels/text-filter-panel.stories.tsx index df81c136a0db7..6bf47bef2319a 100644 --- a/graph/client/src/app/feature-projects/panels/text-filter-panel.stories.tsx +++ b/graph/client/src/app/feature-projects/panels/text-filter-panel.stories.tsx @@ -1,7 +1,7 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { TextFilterPanel } from './text-filter-panel'; -export default { +const meta: Meta = { component: TextFilterPanel, title: 'Project Graph/TextFilterPanel', argTypes: { @@ -13,14 +13,14 @@ export default { action: 'updateTextFilter', }, }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - includePath: false, - textFilter: 'some-lib', +export const Primary: Story = { + args: { + includePath: false, + textFilter: 'some-lib', + }, }; diff --git a/graph/client/src/app/feature-projects/panels/theme-panel.stories.tsx b/graph/client/src/app/feature-projects/panels/theme-panel.stories.tsx index c8d5e0b2e8e15..a9aacfcbe4a45 100644 --- a/graph/client/src/app/feature-projects/panels/theme-panel.stories.tsx +++ b/graph/client/src/app/feature-projects/panels/theme-panel.stories.tsx @@ -1,12 +1,14 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import ThemePanel from './theme-panel'; +import type { Meta, StoryObj } from '@storybook/react'; +import { ThemePanel } from './theme-panel'; -export default { +const meta: Meta = { component: ThemePanel, title: 'Project Graph/ThemePanel', -} as ComponentMeta; +}; -const Template: ComponentStory = () => ; +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = {}; +export const Primary: Story = { + args: {}, +}; diff --git a/graph/client/src/app/feature-projects/panels/tracing-panel.stories.tsx b/graph/client/src/app/feature-projects/panels/tracing-panel.stories.tsx index caa7682c9c5fd..a0a411fcfafcc 100644 --- a/graph/client/src/app/feature-projects/panels/tracing-panel.stories.tsx +++ b/graph/client/src/app/feature-projects/panels/tracing-panel.stories.tsx @@ -1,7 +1,7 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { TracingPanel } from './tracing-panel'; -export default { +const meta: Meta = { component: TracingPanel, title: 'Project Graph/TracingPanel', argTypes: { @@ -9,15 +9,15 @@ export default { resetStart: { action: 'resetStart' }, setAlgorithm: { action: 'setAlgorithm' }, }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - end: 'shared-ui', - start: 'store', - algorithm: 'shortest', +export const Primary: Story = { + args: { + end: 'shared-ui', + start: 'store', + algorithm: 'shortest', + }, }; diff --git a/graph/client/src/app/feature-tasks/task-list.stories.tsx b/graph/client/src/app/feature-tasks/task-list.stories.tsx index dc4aa853a5ff6..52c92e4f174b0 100644 --- a/graph/client/src/app/feature-tasks/task-list.stories.tsx +++ b/graph/client/src/app/feature-tasks/task-list.stories.tsx @@ -1,7 +1,7 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { TaskList, TaskListProps } from './task-list'; -const Story: ComponentMeta = { +const meta: Meta = { component: TaskList, title: 'TaskList', argTypes: { @@ -10,13 +10,10 @@ const Story: ComponentMeta = { }, }, }; -export default Story; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); const args: Partial = { projects: [ { @@ -40,7 +37,7 @@ const args: Partial = { root: 'apps/nested/app', targets: { build: { configurations: { production: {} } } }, files: [], - }, + } as any, }, { name: 'app1-e2e', @@ -49,7 +46,7 @@ const args: Partial = { root: 'apps/app1-e2e', targets: { e2e: { configurations: { production: {} } } }, files: [], - }, + } as any, }, { name: 'lib1', @@ -58,7 +55,7 @@ const args: Partial = { root: 'libs/lib1', targets: { lint: { configurations: { production: {} } } }, files: [], - }, + } as any, }, ], @@ -71,4 +68,7 @@ const args: Partial = { 'app1:build': 'Missing executor', }, }; -Primary.args = args; + +export const Primary: Story = { + args, +}; diff --git a/graph/client/src/app/hooks/get-project-graph-data-service.ts b/graph/client/src/app/hooks/get-project-graph-data-service.ts index 1f5e129478c5d..5d8f1213c5f60 100644 --- a/graph/client/src/app/hooks/get-project-graph-data-service.ts +++ b/graph/client/src/app/hooks/get-project-graph-data-service.ts @@ -7,11 +7,14 @@ let projectGraphService: ProjectGraphService; export function getProjectGraphDataService() { if (projectGraphService === undefined) { - if (window.environment === 'dev' || window.environment === 'nx-console') { + if (window.environment === 'dev') { projectGraphService = new FetchProjectGraphService(); } else if (window.environment === 'watch') { projectGraphService = new MockProjectGraphService(); - } else if (window.environment === 'release') { + } else if ( + window.environment === 'release' || + window.environment === 'nx-console' + ) { if (window.localMode === 'build') { projectGraphService = new LocalProjectGraphService(); } else { diff --git a/graph/client/src/app/machines/graph.service.ts b/graph/client/src/app/machines/graph.service.ts index e44fad5a765b5..fb0562cbba224 100644 --- a/graph/client/src/app/machines/graph.service.ts +++ b/graph/client/src/app/machines/graph.service.ts @@ -1,14 +1,16 @@ import { GraphService } from '@nx/graph/ui-graph'; import { selectValueByThemeStatic } from '../theme-resolver'; +import { getEnvironmentConfig } from '../hooks/use-environment-config'; let graphService: GraphService; export function getGraphService(): GraphService { + const environment = getEnvironmentConfig(); if (!graphService) { - const darkModeEnabled = selectValueByThemeStatic(true, false); graphService = new GraphService( 'cytoscape-graph', - selectValueByThemeStatic('dark', 'light') + selectValueByThemeStatic('dark', 'light'), + environment.environment === 'nx-console' ? 'nx-console' : undefined ); } diff --git a/graph/client/src/app/ui-components/checkbox-panel.stories.tsx b/graph/client/src/app/ui-components/checkbox-panel.stories.tsx index 9b89dd16c6aff..0fab62f2f4a7d 100644 --- a/graph/client/src/app/ui-components/checkbox-panel.stories.tsx +++ b/graph/client/src/app/ui-components/checkbox-panel.stories.tsx @@ -1,20 +1,20 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { CheckboxPanel } from './checkbox-panel'; -export default { +const meta: Meta = { component: CheckboxPanel, title: 'Shared/CheckboxPanel', argTypes: { checkChanged: { action: 'checkChanged' } }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - checked: false, - name: 'option-to-check', - label: 'Option to check', - description: 'You can check this option.', +export const Primary: Story = { + args: { + checked: false, + name: 'option-to-check', + label: 'Option to check', + description: 'You can check this option.', + }, }; diff --git a/graph/client/src/app/ui-components/debugger-panel.stories.tsx b/graph/client/src/app/ui-components/debugger-panel.stories.tsx index 661039dffc6a1..f3d45fed07646 100644 --- a/graph/client/src/app/ui-components/debugger-panel.stories.tsx +++ b/graph/client/src/app/ui-components/debugger-panel.stories.tsx @@ -1,36 +1,36 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { DebuggerPanel } from './debugger-panel'; -export default { +const meta: Meta = { component: DebuggerPanel, title: 'Shell/DebuggerPanel', argTypes: { selectedProjectChange: { action: 'projectGraphChange' }, }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - projectGraphs: [ - { - url: 'some-graph.json', - label: 'Some graph', - id: 'some-graph', - }, - { - url: 'another-graph.json', - label: 'Another graph', - id: 'another-graph', +export const Primary: Story = { + args: { + projects: [ + { + url: 'some-graph.json', + label: 'Some graph', + id: 'some-graph', + } as any, + { + url: 'another-graph.json', + label: 'Another graph', + id: 'another-graph', + } as any, + ], + selectedProject: 'another-graph', + lastPerfReport: { + numEdges: 20, + numNodes: 10, + renderTime: 500, }, - ], - selectedProjectGraph: 'another-graph', - lastPerfReport: { - numEdges: 20, - numNodes: 10, - renderTime: 500, }, }; diff --git a/graph/client/src/app/ui-components/focused-project-panel.stories.tsx b/graph/client/src/app/ui-components/focused-project-panel.stories.tsx index 43eef8a748f25..0fb586ab5cbf9 100644 --- a/graph/client/src/app/ui-components/focused-project-panel.stories.tsx +++ b/graph/client/src/app/ui-components/focused-project-panel.stories.tsx @@ -1,17 +1,17 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { FocusedPanel } from './focused-panel'; -export default { +const meta: Meta = { component: FocusedPanel, title: 'Project Graph/FocusedProjectPanel', argTypes: { resetFocus: { action: 'resetFocus' } }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - focusedProject: 'store', +export const Primary: Story = { + args: { + focusedLabel: 'store', + }, }; diff --git a/graph/client/src/app/ui-components/show-hide-all.stories.tsx b/graph/client/src/app/ui-components/show-hide-all.stories.tsx index f694e90d54c88..a92b804a6fc51 100644 --- a/graph/client/src/app/ui-components/show-hide-all.stories.tsx +++ b/graph/client/src/app/ui-components/show-hide-all.stories.tsx @@ -1,7 +1,7 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { ShowHideAll } from './show-hide-all'; -export default { +const meta: Meta = { component: ShowHideAll, title: 'Project Graph/ShowHideAllProjects', argTypes: { @@ -9,18 +9,19 @@ export default { showAffected: { action: 'showAffectedProjects' }, showAll: { action: 'showAllProjects' }, }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - hasAffectedProjects: false, +export const Primary: Story = { + args: { + hasAffected: false, + }, }; -export const Affected = Template.bind({}); -Affected.args = { - hasAffectedProjects: true, +export const Affected: Story = { + args: { + hasAffected: true, + }, }; diff --git a/graph/client/tailwind.config.js b/graph/client/tailwind.config.js index a130bfceccd48..18a8d985ec32a 100644 --- a/graph/client/tailwind.config.js +++ b/graph/client/tailwind.config.js @@ -36,5 +36,10 @@ module.exports = { translate: ['group-hover'], }, }, - plugins: [require('@tailwindcss/typography')], + plugins: [ + require('@tailwindcss/typography'), + require('@tailwindcss/forms')({ + strategy: 'class', + }), + ], }; diff --git a/graph/ui-components/.storybook/preview.js b/graph/ui-components/.storybook/preview.js index b569e15f753cb..71009fbf6b882 100644 --- a/graph/ui-components/.storybook/preview.js +++ b/graph/ui-components/.storybook/preview.js @@ -1,3 +1,3 @@ -import 'graph-client/.storybook/tailwind-imports.css'; +import 'graph/client/.storybook/tailwind-imports.css'; export const parameters = {}; diff --git a/graph/ui-components/src/lib/debounced-text-input.stories.tsx b/graph/ui-components/src/lib/debounced-text-input.stories.tsx index d66680a451daf..785ac52ff4557 100644 --- a/graph/ui-components/src/lib/debounced-text-input.stories.tsx +++ b/graph/ui-components/src/lib/debounced-text-input.stories.tsx @@ -1,7 +1,7 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { DebouncedTextInput } from './debounced-text-input'; -const Story: ComponentMeta = { +const meta: Meta = { component: DebouncedTextInput, title: 'Shared/DebouncedTextInput', argTypes: { @@ -13,14 +13,13 @@ const Story: ComponentMeta = { }, }, }; -export default Story; -const Template: ComponentStory = (args) => ( - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = { - initialText: '', - placeholderText: '', +export const Primary: Story = { + args: { + initialText: '', + placeholderText: '', + }, }; diff --git a/graph/ui-components/src/lib/dropdown.stories.tsx b/graph/ui-components/src/lib/dropdown.stories.tsx index 523be59a72431..b7d9d64d17c8c 100644 --- a/graph/ui-components/src/lib/dropdown.stories.tsx +++ b/graph/ui-components/src/lib/dropdown.stories.tsx @@ -1,20 +1,22 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { Dropdown } from './dropdown'; -export default { +const meta: Meta = { component: Dropdown, title: 'Shared/Dropdown', argTypes: { onChange: { action: 'onChange' }, }, -} as ComponentMeta; +}; -const Template: ComponentStory = (args) => ( - - - - -); +export default meta; +type Story = StoryObj; -export const Primary = Template.bind({}); -Primary.args = {}; +export const Primary: Story = { + render: () => ( + + + + + ), +}; diff --git a/graph/ui-components/src/lib/dropdown.tsx b/graph/ui-components/src/lib/dropdown.tsx index 19d0e6fef065d..f7a1d8323dabe 100644 --- a/graph/ui-components/src/lib/dropdown.tsx +++ b/graph/ui-components/src/lib/dropdown.tsx @@ -9,7 +9,7 @@ export function Dropdown(props: DropdownProps) { const { className, children, ...rest } = props; return ( setSearchTerm(event.target.value)} + onKeyDown={(event) => { + if (event.keyCode === 13 || event.key === 'Enter') { + handleSubmit(); + } + }} + type="search" + /> + + + {loading ? ( +
+

Thinking...

+
+ ) : null} + {finalResult && !error ? ( + <> +
+ {finalResult} +
+
+ + +
+ + ) : null} + {error ?
There was an error: {error['message']}
: null} + + ); +} + +export default FeatureAi; diff --git a/nx-dev/feature-ai/tsconfig.json b/nx-dev/feature-ai/tsconfig.json new file mode 100644 index 0000000000000..3230750a884f7 --- /dev/null +++ b/nx-dev/feature-ai/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/nx-dev/feature-ai/tsconfig.lib.json b/nx-dev/feature-ai/tsconfig.lib.json new file mode 100644 index 0000000000000..cccfe3f7d83d9 --- /dev/null +++ b/nx-dev/feature-ai/tsconfig.lib.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node"], + "lib": ["dom"] + }, + "files": [ + "../../node_modules/@nx/react/typings/cssmodule.d.ts", + "../../node_modules/@nx/react/typings/image.d.ts" + ], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "jest.config.ts" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/nx-dev/feature-ai/tsconfig.spec.json b/nx-dev/feature-ai/tsconfig.spec.json new file mode 100644 index 0000000000000..46f9467f3bd81 --- /dev/null +++ b/nx-dev/feature-ai/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/nx-dev/feature-analytics/src/lib/google-analytics.ts b/nx-dev/feature-analytics/src/lib/google-analytics.ts index 01362efa6e2d2..bfca9c46385ab 100644 --- a/nx-dev/feature-analytics/src/lib/google-analytics.ts +++ b/nx-dev/feature-analytics/src/lib/google-analytics.ts @@ -26,13 +26,15 @@ export function sendCustomEvent( action: string, category: string, label: string, - value?: number + value?: number, + customObject?: Record ): void { try { gtag('event', action, { event_category: category, event_label: label, value, + ...customObject, }); } catch (error) { throw new Error(`Cannot send Google Tag event: ${error}`); diff --git a/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx b/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx index f11eea3e17085..b784f689bb0c9 100644 --- a/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx +++ b/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx @@ -4,7 +4,7 @@ import { ProcessedDocument, RelatedDocument, } from '@nx/nx-dev/models-document'; -import { Breadcrumbs, Footer } from '@nx/nx-dev/ui-common'; +import { Breadcrumbs, Footer, GitHubStarWidget } from '@nx/nx-dev/ui-common'; import { renderMarkdown } from '@nx/nx-dev/ui-markdoc'; import { NextSeo } from 'next-seo'; import { useRouter } from 'next/router'; @@ -15,14 +15,18 @@ import { collectHeadings, TableOfContents } from './table-of-contents'; export function DocViewer({ document, relatedDocuments, + widgetData, }: { document: ProcessedDocument; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); - const isIntroPage = + const hideTableOfContent = router.asPath.includes('/getting-started/intro') || - router.asPath.includes('/plugins/intro/getting-started'); + router.asPath.includes('/extending-nx/intro/getting-started') || + router.asPath.includes('/packages/devkit') || + router.asPath.includes('/reference/glossary'); const ref = useRef(null); const { metadata, node, treeNode } = renderMarkdown( @@ -92,12 +96,12 @@ export function DocViewer({ data-document="main" className={cx( 'prose prose-slate dark:prose-invert w-full max-w-none 2xl:max-w-4xl', - { 'xl:max-w-2xl': !isIntroPage } + { 'xl:max-w-2xl': !hideTableOfContent } )} > {vm.content} - {!isIntroPage && ( + {!hideTableOfContent && ( )} diff --git a/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx b/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx index 5428e884bdc8e..24bdabeb908ab 100644 --- a/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx +++ b/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx @@ -39,10 +39,12 @@ export function TableOfContents({ elementRef, headings, path, + children, }: { elementRef: any; headings: Heading[]; path: string; + children: React.ReactNode; }): JSX.Element { const headingLevelTargets: number[] = [1, 2, 3]; // matching to: H1, H2, H3... const items = headings.filter( @@ -60,32 +62,35 @@ export function TableOfContents({ ); return ( - + <> + +
{children}
+ ); } diff --git a/nx-dev/feature-package-schema-viewer/src/lib/ui/package-reference.tsx b/nx-dev/feature-package-schema-viewer/src/lib/ui/package-reference.tsx index 049d92d48617c..05293e326e74c 100644 --- a/nx-dev/feature-package-schema-viewer/src/lib/ui/package-reference.tsx +++ b/nx-dev/feature-package-schema-viewer/src/lib/ui/package-reference.tsx @@ -124,7 +124,7 @@ function EmptyList({
  • diff --git a/nx-dev/feature-search/src/lib/algolia-search.global.css b/nx-dev/feature-search/src/lib/algolia-search.global.css index a7bac510ac54e..bdcccdbe01ee1 100644 --- a/nx-dev/feature-search/src/lib/algolia-search.global.css +++ b/nx-dev/feature-search/src/lib/algolia-search.global.css @@ -38,7 +38,7 @@ body .DocSearch-Container { .DocSearch-SearchBar { z-index: 1; padding: 0 1rem; - @apply relative flex flex-none items-center border-b border-slate-100 dark:border-slate-800; + @apply relative flex flex-none items-center border-b border-slate-200 dark:border-slate-800; } .DocSearch-Form { @@ -74,7 +74,7 @@ body .DocSearch-Container { .DocSearch-Hit > a { position: relative; font-size: 0.875rem; - @apply border-b border-slate-100 dark:border-slate-800; + @apply border-b border-slate-200 dark:border-slate-800; } .DocSearch-Hit--Result { @@ -132,7 +132,7 @@ body .DocSearch-Container { font-size: 0; border-radius: 0.375rem; padding: 0.25rem 0.375rem; - @apply border border-slate-900/5 hover:border-slate-900/10 dark:border-slate-100/10 dark:hover:border-slate-100/20; + @apply border border-slate-900/5 hover:border-slate-900/10 dark:border-slate-200/10 dark:hover:border-slate-200/20; width: 1.75rem; height: 1.5rem; /* esc icon */ @@ -255,7 +255,7 @@ body .DocSearch-Container { } .DocSearch-Hit:first-child > a { - @apply border-t border-slate-100 dark:border-slate-800; + @apply border-t border-slate-200 dark:border-slate-800; } .DocSearch-Hit--Result { @@ -296,7 +296,7 @@ body .DocSearch-Container { } .DocSearch-Footer { - @apply flex flex-none justify-end border-t border-slate-100 py-4 px-6 dark:border-slate-800; + @apply flex flex-none justify-end border-t border-slate-200 py-4 px-6 dark:border-slate-800; } .DocSearch-Commands { @@ -435,5 +435,5 @@ body .DocSearch-Container { } .DocSearch-Hit-action + .DocSearch-Hit-action { - @apply ml-3 border-l border-slate-100 pl-3 dark:border-slate-800; + @apply ml-3 border-l border-slate-200 pl-3 dark:border-slate-800; } diff --git a/nx-dev/feature-search/src/lib/algolia-search.tsx b/nx-dev/feature-search/src/lib/algolia-search.tsx index 1ce1304a27589..1010abe7098c0 100644 --- a/nx-dev/feature-search/src/lib/algolia-search.tsx +++ b/nx-dev/feature-search/src/lib/algolia-search.tsx @@ -114,7 +114,7 @@ export function AlgoliaSearch({ > Press diff --git a/nx-dev/models-document/src/lib/related-documents.utils.ts b/nx-dev/models-document/src/lib/related-documents.utils.ts index 7b3fe243c5ce5..cc06753e34dfe 100644 --- a/nx-dev/models-document/src/lib/related-documents.utils.ts +++ b/nx-dev/models-document/src/lib/related-documents.utils.ts @@ -17,7 +17,7 @@ export function categorizeRelatedDocuments( { id: 'concepts', name: 'Concepts', - matchers: ['/concepts/', '/more-concepts/'], + matchers: ['/concepts/', '/concepts/more-concepts/'], relatedDocuments: [], }, { diff --git a/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts b/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts index adac08ba2b22a..4a496882152cf 100644 --- a/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts +++ b/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts @@ -36,7 +36,7 @@ describe('nx-dev: Nx Cloud section', () => { path: '/nx-cloud/account/encryption', }, { - title: 'Running Nx Cloud on Prem', + title: 'Running Nx Cloud Enterprise', path: '/nx-cloud/private-cloud/get-started', }, { @@ -51,6 +51,10 @@ describe('nx-dev: Nx Cloud section', () => { title: 'GitLab Auth', path: '/nx-cloud/private-cloud/auth-gitlab', }, + { + title: 'Setting up a dedicated NxCloud VM', + path: '/nx-cloud/private-cloud/ami-setup', + }, { title: 'BitBucket Auth', path: '/nx-cloud/private-cloud/auth-bitbucket', diff --git a/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts b/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts index 09fabfffe0ebe..e3cccf8da9764 100644 --- a/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts +++ b/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts @@ -164,8 +164,8 @@ describe('nx-dev: Packages Section', () => { { title: '@nx/jest', path: '/packages/jest' }, { title: '@nx/jest:init', path: '/packages/jest/generators/init' }, { - title: '@nx/jest:jest-project', - path: '/packages/jest/generators/jest-project', + title: '@nx/jest:configuration', + path: '/packages/jest/generators/configuration', }, { title: '@nx/jest', path: '/packages/jest/executors/jest' }, { title: '@nx/js', path: '/packages/js' }, diff --git a/nx-dev/nx-dev-e2e/src/e2e/recipes.cy.ts b/nx-dev/nx-dev-e2e/src/e2e/recipes.cy.ts index a0da574041c9c..15e3357de5b8d 100644 --- a/nx-dev/nx-dev-e2e/src/e2e/recipes.cy.ts +++ b/nx-dev/nx-dev-e2e/src/e2e/recipes.cy.ts @@ -4,7 +4,7 @@ describe('nx-dev: Recipes pages', () => { it('should list related recipes based on tags', () => { const { map, uniq } = Cypress._; - cy.visit('/recipes/deployment/deno-deploy'); + cy.visit('/recipes/other/deno-deploy'); // All text content has to be different cy.get('[data-document="related"] > article > ul > li').should(($list) => { diff --git a/nx-dev/nx-dev/lib/githubStars.api.ts b/nx-dev/nx-dev/lib/githubStars.api.ts new file mode 100644 index 0000000000000..329709ad51525 --- /dev/null +++ b/nx-dev/nx-dev/lib/githubStars.api.ts @@ -0,0 +1,33 @@ +import { Octokit } from 'octokit'; + +let cachedGithubStarCountPromise: null | Promise = null; + +export async function fetchGithubStarCount() { + if (cachedGithubStarCountPromise !== null) { + // If the promise is in the cache, return it directly + return cachedGithubStarCountPromise; + } + + cachedGithubStarCountPromise = (async () => { + try { + const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }); + const responseData = await octokit.request('GET /repos/{owner}/{repo}', { + owner: 'nrwl', + repo: 'nx', + headers: { + 'X-GitHub-Api-Version': '2022-11-28', + }, + retry: { enabled: false }, + throttle: { + enabled: true, + }, + }); + + return responseData.data.stargazers_count; + } catch (e) { + return 0; // fallback, will hide GitHub star widget + } + })(); + + return cachedGithubStarCountPromise; +} diff --git a/nx-dev/nx-dev/lib/plugins.api.ts b/nx-dev/nx-dev/lib/plugins.api.ts index a969352b72e36..c4c3e11d8c1b8 100644 --- a/nx-dev/nx-dev/lib/plugins.api.ts +++ b/nx-dev/nx-dev/lib/plugins.api.ts @@ -1,9 +1,9 @@ import { DocumentsApi } from '@nx/nx-dev/data-access-documents/node-only'; -import documents from '../public/documentation/generated/manifests/plugins.json'; +import documents from '../public/documentation/generated/manifests/extending-nx.json'; import { tagsApi } from './tags.api'; export const nxPluginsApi = new DocumentsApi({ - id: 'plugins', + id: 'extending-nx', manifest: documents, prefix: '', publicDocsRoot: 'public/documentation', diff --git a/nx-dev/nx-dev/next-sitemap.config.js b/nx-dev/nx-dev/next-sitemap.config.js index 00aefe0cdf13c..34b985c514e11 100644 --- a/nx-dev/nx-dev/next-sitemap.config.js +++ b/nx-dev/nx-dev/next-sitemap.config.js @@ -3,6 +3,7 @@ const path = require('path'); module.exports = { siteUrl: process.env.SITE_URL || 'https://nx.dev', generateRobotsTxt: true, + exclude: ['/ai'], sourceDir: path.resolve(__dirname, '../../dist/nx-dev/nx-dev/.next'), outDir: path.resolve(__dirname, '../../dist/nx-dev/nx-dev/public'), }; diff --git a/nx-dev/nx-dev/next.config.js b/nx-dev/nx-dev/next.config.js index 71805642782a6..2880cb7382d74 100644 --- a/nx-dev/nx-dev/next.config.js +++ b/nx-dev/nx-dev/next.config.js @@ -28,175 +28,17 @@ module.exports = withNx({ async redirects() { const rules = []; - // Tutorials - for (let s of Object.keys(redirectRules.tutorialRedirects)) { - rules.push({ - source: s, - destination: redirectRules.tutorialRedirects[s], - permanent: true, - }); + // Apply all the redirects from the redirect-rules.js file + for (const section of Object.keys(redirectRules)) { + for (const source of Object.keys(redirectRules[section])) { + rules.push({ + source: source, + destination: redirectRules[section][source], + permanent: true, + }); + } } - // Storybook - rules.push({ - source: '/(l|latest)/(r|react)/storybook/overview', - destination: '/storybook/overview-react', - permanent: true, - }); - rules.push({ - source: '/(l|latest)/(a|angular)/storybook/overview', - destination: '/storybook/overview-angular', - permanent: true, - }); - rules.push({ - source: '/(l|latest)/(a|angular|r|react)/storybook/executors', - destination: '/storybook/executors-storybook', - permanent: true, - }); - - // Nx Console - rules.push({ - source: '/nx-console', - destination: '/using-nx/console', - permanent: true, - }); - rules.push({ - source: '/(l|latest)/(a|angular)/storybook/overview', - destination: '/storybook/overview-angular', - permanent: true, - }); - rules.push({ - source: '/(l|latest)/(a|angular|r|react)/storybook/executors', - destination: '/storybook/executors-storybook', - permanent: true, - }); - - // Customs - for (let s of Object.keys(redirectRules.guideUrls)) { - rules.push({ - source: `/l/n${s}`, - destination: redirectRules.guideUrls[s], - permanent: true, - }); - - rules.push({ - source: `/l/r${s}`, - destination: redirectRules.guideUrls[s], - permanent: true, - }); - - rules.push({ - source: `/l/a${s}`, - destination: redirectRules.guideUrls[s], - permanent: true, - }); - - rules.push({ - source: s, - destination: redirectRules.guideUrls[s], - permanent: true, - }); - } - - // Generic, catch-all - rules.push({ - source: '/(l|latest|p|previous)/(a|angular|r|react|n|node)/:path*', - destination: '/:path*', - permanent: true, - }); - rules.push({ - source: '/(l|latest|p|previous)/:path*', - destination: '/:path*', - permanent: true, - }); - rules.push({ - source: '/(a|angular|r|react|n|node)/:path*', - destination: '/:path*', - permanent: true, - }); - - // Schemas (generators & executors) - for (let s of Object.keys(redirectRules.schemaUrls)) { - rules.push({ - source: s, - destination: redirectRules.schemaUrls[s], - permanent: true, - }); - } - - // Api overviews - for (let s of Object.keys(redirectRules.overviewUrls)) { - rules.push({ - source: s, - destination: redirectRules.overviewUrls[s], - permanent: true, - }); - } - // Api CLI redirection to Nx - for (let s of Object.keys(redirectRules.cliUrls)) { - rules.push({ - source: s, - destination: redirectRules.cliUrls[s], - permanent: true, - }); - } - - // Diataxis doc restructure - for (let s of Object.keys(redirectRules.diataxis)) { - rules.push({ - source: s, - destination: redirectRules.diataxis[s], - permanent: true, - }); - } - // Recipes doc restructure - for (let s of Object.keys(redirectRules.recipesUrls)) { - rules.push({ - source: s, - destination: redirectRules.recipesUrls[s], - permanent: true, - }); - } - // Nx Cloud restructure - for (let s of Object.keys(redirectRules.nxCloudUrls)) { - rules.push({ - source: s, - destination: redirectRules.nxCloudUrls[s], - permanent: true, - }); - } - // Tutorials / Getting started - for (let s of Object.keys(redirectRules.conceptUrls)) { - rules.push({ - source: s, - destination: redirectRules.conceptUrls[s], - permanent: true, - }); - } - - // Packages Indexes - for (let s of Object.keys(redirectRules.packagesIndexes)) { - rules.push({ - source: s, - destination: redirectRules.packagesIndexes[s], - permanent: true, - }); - } - // Packages Documents - for (let s of Object.keys(redirectRules.packagesDocuments)) { - rules.push({ - source: s, - destination: redirectRules.packagesDocuments[s], - permanent: true, - }); - } - - // Docs - rules.push({ - source: '/docs', - destination: '/getting-started/intro', - permanent: true, - }); return rules; }, }); diff --git a/nx-dev/nx-dev/pages/[...segments].tsx b/nx-dev/nx-dev/pages/[...segments].tsx index dd53cf1e9a0fe..236a10d22e961 100644 --- a/nx-dev/nx-dev/pages/[...segments].tsx +++ b/nx-dev/nx-dev/pages/[...segments].tsx @@ -1,7 +1,7 @@ import { getBasicNxSection } from '@nx/nx-dev/data-access-menu'; import { DocViewer } from '@nx/nx-dev/feature-doc-viewer'; import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document'; -import { Menu, MenuItem } from '@nx/nx-dev/models-menu'; +import { MenuItem } from '@nx/nx-dev/models-menu'; import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common'; import { GetStaticPaths, GetStaticProps } from 'next'; import { useRouter } from 'next/router'; @@ -10,15 +10,18 @@ import { menusApi } from '../lib/menus.api'; import { useNavToggle } from '../lib/navigation-toggle.effect'; import { nxDocumentationApi } from '../lib/nx.api'; import { tagsApi } from '../lib/tags.api'; +import { fetchGithubStarCount } from '../lib/githubStars.api'; export default function NxDocumentation({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -40,16 +43,8 @@ export default function NxDocumentation({ return () => router.events.off('routeChangeComplete', handleRouteChange); }, [router, wrapperElement]); - const vm: { - document: ProcessedDocument; - menu: Menu; - relatedDocuments: RelatedDocument[]; - } = { - document, - menu: { - sections: [getBasicNxSection(menu)], - }, - relatedDocuments, + const menuWithSections = { + sections: [getBasicNxSection(menu)], }; return ( @@ -62,7 +57,7 @@ export default function NxDocumentation({ role="main" className="flex h-full flex-1 overflow-y-hidden" > - +
    @@ -80,12 +76,7 @@ export default function NxDocumentation({ } export const getStaticPaths: GetStaticPaths = () => { - const reservedPaths = [ - '/recipes', - '/nx-cloud', - '/packages', - '/reference/changelog', - ]; + const reservedPaths = ['/nx-cloud', '/packages', '/changelog']; return { paths: nxDocumentationApi .getSlugsStaticDocumentPaths() @@ -105,6 +96,9 @@ export const getStaticProps: GetStaticProps = async ({ return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + params.segments.join('/')), // Remove currently displayed item diff --git a/nx-dev/nx-dev/pages/ai/index.tsx b/nx-dev/nx-dev/pages/ai/index.tsx new file mode 100644 index 0000000000000..1f55df54c8cdf --- /dev/null +++ b/nx-dev/nx-dev/pages/ai/index.tsx @@ -0,0 +1,32 @@ +import { DocumentationHeader } from '@nx/nx-dev/ui-common'; +import { FeatureAi } from '@nx/nx-dev/feature-ai'; +import { useNavToggle } from '../../lib/navigation-toggle.effect'; +import { NextSeo } from 'next-seo'; + +export default function AiDocs(): JSX.Element { + const { toggleNav, navIsOpen } = useNavToggle(); + return ( + <> + +
    +
    + +
    +
    + +
    +
    + + ); +} diff --git a/nx-dev/nx-dev/pages/reference/changelog.tsx b/nx-dev/nx-dev/pages/changelog.tsx similarity index 93% rename from nx-dev/nx-dev/pages/reference/changelog.tsx rename to nx-dev/nx-dev/pages/changelog.tsx index 8df1e75b21ada..23d2e02286883 100644 --- a/nx-dev/nx-dev/pages/reference/changelog.tsx +++ b/nx-dev/nx-dev/pages/changelog.tsx @@ -1,4 +1,4 @@ -import { TagIcon } from '@heroicons/react/24/outline'; +import { LinkIcon, TagIcon } from '@heroicons/react/24/outline'; import { Breadcrumbs, DocumentationHeader, @@ -11,9 +11,9 @@ import { NextSeo } from 'next-seo'; import { useRouter } from 'next/router'; import { Octokit } from 'octokit'; import { compare, parse } from 'semver'; -import { changeLogApi } from '../../lib/changelog.api'; -import { useNavToggle } from '../../lib/navigation-toggle.effect'; -import { menusApi } from '../../lib/menus.api'; +import { changeLogApi } from '../lib/changelog.api'; +import { useNavToggle } from '../lib/navigation-toggle.effect'; +import { menusApi } from '../lib/menus.api'; import { MenuItem } from '@nx/nx-dev/models-menu'; import { getBasicNxSection } from '@nx/nx-dev/data-access-menu'; @@ -188,7 +188,7 @@ export default function Changelog(props: ChangeLogProps): JSX.Element { return entry; }); const convertToDate = (invalidDate) => - new Date(invalidDate.replace(/(nd|th|rd)/g, '')); + new Date(invalidDate.replace(/(nd|th|rd|st)/g, '')); const { toggleNav, navIsOpen } = useNavToggle(); const menu = { @@ -251,7 +251,10 @@ export default function Changelog(props: ChangeLogProps): JSX.Element {
    -
    +

    {' '} v{changelog.version} +

    - Talks from the Nx & Nx Cloud teams and selected speakers from - the community. + Nx Conf 2023 is a conference featuring members of the Nx & Nx + Cloud team and the community. Join us as we share our ideas + and expertise about monorepos and making development faster, + more scalable, and more collaborative.

    {/*

    @@ -120,7 +122,7 @@ export default function ConfPage(): JSX.Element {

    */}

    - Registration opening soon! Follow us on{' '} + Follow us on{' '} subscribe to our news {' '} - to not miss when registration opens. + to not miss any updates.

    @@ -171,11 +173,36 @@ export default function ConfPage(): JSX.Element { /> */} + + + Register to attend online for free + + + + + + Watch last year's live replay diff --git a/nx-dev/nx-dev/pages/plugins/[...segments].tsx b/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx similarity index 88% rename from nx-dev/nx-dev/pages/plugins/[...segments].tsx rename to nx-dev/nx-dev/pages/extending-nx/[...segments].tsx index df2a65da9e136..6b7128517c3d7 100644 --- a/nx-dev/nx-dev/pages/plugins/[...segments].tsx +++ b/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx @@ -10,15 +10,18 @@ import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { nxPluginsApi } from '../../lib/plugins.api'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function Pages({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -72,6 +75,7 @@ export default function Pages({
    @@ -83,7 +87,7 @@ export const getStaticPaths: GetStaticPaths = () => { return { paths: nxPluginsApi .getSlugsStaticDocumentPaths() - .filter((v) => v !== '/plugins/registry'), + .filter((v) => v !== '/extending-nx/registry'), fallback: 'blocking', }; }; @@ -93,15 +97,18 @@ export const getStaticProps: GetStaticProps = async ({ params: { segments: string[] }; }) => { try { - const segments = ['plugins', ...params.segments]; + const segments = ['extending-nx', ...params.segments]; const document = nxPluginsApi.getDocument(segments); return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item - menu: menusApi.getMenu('plugins', ''), + menu: menusApi.getMenu('extending-nx', ''), }, }; } catch (e) { diff --git a/nx-dev/nx-dev/pages/plugins/index.tsx b/nx-dev/nx-dev/pages/extending-nx/index.tsx similarity index 87% rename from nx-dev/nx-dev/pages/plugins/index.tsx rename to nx-dev/nx-dev/pages/extending-nx/index.tsx index 3c82d5c3140c2..5d8f92214e5b9 100644 --- a/nx-dev/nx-dev/pages/plugins/index.tsx +++ b/nx-dev/nx-dev/pages/extending-nx/index.tsx @@ -10,15 +10,18 @@ import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { nxPluginsApi } from '../../lib/plugins.api'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function PluginsRoot({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -72,6 +75,7 @@ export default function PluginsRoot({

    @@ -81,13 +85,16 @@ export default function PluginsRoot({ export const getStaticProps: GetStaticProps = async () => { const document = nxPluginsApi.generateRootDocumentIndex({ - name: 'Plugins', - description: 'Learn quickly how to do things with Nx.', + name: 'Extending Nx', + description: 'Learn more about creating your own plugin, extending Nx.', }); return { props: { document, - menu: menusApi.getMenu('plugins', ''), + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, + menu: menusApi.getMenu('extending-nx', ''), relatedDocuments: document.tags .map((t) => tagsApi.getAssociatedItems(t)) .flat(), diff --git a/nx-dev/nx-dev/pages/plugins/registry.tsx b/nx-dev/nx-dev/pages/extending-nx/registry.tsx similarity index 98% rename from nx-dev/nx-dev/pages/plugins/registry.tsx rename to nx-dev/nx-dev/pages/extending-nx/registry.tsx index 01f5352dc32cc..1d215e36174ea 100644 --- a/nx-dev/nx-dev/pages/plugins/registry.tsx +++ b/nx-dev/nx-dev/pages/extending-nx/registry.tsx @@ -71,7 +71,7 @@ export default function Browse(props: BrowseProps): JSX.Element { menu: Menu; } = { menu: { - sections: [getBasicPluginsSection(menusApi.getMenu('plugins', ''))], + sections: [getBasicPluginsSection(menusApi.getMenu('extending-nx', ''))], }, }; diff --git a/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx b/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx index 1bf55d9b576ef..b4d9791d0a975 100644 --- a/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx +++ b/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx @@ -13,15 +13,18 @@ import { nxCloudApi } from '../../lib/cloud.api'; import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function Pages({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -75,6 +78,7 @@ export default function Pages({
    @@ -99,6 +103,9 @@ export const getStaticProps: GetStaticProps = async ({ return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item diff --git a/nx-dev/nx-dev/pages/nx-cloud/index.tsx b/nx-dev/nx-dev/pages/nx-cloud/index.tsx index 4ae72535b838f..9742328df419f 100644 --- a/nx-dev/nx-dev/pages/nx-cloud/index.tsx +++ b/nx-dev/nx-dev/pages/nx-cloud/index.tsx @@ -13,15 +13,18 @@ import { nxCloudApi } from '../../lib/cloud.api'; import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function CloudRoot({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -75,6 +78,7 @@ export default function CloudRoot({
    @@ -90,6 +94,9 @@ export const getStaticProps: GetStaticProps = async () => { return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, menu: menusApi.getMenu('cloud', ''), relatedDocuments: document.tags .map((t) => tagsApi.getAssociatedItems(t)) diff --git a/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx b/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx index 5cb45d0b854a8..de802de86702e 100644 --- a/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx +++ b/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx @@ -13,16 +13,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { nxPackagesApi } from '../../../../lib/packages.api'; import { tagsApi } from '../../../../lib/tags.api'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function PackageDocument({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -79,6 +82,7 @@ export default function PackageDocument({ @@ -120,6 +124,9 @@ export async function getStaticProps({ props: { pkg: nxPackagesApi.getPackage([params.name]), document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx index e4e5960e2bb0f..badb40132070f 100644 --- a/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx +++ b/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx @@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { content } from '../../../../lib/rspack/content/overview'; import { pkg } from '../../../../lib/rspack/pkg'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function Overview({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -77,6 +80,7 @@ export default function Overview({ @@ -99,6 +103,9 @@ export async function getStaticProps() { props: { pkg, document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: [], menu: menusApi.getMenu('packages', ''), }, diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx index 028f2bbb8486a..0ba2309bf3385 100644 --- a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx +++ b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx @@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { content } from '../../../../lib/rspack/content/rspack-config-setup'; import { pkg } from '../../../../lib/rspack/pkg'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function RspackConfigSetup({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -77,6 +80,7 @@ export default function RspackConfigSetup({ @@ -100,6 +104,9 @@ export async function getStaticProps() { props: { pkg, document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: [], menu: menusApi.getMenu('packages', ''), }, diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx index 065c3d1834dc1..6567ff04f58af 100644 --- a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx +++ b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx @@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { content } from '../../../../lib/rspack/content/rspack-plugin'; import { pkg } from '../../../../lib/rspack/pkg'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function RspackPlugins({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -77,6 +80,7 @@ export default function RspackPlugins({ @@ -99,6 +103,9 @@ export async function getStaticProps() { props: { pkg, document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: [], menu: menusApi.getMenu('packages', ''), }, diff --git a/nx-dev/nx-dev/pages/recipes/[...segments].tsx b/nx-dev/nx-dev/pages/recipes/[...segments].tsx deleted file mode 100644 index 68e3e444a3b69..0000000000000 --- a/nx-dev/nx-dev/pages/recipes/[...segments].tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { getBasicRecipesSection } from '@nx/nx-dev/data-access-menu'; -import { DocViewer } from '@nx/nx-dev/feature-doc-viewer'; -import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document'; -import { Menu, MenuItem } from '@nx/nx-dev/models-menu'; -import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common'; -import { GetStaticPaths, GetStaticProps } from 'next'; -import { useRouter } from 'next/router'; -import { useEffect, useRef } from 'react'; -import { menusApi } from '../../lib/menus.api'; -import { useNavToggle } from '../../lib/navigation-toggle.effect'; -import { nxRecipesApi } from '../../lib/recipes.api'; -import { tagsApi } from '../../lib/tags.api'; - -export default function Recipes({ - document, - menu, - relatedDocuments, -}: { - document: ProcessedDocument; - menu: MenuItem[]; - relatedDocuments: RelatedDocument[]; -}): JSX.Element { - const router = useRouter(); - const { toggleNav, navIsOpen } = useNavToggle(); - const wrapperElement = useRef(null); - - useEffect(() => { - const handleRouteChange = (url: string) => { - if (url.includes('#')) return; - if (!wrapperElement) return; - - (wrapperElement as any).current.scrollTo({ - top: 0, - left: 0, - behavior: 'smooth', - }); - }; - - router.events.on('routeChangeComplete', handleRouteChange); - return () => router.events.off('routeChangeComplete', handleRouteChange); - }, [router, wrapperElement]); - - const vm: { - document: ProcessedDocument; - menu: Menu; - relatedDocuments: RelatedDocument[]; - } = { - document, - menu: { - sections: [getBasicRecipesSection(menu)], - }, - relatedDocuments, - }; - - return ( -
    -
    - -
    -
    - -
    - -
    -
    -
    - ); -} - -export const getStaticPaths: GetStaticPaths = () => { - return { - paths: nxRecipesApi.getSlugsStaticDocumentPaths(), - fallback: 'blocking', - }; -}; -export const getStaticProps: GetStaticProps = async ({ - params, -}: { - params: { segments: string[] }; -}) => { - try { - const segments = ['recipes', ...params.segments]; - const document = nxRecipesApi.getDocument(segments); - return { - props: { - document, - relatedDocuments: tagsApi - .getAssociatedItemsFromTags(document.tags) - .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item - menu: menusApi.getMenu('recipes', ''), - }, - }; - } catch (e) { - return { - notFound: true, - props: { - statusCode: 404, - }, - }; - } -}; diff --git a/nx-dev/nx-dev/pages/recipes/index.tsx b/nx-dev/nx-dev/pages/recipes/index.tsx deleted file mode 100644 index 9e513353dd0a9..0000000000000 --- a/nx-dev/nx-dev/pages/recipes/index.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { getBasicRecipesSection } from '@nx/nx-dev/data-access-menu'; -import { DocViewer } from '@nx/nx-dev/feature-doc-viewer'; -import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document'; -import { Menu, MenuItem } from '@nx/nx-dev/models-menu'; -import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common'; -import { GetStaticProps } from 'next'; -import { useRouter } from 'next/router'; -import { useEffect, useRef } from 'react'; -import { menusApi } from '../../lib/menus.api'; -import { useNavToggle } from '../../lib/navigation-toggle.effect'; -import { nxRecipesApi } from '../../lib/recipes.api'; -import { tagsApi } from '../../lib/tags.api'; - -export default function RecipesRoot({ - document, - menu, - relatedDocuments, -}: { - document: ProcessedDocument; - menu: MenuItem[]; - relatedDocuments: RelatedDocument[]; -}) { - const router = useRouter(); - const { toggleNav, navIsOpen } = useNavToggle(); - const wrapperElement = useRef(null); - - useEffect(() => { - const handleRouteChange = (url: string) => { - if (url.includes('#')) return; - if (!wrapperElement) return; - - (wrapperElement as any).current.scrollTo({ - top: 0, - left: 0, - behavior: 'smooth', - }); - }; - - router.events.on('routeChangeComplete', handleRouteChange); - return () => router.events.off('routeChangeComplete', handleRouteChange); - }, [router, wrapperElement]); - - const vm: { - document: ProcessedDocument; - menu: Menu; - relatedDocuments: RelatedDocument[]; - } = { - document, - menu: { - sections: [getBasicRecipesSection(menu)], - }, - relatedDocuments, - }; - - return ( -
    -
    - -
    -
    - -
    - -
    -
    -
    - ); -} - -export const getStaticProps: GetStaticProps = async () => { - const document = nxRecipesApi.generateRootDocumentIndex({ - name: 'Recipes', - description: 'Learn quickly how to do things with Nx.', - }); - return { - props: { - document, - menu: menusApi.getMenu('recipes', ''), - relatedDocuments: document.tags - .map((t) => tagsApi.getAssociatedItems(t)) - .flat(), - }, - }; -}; diff --git a/nx-dev/nx-dev/public/images/conf/adrian-baran.webp b/nx-dev/nx-dev/public/images/conf/adrian-baran.webp new file mode 100644 index 0000000000000..97bdba310ad28 Binary files /dev/null and b/nx-dev/nx-dev/public/images/conf/adrian-baran.webp differ diff --git a/nx-dev/nx-dev/public/images/conf/brandon-roberts.webp b/nx-dev/nx-dev/public/images/conf/brandon-roberts.webp new file mode 100644 index 0000000000000..f6663c2a3fd29 Binary files /dev/null and b/nx-dev/nx-dev/public/images/conf/brandon-roberts.webp differ diff --git a/nx-dev/nx-dev/public/images/conf/james-henry.webp b/nx-dev/nx-dev/public/images/conf/james-henry.webp index 336b08f75d44a..3dfdcf0a23524 100644 Binary files a/nx-dev/nx-dev/public/images/conf/james-henry.webp and b/nx-dev/nx-dev/public/images/conf/james-henry.webp differ diff --git a/nx-dev/nx-dev/public/images/conf/johanna-pearce.webp b/nx-dev/nx-dev/public/images/conf/johanna-pearce.webp new file mode 100644 index 0000000000000..548267ebc6cb9 Binary files /dev/null and b/nx-dev/nx-dev/public/images/conf/johanna-pearce.webp differ diff --git a/nx-dev/nx-dev/public/images/conf/juri-strumpflohner.webp b/nx-dev/nx-dev/public/images/conf/juri-strumpflohner.webp index aa4005e103930..8994e3aacaa46 100644 Binary files a/nx-dev/nx-dev/public/images/conf/juri-strumpflohner.webp and b/nx-dev/nx-dev/public/images/conf/juri-strumpflohner.webp differ diff --git a/nx-dev/nx-dev/public/images/conf/max-kless.webp b/nx-dev/nx-dev/public/images/conf/max-kless.webp new file mode 100644 index 0000000000000..1a438f2703280 Binary files /dev/null and b/nx-dev/nx-dev/public/images/conf/max-kless.webp differ diff --git a/nx-dev/nx-dev/public/images/conf/michael-hladky.webp b/nx-dev/nx-dev/public/images/conf/michael-hladky.webp new file mode 100644 index 0000000000000..d412ae46c4aa6 Binary files /dev/null and b/nx-dev/nx-dev/public/images/conf/michael-hladky.webp differ diff --git a/nx-dev/nx-dev/public/images/conf/miro-jonas.webp b/nx-dev/nx-dev/public/images/conf/miro-jonas.webp new file mode 100644 index 0000000000000..f216e744e35f7 Binary files /dev/null and b/nx-dev/nx-dev/public/images/conf/miro-jonas.webp differ diff --git a/nx-dev/nx-dev/public/images/icons/playwright.svg b/nx-dev/nx-dev/public/images/icons/playwright.svg new file mode 100644 index 0000000000000..a963d08b688ad --- /dev/null +++ b/nx-dev/nx-dev/public/images/icons/playwright.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 414242945285c..de0a6692eae56 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -144,6 +144,14 @@ const schemaUrls = { '/react-native/start': '/packages/react-native/executors/start', '/react-native/storybook': '/packages/react-native/executors/storybook', '/react-native/sync-deps': '/packages/react-native/executors/sync-deps', + '/packages/cypress/generators/cypress-e2e-configuration': + '/packages/cypress/generators/configuration', + '/packages/cypress/generators/cypress-component-configuration': + '/packages/cypress/generators/component-configuration', + '/packages/esbuild/generators/esbuild-project': + '/packages/esbuild/generators/configuration', + '/packages/jest/generators/jest-project': + '/packages/jest/generators/configuration', '/packages/nx-plugin/generators/executor': '/packages/plugin/generators/executor', '/packages/nx-plugin/generators/migration': @@ -152,6 +160,10 @@ const schemaUrls = { '/packages/nx-plugin/generators/schematic': '/packages/plugin/generators/generator', '/packages/nx-plugin/generators/e2e': '/packages/plugin/executors/e2e', + '/packages/rollup/generators/rollup-project': + '/packages/rollup/generators/configuration', + '/packages/webpack/generators/webpack-project': + '/packages/webpack/generators/configuration', '/nx-plugin/executor': '/packages/plugin/generators/executor', '/nx-plugin/migration': '/packages/plugin/generators/migration', '/nx-plugin/plugin': '/packages/plugin/generators/plugin', @@ -201,7 +213,7 @@ const diataxis = { '/using-nx/updating-nx': '/core-features/automate-updating-dependencies', '/using-nx/nx-nodejs-typescript-version-matrix': '/workspace/nx-nodejs-typescript-version-matrix', - '/extending-nx/nx-devkit': '/plugins/intro/getting-started', + '/extending-nx/nx-devkit': '/extending-nx/intro/getting-started', '/extending-nx/project-inference-plugins': '/recipes/advanced-plugins/project-inference-plugins', '/extending-nx/project-graph-plugins': @@ -214,11 +226,13 @@ const diataxis = { '/migration/preserving-git-histories': '/recipes/adopting-nx/preserving-git-histories', '/migration/manual': '/recipes/adopting-nx/manual', - '/executors/using-builders': '/plugin-features/use-task-executors', + '/executors/using-builders': + '/core-features/plugin-features/use-task-executors', '/executors/run-commands-builder': '/recipes/executors/run-commands-executor', '/executors/creating-custom-builders': '/recipes/executors/creating-custom-executors', - '/generators/using-generators': '/plugin-features/use-code-generators', + '/generators/using-generators': + '/core-features/plugin-features/use-code-generators', '/generators/workspace-generators': '/recipes/generators/workspace-generators', '/generators/composing-generators': @@ -228,12 +242,14 @@ const diataxis = { '/generators/modifying-files': '/recipes/generators/modifying-files', '/structure/applications-and-libraries': 'more-concepts/applications-and-libraries', - '/structure/creating-libraries': '/more-concepts/creating-libraries', - '/structure/library-types': '/more-concepts/library-types', - '/structure/grouping-libraries': '/more-concepts/grouping-libraries', + '/structure/creating-libraries': '/concepts/more-concepts/creating-libraries', + '/structure/library-types': '/concepts/more-concepts/library-types', + '/structure/grouping-libraries': '/concepts/more-concepts/grouping-libraries', '/structure/buildable-and-publishable-libraries': - '/more-concepts/buildable-and-publishable-libraries', - '/structure/monorepo-tags': '/core-features/enforce-project-boundaries', + '/concepts/more-concepts/buildable-and-publishable-libraries', + '/structure/monorepo-tags': '/core-features/enforce-module-boundaries', + '/core-features/enforce-project-boundaries': + '/core-features/enforce-module-boundaries', '/structure/dependency-graph': '/core-features/explore-graph', '/structure/project-graph-plugins': '/recipes/advanced-plugins/project-graph-plugins', @@ -245,19 +261,20 @@ const diataxis = { '/ci/monorepo-ci-bitbucket-pipelines': '/recipes/ci/monorepo-ci-bitbucket-pipelines', '/ci/distributed-builds': '/concepts/dte', // 👀 - '/ci/incremental-builds': '/more-concepts/incremental-builds', + '/ci/incremental-builds': '/concepts/more-concepts/incremental-builds', '/ci/setup-incremental-builds-angular': '/recipes/other/setup-incremental-builds-angular', - '/guides/turbo-and-nx': '/more-concepts/turbo-and-nx', - '/guides/why-monorepos': '/more-concepts/why-monorepos', + '/guides/turbo-and-nx': '/concepts/more-concepts/turbo-and-nx', + '/guides/why-monorepos': '/concepts/more-concepts/why-monorepos', '/guides/adding-assets-react': '/recipes/other/adding-assets-react', '/guides/environment-variables': '/reference/environment-variables', - '/guides/monorepo-nx-enterprise': '/more-concepts/monorepo-nx-enterprise', + '/guides/monorepo-nx-enterprise': + '/concepts/more-concepts/monorepo-nx-enterprise', '/guides/performance-profiling': '/recipes/other/performance-profiling', '/guides/eslint': '/recipes/other/eslint', '/guides/customize-webpack': '/packages/webpack/documents/webpack-config-setup', - '/guides/nx-daemon': '/more-concepts/nx-daemon', + '/guides/nx-daemon': '/concepts/more-concepts/nx-daemon', '/guides/js-and-ts': '/recipes/other/js-and-ts', '/guides/browser-support': '/recipes/other/browser-support', '/guides/react-native': '/recipes/other/react-native', @@ -269,11 +286,12 @@ const diataxis = { '/recipes/other/using-tailwind-css-with-angular-projects', '/guides/misc-ngrx': '/recipes/other/misc-ngrx', '/guides/misc-data-persistence': '/recipes/other/misc-data-persistence', - '/guides/nx-devkit-angular-devkit': '/more-concepts/nx-devkit-angular-devkit', + '/guides/nx-devkit-angular-devkit': + '/concepts/more-concepts/nx-devkit-angular-devkit', '/module-federation/faster-builds': '/recipes/module-federation/faster-builds', '/module-federation/micro-frontend-architecture': - '/more-concepts/micro-frontend-architecture', + '/concepts/more-concepts/micro-frontend-architecture', '/module-federation/dynamic-module-federation-with-angular': '/recipes/module-federation/dynamic-module-federation-with-angular', '/examples/nx-examples': '/recipes/other/nx-examples', @@ -345,21 +363,33 @@ const recipesUrls = { '/recipes/enforce-module-boundaries/ban-external-imports', '/recipes/other/tags-allow-list': '/recipes/enforce-module-boundaries/tags-allow-list', - '/recipes/other/react-nx': '/recipes/example-repos/react-nx', - '/recipes/other/apollo-react': '/recipes/example-repos/apollo-react', - '/recipes/other/caching': '/recipes/example-repos/caching', - '/recipes/other/dte': '/recipes/example-repos/dte', + '/recipes/other/react-nx': '/showcase/example-repos/react-nx', + '/recipes/other/apollo-react': '/showcase/example-repos/apollo-react', + '/recipes/other/caching': '/showcase/example-repos/caching', + '/recipes/other/dte': '/showcase/example-repos/dte', '/recipes/other/deploy-nextjs-to-vercel': '/recipes/deployment/deploy-nextjs-to-vercel', + '/recipes/other/root-level-scripts': + '/recipes/managing-repository/root-level-scripts', + '/recipes/other/analyze-source-files': + '/recipes/managing-repository/analyze-source-files', + '/recipes/other/workspace-watching': + '/recipes/managing-repository/workspace-watching', + '/recipes/other/advanced-update': + '/recipes/managing-repository/advanced-update', + '/recipes/other/js-and-ts': '/recipes/managing-repository/js-and-ts', }; /** * Nx Cloud */ const nxCloudUrls = { - '/nx-cloud/set-up/add-nx-cloud': '/core-features/share-your-cache', - '/nx-cloud/set-up/set-up-caching': '/core-features/share-your-cache', + '/nx-cloud/set-up/add-nx-cloud': '/core-features/remote-cache', + '/nx-cloud/set-up/set-up-caching': '/core-features/remote-cache', '/nx-cloud/set-up/set-up-dte': '/core-features/distribute-task-execution', + '/nx-cloud/private-cloud/standalone': '/nx-cloud/private-cloud/ami-setup', + '/nx-cloud/private-cloud/kubernetes-setup': + '/nx-cloud/private-cloud/get-started', }; /** @@ -405,7 +435,8 @@ const oldNodeTutorialPaths = [ ]; const extraNodeRedirects = { - '/getting-started/node-tutorial': '/getting-started/node-server-tutorial', + '/getting-started/node-tutorial': + '/getting-started/tutorials/node-server-tutorial', '/node-tutorial/1-code-generation': '/node-server-tutorial/1-code-generation', '/node-tutorial/2-project-graph': '/node-server-tutorial/2-project-graph', '/node-tutorial/3-task-running': '/node-server-tutorial/3-task-running', @@ -461,15 +492,15 @@ const standaloneTutorialRedirects = { '/getting-started/tutorials/react-standalone-tutorial', '/shared/react-standalone-tutorial/5-summary': '/getting-started/tutorials/react-standalone-tutorial', - 'shared/angular-standalone-tutorial/1-code-generation': + '/shared/angular-standalone-tutorial/1-code-generation': '/getting-started/tutorials/angular-standalone-tutorial', - 'shared/angular-standalone-tutorial/2-project-graph': + '/shared/angular-standalone-tutorial/2-project-graph': '/getting-started/tutorials/angular-standalone-tutorial', - 'shared/angular-standalone-tutorial/3-task-running': + '/shared/angular-standalone-tutorial/3-task-running': '/getting-started/tutorials/angular-standalone-tutorial', - 'shared/angular-standalone-tutorial/4-task-pipelines': + '/shared/angular-standalone-tutorial/4-task-pipelines': '/getting-started/tutorials/angular-standalone-tutorial', - 'shared/angular-standalone-tutorial/5-summary': + '/shared/angular-standalone-tutorial/5-summary': '/getting-started/tutorials/angular-standalone-tutorial', }; @@ -597,7 +628,7 @@ const packagesDocuments = { * Concept documents Updates (updated 2023-03-31) */ const conceptUrls = { - '/more-concepts/global-nx': + '/concepts/more-concepts/global-nx': '/getting-started/installation#installing-nx-globally', '/getting-started/package-based-repo-tutorial': '/getting-started/tutorials/package-based-repo-tutorial', @@ -623,27 +654,185 @@ const nested5minuteTutorialUrls = { }; const pluginUrls = { - '/plugin-features/create-your-own-plugin': '/plugins/tutorials/create-plugin', - '/recipes/advanced-plugins': '/plugins/recipes', - '/recipes/advanced-plugins/create-preset': '/plugins/recipes/create-preset', + '/plugin-features/create-your-own-plugin': + '/extending-nx/tutorials/create-plugin', + '/recipes/advanced-plugins': '/extending-nx/recipes', + '/recipes/advanced-plugins/create-preset': + '/extending-nx/recipes/create-preset', '/recipes/advanced-plugins/migration-generators': - '/plugins/recipes/migration-generators', + '/extending-nx/recipes/migration-generators', '/recipes/advanced-plugins/project-graph-plugins': - '/plugins/recipes/project-graph-plugins', + '/extending-nx/recipes/project-graph-plugins', '/recipes/advanced-plugins/project-inference-plugins': - '/plugins/recipes/project-inference-plugins', + '/extending-nx/recipes/project-inference-plugins', '/recipes/advanced-plugins/share-your-plugin': - '/plugins/tutorials/maintain-published-plugin', - '/recipes/executors/compose-executors': '/plugins/recipes/compose-executors', + '/extending-nx/tutorials/maintain-published-plugin', + '/recipes/executors/compose-executors': + '/extending-nx/recipes/compose-executors', '/recipes/executors/creating-custom-executors': - '/plugins/recipes/local-executors', - '/recipes/generators': '/plugins/recipes', + '/extending-nx/recipes/local-executors', + '/recipes/generators': '/extending-nx/recipes', '/recipes/generators/composing-generators': - '/plugins/recipes/composing-generators', - '/recipes/generators/creating-files': '/plugins/recipes/creating-files', - '/recipes/generators/generator-options': '/plugins/recipes/generator-options', - '/recipes/generators/local-generators': '/plugins/recipes/local-generators', - '/recipes/generators/modifying-files': '/plugins/recipes/modifying-files', + '/extending-nx/recipes/composing-generators', + '/recipes/generators/creating-files': '/extending-nx/recipes/creating-files', + '/recipes/generators/generator-options': + '/extending-nx/recipes/generator-options', + '/recipes/generators/local-generators': + '/extending-nx/recipes/local-generators', + '/recipes/generators/modifying-files': + '/extending-nx/recipes/modifying-files', +}; + +const referenceUrls = { + '/reference/changelog': '/changelog', +}; + +const missingAndCatchAllRedirects = { + // missing + '/docs': '/getting-started/intro', + // catch all + '/(l|latest|p|previous)/(a|angular|r|react|n|node)/:path*': '/:path*', + '/(l|latest|p|previous)/:path*': '/:path*', + '/(a|angular|r|react|n|node)/:path*': '/:path*', + // Storybook + '/(l|latest)/(r|react)/storybook/overview': '/storybook/overview-react', + '/(l|latest)/(a|angular)/storybook/overview': '/storybook/overview-angular', + '/(l|latest)/(a|angular|r|react)/storybook/executors': + '/storybook/executors-storybook', + // Nx Console + '/nx-console': '/using-nx/console', +}; + +const movePluginFeaturesToCore = { + '/plugin-features/use-task-executors': + '/core-features/plugin-features/use-task-executors', + '/plugin-features/use-code-generators': + '/core-features/plugin-features/use-code-generators', +}; + +const makeMoreConceptsSubmenu = { + '/more-concepts': '/concepts/more-concepts', + '/more-concepts/:path*': '/concepts/more-concepts/:path*', +}; + +const pluginsToExtendNx = { + '/plugins': '/extending-nx/intro/getting-started', + '/plugins/:path*': '/extending-nx/:path*', +}; + +// (meeroslav) 2023-07-20 +const latestRecipesRefactoring = { + // removed + '/recipes/getting-started/set-up-a-new-workspace': + '/getting-started/installation', + '/recipes/other/misc-ngrx': '/packages/angular/generators/ngrx', // 486 views + '/recipes/other/misc-data-persistence': '/packages/angular/generators/ngrx', // 200 views + '/recipes/other/standalone-ngrx-apis': '/packages/angular/generators/ngrx', //47 views -> can be freely removed + '/recipes/other/export-project-graph': '/recipes/core-features/explore-graph', // 20 views -> contents moved to explore-graph + '/recipes/executors/use-executor-configurations': + '/plugin-features/use-task-executors', // --> contents are moved over to use-task-executors + // ci + '/recipes/other/azure-last-successful-commit': + '/recipes/ci/azure-last-successful-commit', + // angular + '/recipes/adopting-nx/migration-angular': + '/recipes/angular/migration/angular', + '/recipes/adopting-nx-angular/angular-integrated': + '/recipes/angular/migration/angular', + '/recipes/adopting-nx-angular/angular-manual': + '/recipes/angular/migration/angular-manual', + '/recipes/adopting-nx-angular/angular-multiple': + '/recipes/angular/migration/angular-multiple', + '/recipes/adopting-nx/migration-angularjs': + '/recipes/angular/migration/angularjs', + '/recipes/environment-variables/use-environment-variables-in-angular': + '/recipes/angular/use-environment-variables-in-angular', + '/recipes/other/using-tailwind-css-with-angular-projects': + '/recipes/angular/using-tailwind-css-with-angular-projects', + '/recipes/module-federation/dynamic-module-federation-with-angular': + '/recipes/angular/dynamic-module-federation-with-angular', + '/recipes/other/setup-incremental-builds-angular': + '/recipes/angular/setup-incremental-builds-angular', + // react + '/recipes/adopting-nx/migration-cra': '/recipes/react/migration-cra', + '/recipes/other/react-18': '/recipes/react/react-18', + '/recipes/other/react-native': '/recipes/react/react-native', + '/recipes/other/remix': '/recipes/react/remix', + '/recipes/environment-variables/use-environment-variables-in-react': + '/recipes/react/use-environment-variables-in-react', + '/recipes/other/using-tailwind-css-in-react': + '/recipes/react/using-tailwind-css-in-react', + '/recipes/deployment/deploy-nextjs-to-vercel': + '/recipes/react/deploy-nextjs-to-vercel', + '/recipes/module-federation/module-federation-with-ssr': + '/recipes/react/module-federation-with-ssr', + '/recipes/other/adding-assets-react': '/recipes/react/adding-assets', + // node + '/recipes/deployment/node-server-fly-io': '/recipes/node/node-server-fly-io', + '/recipes/deployment/node-serverless-functions-netlify': + '/recipes/node/node-serverless-functions-netlify', + '/recipes/deployment/node-aws-lambda': '/recipes/node/node-aws-lambda', + // examples + '/recipes/module-federation/nx-examples': '/showcase/example-repos/mfe', + '/recipes/database/nestjs-prisma': '/showcase/example-repos/nestjs-prisma', + '/recipes/database/mongo-fastify': '/showcase/example-repos/mongo-fastify', + '/recipes/database/redis-fastify': '/showcase/example-repos/redis-fastify', + '/recipes/database/postgres-fastify': + '/showcase/example-repos/postgres-fastify', + '/recipes/database/serverless-fastify-planetscale': + '/showcase/example-repos/serverless-fastify-planetscale', + '/recipes/example-repos/:path*': '/showcase/example-repos/:path*', + // troubleshooting + '/recipes/other/resolve-circular-dependencies': + '/recipes/troubleshooting/resolve-circular-dependencies', + '/recipes/ci/troubleshoot-nx-install-issues': + '/recipes/troubleshooting/troubleshoot-nx-install-issues', + '/recipes/other/troubleshoot-cache-misses': + '/recipes/troubleshooting/troubleshoot-cache-misses', + '/recipes/other/unknown-local-cache': + '/recipes/troubleshooting/unknown-local-cache', + '/recipes/other/performance-profiling': + '/recipes/troubleshooting/performance-profiling', + // tips and tricks + '/recipes/environment-variables/define-environment-variables': + '/recipes/tips-n-tricks/define-environment-variables', + '/recipes/other/eslint': '/recipes/tips-n-tricks/eslint', + '/recipes/other/browser-support': '/recipes/tips-n-tricks/browser-support', + '/recipes/other/include-assets-in-build': + '/recipes/tips-n-tricks/include-assets-in-build', + '/recipes/other/include-all-packagejson': + '/recipes/tips-n-tricks/include-all-packagejson', + '/recipes/other/identify-dependencies-between-folders': + '/recipes/tips-n-tricks/identify-dependencies-between-folders', + '/recipes/managing-repository/root-level-scripts': + '/recipes/tips-n-tricks/root-level-scripts', + '/recipes/managing-repository/analyze-source-files': + '/recipes/tips-n-tricks/analyze-source-files', + '/recipes/managing-repository/workspace-watching': + '/recipes/tips-n-tricks/workspace-watching', + '/recipes/managing-repository/standalone-to-integrated': + '/recipes/tips-n-tricks/standalone-to-integrated', + '/recipes/managing-repository/js-and-ts': '/recipes/tips-n-tricks/js-and-ts', + '/recipes/managing-repository/advanced-update': + '/recipes/tips-n-tricks/advanced-update', + '/recipes/executors/run-commands-executor': + '/recipes/tips-n-tricks/run-commands-executor', + // ci + '/recipes/ci/azure-last-successful-commit': '/recipes/ci/monorepo-ci-azure', + // other + '/recipes/deployment/deno-deploy': '/recipes/other/deno-deploy', + '/recipes/deployment/deno-netlify-functions': + '/recipes/other/deno-netlify-functions', + + // nx concepts + '/recipes/module-federation/faster-builds': + '/concepts/more-concepts/faster-builds-with-module-federation', + + '/reference/commands': '/packages/nx', +}; + +const coreFeatureRefactoring = { + '/core-features/share-your-cache': '/core-features/remote-cache', }; /** @@ -664,4 +853,11 @@ module.exports = { conceptUrls, nested5minuteTutorialUrls, pluginUrls, + referenceUrls, + missingAndCatchAllRedirects, + movePluginFeaturesToCore, + makeMoreConceptsSubmenu, + pluginsToExtendNx, + latestRecipesRefactoring, + coreFeatureRefactoring, }; diff --git a/nx-dev/nx-dev/redirect-rules.spec.js b/nx-dev/nx-dev/redirect-rules.spec.js index c4a4d73c17057..01f0df5bb8941 100644 --- a/nx-dev/nx-dev/redirect-rules.spec.js +++ b/nx-dev/nx-dev/redirect-rules.spec.js @@ -100,5 +100,21 @@ describe('Redirect rules configuration', () => { ).toEqual(`${newNodePathPrefix}${des}`); }); }); + + test('old tutorial links', () => { + const oldTutorialUrls = [ + '/tutorials/package-based-repo-tutorial', + '/tutorials/integrated-repo-tutorial', + '/tutorials/react-standalone-tutorial', + '/tutorials/angular-standalone-tutorial', + '/tutorials/node-server-tutorial', + ]; + + for (const url of oldTutorialUrls) { + expect(redirectRules.nested5minuteTutorialUrls[url]).toEqual( + '/getting-started' + url + ); + } + }); }); }); diff --git a/nx-dev/ui-common/src/index.ts b/nx-dev/ui-common/src/index.ts index 1431e27616f01..0be0fe5c60da1 100644 --- a/nx-dev/ui-common/src/index.ts +++ b/nx-dev/ui-common/src/index.ts @@ -13,3 +13,4 @@ export * from './lib/nx-users-showcase'; export * from './lib/plugin-card'; export * from './lib/testimonial-card'; export * from './lib/typography'; +export * from './lib/github-star-widget'; diff --git a/nx-dev/ui-common/src/lib/breadcrumbs.tsx b/nx-dev/ui-common/src/lib/breadcrumbs.tsx index 873e322d574b8..d3891c8b9f399 100644 --- a/nx-dev/ui-common/src/lib/breadcrumbs.tsx +++ b/nx-dev/ui-common/src/lib/breadcrumbs.tsx @@ -20,6 +20,10 @@ export function Breadcrumbs({ path }: { path: string }): JSX.Element { ]; const hasRef = path.includes('?') ? path.slice(0, path.indexOf('?')) : ''; + if (pages.length === 1) { + return <>; + } + return (