Skip to content

Commit

Permalink
fix(core): add warning if running on an outdated global installation
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder committed Mar 3, 2023
1 parent c9244d2 commit f7322c0
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 1 deletion.
16 changes: 16 additions & 0 deletions docs/generated/manifests/menus.json
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,14 @@
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Managing your Global Nx Installation",
"path": "/more-concepts/global-nx",
"id": "global-nx",
"isExternal": false,
"children": [],
"disableCollapsible": false
}
],
"disableCollapsible": false
Expand Down Expand Up @@ -1317,6 +1325,14 @@
"children": [],
"disableCollapsible": false
},
{
"name": "Managing your Global Nx Installation",
"path": "/more-concepts/global-nx",
"id": "global-nx",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "All Recipes »",
"path": "/recipes",
Expand Down
20 changes: 20 additions & 0 deletions docs/generated/manifests/nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,16 @@
"isExternal": false,
"path": "/more-concepts/encapsulated-nx-and-the-wrapper",
"tags": []
},
{
"id": "global-nx",
"name": "Managing your Global Nx Installation",
"description": "",
"file": "shared/guides/global-nx",
"itemList": [],
"isExternal": false,
"path": "/more-concepts/global-nx",
"tags": []
}
],
"isExternal": false,
Expand Down Expand Up @@ -1640,6 +1650,16 @@
"path": "/more-concepts/encapsulated-nx-and-the-wrapper",
"tags": []
},
"/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",
"tags": []
},
"/recipes": {
"id": "all",
"name": "All Recipes »",
Expand Down
5 changes: 5 additions & 0 deletions docs/map.json
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,11 @@
"name": "Encapsulated Nx and the Nx Wrapper",
"id": "encapsulated-nx-and-the-wrapper",
"file": "shared/guides/encapsulated-nx-and-the-wrapper"
},
{
"name": "Managing your Global Nx Installation",
"id": "global-nx",
"file": "shared/guides/global-nx"
}
]
},
Expand Down
94 changes: 94 additions & 0 deletions docs/shared/guides/global-nx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Managing your Global Nx Installation

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 an [encapsulated install](/more-concepts/encapsulated-nx-and-the-wrapper) (e.g. `./nx` or `./nx.bat`)
- 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.

However, there are still cases where an issue could arise. If the structure of your Nx workspace no longer matches up with what the globally installed copy of Nx expects, it may fail to hand off to your local installation properly and instead error. This commonly results in errors such as:

- Could not find Nx modules in this workspace.
- The current directory isn't part of an Nx workspace.

If you find yourself in this position, you will need to update your global install of Nx. Exactly how you do this will depend on which package manager you originally installed Nx with.

If you cannot remember which package manager you installed Nx globally with, the below commands should help narrow it down.

{% tabs %}
{% tab label="npm" %}

```shell
npm list --global nx
```

{% /tab %}
{% tab label="yarn" %}

```shell
yarn global list nx
```

{% /tab %}
{% tab label="pnpm" %}

```shell
pnpm list --global nx
```

{% /tab %}
{% /tabs %}

If you find Nx has been installed multiple times, you can remove the global installation for all but 1 package manager by running the following commands for the duplicate installations:

{% tabs %}
{% tab label="npm" %}

```shell
npm rm --global nx
```

{% /tab %}
{% tab label="yarn" %}

```shell
yarn global remove nx
```

{% /tab %}
{% tab label="pnpm" %}

```shell
pnpm rm --global nx
```

{% /tab %}
{% /tabs %}

Finally, to complete your global installation update, simply reinstall it with the package manager of your choosing:

{% tabs %}
{% tab label="npm" %}

```shell
npm install --global nx@latest
```

{% /tab %}
{% tab label="yarn" %}

```shell
yarn global add nx@latest
```

{% /tab %}
{% tab label="pnpm" %}

```shell
pnpm install --global nx@latest
```

{% /tab %}
{% /tabs %}
57 changes: 56 additions & 1 deletion packages/nx/bin/nx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@ import {
import * as chalk from 'chalk';
import { initLocal } from './init-local';
import { output } from '../src/utils/output';
import { getNxInstallationPath } from 'nx/src/utils/installation-directory';
import {
getNxInstallationPath,
getNxRequirePaths,
} from '../src/utils/installation-directory';
import { major } from 'semver';
import { NX_PREFIX } from '../src/utils/logger';
import { readJsonFile } from '../src/utils/fileutils';
import {
detectPackageManager,
getPackageManagerCommand,
} from '../src/utils/package-manager';
import { execSync } from 'child_process';

const workspace = findWorkspaceRoot(process.cwd());
// new is a special case because there is no local workspace to load
Expand Down Expand Up @@ -53,6 +64,8 @@ if (
try {
localNx = resolveNx(workspace);
} catch {
// If we can't resolve a local copy of Nx, we must be global.
warnIfUsingOutdatedGlobalInstall();
output.error({
title: `Could not find Nx modules in this workspace.`,
bodyLines: [`Have you run ${chalk.bold.white(`npm/yarn install`)}?`],
Expand All @@ -69,6 +82,7 @@ if (
initLocal(workspace);
} else {
// Nx is being run from globally installed CLI - hand off to the local
warnIfUsingOutdatedGlobalInstall(getLocalNxVersion(workspace));
require(localNx);
}
}
Expand All @@ -93,3 +107,44 @@ function resolveNx(workspace: WorkspaceTypeAndRoot | null) {
});
}
}

/**
* Assumes currently running Nx is global install.
* Warns if out of date by 1 major version or more.
*/
function warnIfUsingOutdatedGlobalInstall(localNxVersion?: string) {
const globalVersion = require('../package.json').version;
const isOutdatedGlobalInstall =
globalVersion &&
((localNxVersion && major(globalVersion) - major(localNxVersion) < 0) ||
major(globalVersion) - major(getLatestVersionOfNx()) < 0);

// Using a global Nx Install
if (isOutdatedGlobalInstall) {
const packageManager = detectPackageManager(workspace.dir);
const bodyLines = [
'For more information, see https://nx.dev/more-concepts/global-nx',
];
if (!localNxVersion) {
bodyLines.unshift(
'Its possible that this is causing Nx to not pick up your workspace properly.'
);
}
output.warn({
title: `${NX_PREFIX} Outdated Global Installation of Nx Detected.`,
bodyLines,
});
}
}

function getLocalNxVersion(workspace: WorkspaceTypeAndRoot): string {
return readJsonFile(
require.resolve('nx/package.json', {
paths: getNxRequirePaths(workspace.dir),
})
).version;
}

function getLatestVersionOfNx(): string {
return execSync('npm view nx@latest version').toString().trim();
}

0 comments on commit f7322c0

Please sign in to comment.