|
| 1 | +/** |
| 2 | + * This file decorate the Angular CLI with the Nx CLI to enable features such as computation caching, |
| 3 | + * and faster execution of tasks. |
| 4 | + * |
| 5 | + * It does this by: |
| 6 | + * |
| 7 | + * - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command. |
| 8 | + * - Symlinking the ng to nx command, so all commands run through the Nx CLI |
| 9 | + * - Updating the package.json postinstall script to give you control over this script |
| 10 | + * |
| 11 | + * The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it. |
| 12 | + * Every command you run should work the same when using the Nx CLI, except faster. |
| 13 | + * |
| 14 | + * Because of symliking you can still type `ng build/test/lint` in the terminal. The ng command, in this case, |
| 15 | + * will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked. |
| 16 | + * The Nx CLI simply does some optimizations before invoking the Angular CLI. |
| 17 | + * |
| 18 | + * To opt out of this patch: |
| 19 | + * - Replace occurrences of nx with ng in your package.json |
| 20 | + * - Remove the script from your postinstall script in your package.json |
| 21 | + * - Delete and reinstall your node_modules |
| 22 | + */ |
| 23 | + |
| 24 | +const fs = require("fs"); |
| 25 | +const os = require("os"); |
| 26 | +const cp = require("child_process"); |
| 27 | +const isWindows = os.platform() === "win32"; |
| 28 | +const { output } = require("@nrwl/workspace"); |
| 29 | + |
| 30 | +/** |
| 31 | + * Paths to files being patched |
| 32 | + */ |
| 33 | +const angularCLIInitPath = "node_modules/@angular/cli/lib/cli/index.js"; |
| 34 | + |
| 35 | +/** |
| 36 | + * Patch index.js to warn you if you invoke the undecorated Angular CLI. |
| 37 | + */ |
| 38 | +function patchAngularCLI(initPath) { |
| 39 | + const angularCLIInit = fs.readFileSync(initPath, "utf-8").toString(); |
| 40 | + |
| 41 | + if (!angularCLIInit.includes("NX_CLI_SET")) { |
| 42 | + fs.writeFileSync( |
| 43 | + initPath, |
| 44 | + ` |
| 45 | +if (!process.env['NX_CLI_SET']) { |
| 46 | + const { output } = require('@nrwl/workspace'); |
| 47 | + output.warn({ title: 'The Angular CLI was invoked instead of the Nx CLI. Use "npx ng [command]" or "nx [command]" instead.' }); |
| 48 | +} |
| 49 | +${angularCLIInit} |
| 50 | + ` |
| 51 | + ); |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +/** |
| 56 | + * Symlink of ng to nx, so you can keep using `ng build/test/lint` and still |
| 57 | + * invoke the Nx CLI and get the benefits of computation caching. |
| 58 | + */ |
| 59 | +function symlinkNgCLItoNxCLI() { |
| 60 | + try { |
| 61 | + const ngPath = "./node_modules/.bin/ng"; |
| 62 | + const nxPath = "./node_modules/.bin/nx"; |
| 63 | + if (isWindows) { |
| 64 | + /** |
| 65 | + * This is the most reliable way to create symlink-like behavior on Windows. |
| 66 | + * Such that it works in all shells and works with npx. |
| 67 | + */ |
| 68 | + ["", ".cmd", ".ps1"].forEach((ext) => { |
| 69 | + fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext)); |
| 70 | + }); |
| 71 | + } else { |
| 72 | + // If unix-based, symlink |
| 73 | + cp.execSync(`ln -sf ./nx ${ngPath}`); |
| 74 | + } |
| 75 | + } catch (e) { |
| 76 | + output.error({ |
| 77 | + title: |
| 78 | + "Unable to create a symlink from the Angular CLI to the Nx CLI:" + |
| 79 | + e.message, |
| 80 | + }); |
| 81 | + throw e; |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +try { |
| 86 | + symlinkNgCLItoNxCLI(); |
| 87 | + patchAngularCLI(angularCLIInitPath); |
| 88 | + output.log({ |
| 89 | + title: "Angular CLI has been decorated to enable computation caching.", |
| 90 | + }); |
| 91 | +} catch (e) { |
| 92 | + output.error({ |
| 93 | + title: "Decoration of the Angular CLI did not complete successfully", |
| 94 | + }); |
| 95 | +} |
0 commit comments