feat(misc): enable ts solution setup by default for new workspaces (#30372)

## Current Behavior

To create a new workspace that uses the new TS solution setup the
`--workspaces` flag must be provided (Node, React, and Vue stacks).

## Expected Behavior

New workspaces should be created by default using the new TS solution
setup (Node, React, and Vue stacks). Users can opt out of it by
providing the `--no-workspaces` flag.

## Related Issue(s)

Fixes #
This commit is contained in:
Leosvel Pérez Espinosa 2025-03-14 17:42:31 +01:00 committed by GitHub
parent 398ab354e5
commit 2d69aa12bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 66 additions and 65 deletions

View File

@ -47,7 +47,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. | | `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) | | `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
| `--version` | boolean | Show version number. | | `--version` | boolean | Show version number. |
| `--workspaces` | boolean | Use package manager workspaces. (Default: `false`) | | `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |
| `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. | | `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. |
## Presets ## Presets

View File

@ -47,7 +47,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. | | `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) | | `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
| `--version` | boolean | Show version number. | | `--version` | boolean | Show version number. |
| `--workspaces` | boolean | Use package manager workspaces. (Default: `false`) | | `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |
| `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. | | `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. |
## Presets ## Presets

View File

@ -102,7 +102,7 @@
"workspaces": { "workspaces": {
"description": "Whether to use package manager workspaces.", "description": "Whether to use package manager workspaces.",
"type": "boolean", "type": "boolean",
"default": false "default": true
} }
}, },
"additionalProperties": true, "additionalProperties": true,

View File

@ -119,7 +119,7 @@
"workspaces": { "workspaces": {
"description": "Whether to use package manager workspaces.", "description": "Whether to use package manager workspaces.",
"type": "boolean", "type": "boolean",
"default": false "default": true
} }
}, },
"required": ["preset", "name"], "required": ["preset", "name"],

View File

@ -29,12 +29,16 @@ There are two different methods that Nx supports for linking TypeScript projects
## Project Linking with Workspaces ## Project Linking with Workspaces
To create a new Nx workspace that links projects with package manager workspaces, use the `--workspaces` flag. Create a new Nx workspace that links projects with package manager workspaces:
```shell ```shell
npx create-nx-workspace --workspaces npx create-nx-workspace
``` ```
{% callout type="note" title="Opt-out of Workspaces" %}
You can opt-out of workspaces by running `npx create-nx-workspace --no-workspaces`.
{% /callout %}
### Set Up Package Manager Workspaces ### Set Up Package Manager Workspaces
The configuration for package manager workspaces varies based on which package manager you're using. The configuration for package manager workspaces varies based on which package manager you're using.

View File

@ -8,9 +8,8 @@ description: A comprehensive reference of all environment variables that can be
The following environment variables are ones that you can set to change the behavior of Nx in different environments. The following environment variables are ones that you can set to change the behavior of Nx in different environments.
| Property | Type | Description | | Property | Type | Description |
| ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| NX_ADD_PLUGINS | boolean | If set to `false`, Nx will not add plugins to infer tasks. This is `true` by default. Workspaces created before Nx 18 will have this disabled via a migration for backwards compatibility | | NX_ADD_PLUGINS | boolean | If set to `false`, Nx will not add plugins to infer tasks. This is `true` by default. Workspaces created before Nx 18 will have this disabled via a migration for backwards compatibility |
| NX_ADD_TS_PLUGIN | boolean | If set to `false` when creating a new workspace using the `ts` preset, Nx will not add the `@nx/js/typescript` plugin to infer tasks and will not set up the workspace with [TypeScript project references](https://www.typescriptlang.org/docs/handbook/project-references.html). This is `true` by default. |
| NX_BASE | string | The default base branch to use when calculating the affected projects. Can be overridden on the command line with `--base`. | | 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 `.nx/cache` by default. Set this variable to use a different directory. | | NX_CACHE_DIRECTORY | string | The cache for task outputs is stored in `.nx/cache` 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_CACHE_PROJECT_GRAPH | boolean | If set to `false`, disables the project graph cache. Most useful when developing a plugin that modifies the project graph. |

View File

@ -52,7 +52,7 @@ title="Nx React Monorepo Tutorial Walkthrough"
Create a new React monorepo with the following command: Create a new React monorepo with the following command:
```{% command="npx create-nx-workspace@latest react-monorepo --preset=react-monorepo --workspaces" path="~" %} ```{% command="npx create-nx-workspace@latest react-monorepo --preset=react-monorepo" path="~" %}
NX Let's create a new workspace [https://nx.dev/getting-started/intro] NX Let's create a new workspace [https://nx.dev/getting-started/intro]

View File

@ -167,7 +167,7 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
.option('workspaces', { .option('workspaces', {
describe: chalk.dim`Use package manager workspaces.`, describe: chalk.dim`Use package manager workspaces.`,
type: 'boolean', type: 'boolean',
default: false, default: true,
}) })
.option('formatter', { .option('formatter', {
describe: chalk.dim`Code formatter to use.`, describe: chalk.dim`Code formatter to use.`,
@ -281,6 +281,8 @@ async function normalizeArgsMiddleware(
"Let's create a new workspace [https://nx.dev/getting-started/intro]", "Let's create a new workspace [https://nx.dev/getting-started/intro]",
}); });
argv.workspaces ??= true;
try { try {
argv.name = await determineFolder(argv); argv.name = await determineFolder(argv);
if (!argv.preset || isKnownPreset(argv.preset)) { if (!argv.preset || isKnownPreset(argv.preset)) {
@ -414,8 +416,7 @@ async function determineStack(
{ {
name: `none`, name: `none`,
message: message:
process.env.NX_ADD_PLUGINS !== 'false' && process.env.NX_ADD_PLUGINS !== 'false' && parsedArgs.workspaces
process.env.NX_ADD_TS_PLUGIN !== 'false'
? `None: Configures a TypeScript/JavaScript monorepo.` ? `None: Configures a TypeScript/JavaScript monorepo.`
: `None: Configures a TypeScript/JavaScript project with minimal structure.`, : `None: Configures a TypeScript/JavaScript project with minimal structure.`,
}, },
@ -519,7 +520,7 @@ async function determineNoneOptions(
if ( if (
(!parsedArgs.preset || parsedArgs.preset === Preset.TS) && (!parsedArgs.preset || parsedArgs.preset === Preset.TS) &&
process.env.NX_ADD_PLUGINS !== 'false' && process.env.NX_ADD_PLUGINS !== 'false' &&
process.env.NX_ADD_TS_PLUGIN !== 'false' parsedArgs.workspaces
) { ) {
return { return {
preset: Preset.TS, preset: Preset.TS,
@ -595,7 +596,7 @@ async function determineReactOptions(
let linter: undefined | 'none' | 'eslint'; let linter: undefined | 'none' | 'eslint';
let formatter: undefined | 'none' | 'prettier'; let formatter: undefined | 'none' | 'prettier';
const workspaces = parsedArgs.workspaces ?? false; const workspaces = parsedArgs.workspaces;
if (parsedArgs.preset && parsedArgs.preset !== Preset.React) { if (parsedArgs.preset && parsedArgs.preset !== Preset.React) {
preset = parsedArgs.preset; preset = parsedArgs.preset;
@ -764,7 +765,7 @@ async function determineVueOptions(
let linter: undefined | 'none' | 'eslint'; let linter: undefined | 'none' | 'eslint';
let formatter: undefined | 'none' | 'prettier'; let formatter: undefined | 'none' | 'prettier';
const workspaces = parsedArgs.workspaces ?? false; const workspaces = parsedArgs.workspaces;
if (parsedArgs.preset && parsedArgs.preset !== Preset.Vue) { if (parsedArgs.preset && parsedArgs.preset !== Preset.Vue) {
preset = parsedArgs.preset; preset = parsedArgs.preset;
@ -1032,7 +1033,7 @@ async function determineNodeOptions(
let linter: undefined | 'none' | 'eslint'; let linter: undefined | 'none' | 'eslint';
let formatter: undefined | 'none' | 'prettier'; let formatter: undefined | 'none' | 'prettier';
let unitTestRunner: undefined | 'none' | 'jest' = undefined; let unitTestRunner: undefined | 'none' | 'jest' = undefined;
const workspaces = parsedArgs.workspaces ?? false; const workspaces = parsedArgs.workspaces;
if (parsedArgs.preset) { if (parsedArgs.preset) {
preset = parsedArgs.preset; preset = parsedArgs.preset;

View File

@ -89,8 +89,7 @@ export async function initGeneratorInternal(
schema.addPlugin ??= schema.addPlugin ??=
process.env.NX_ADD_PLUGINS !== 'false' && process.env.NX_ADD_PLUGINS !== 'false' &&
nxJson.useInferencePlugins !== false; nxJson.useInferencePlugins !== false;
schema.addTsPlugin ??= schema.addTsPlugin ??= schema.addPlugin;
schema.addPlugin && process.env.NX_ADD_TS_PLUGIN !== 'false';
if (schema.addTsPlugin) { if (schema.addTsPlugin) {
await addPlugin( await addPlugin(

View File

@ -62,10 +62,6 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
const options = await normalizeOptions(host, schema); const options = await normalizeOptions(host, schema);
if (options.isUsingTsSolutionConfig) {
await addProjectToTsSolutionWorkspace(host, options.projectRoot);
}
if (options.publishable === true && !schema.importPath) { if (options.publishable === true && !schema.importPath) {
throw new Error( throw new Error(
`For publishable libs you have to provide a proper "--importPath" which needs to be a valid npm package name (e.g. my-awesome-lib or @myorg/my-lib)` `For publishable libs you have to provide a proper "--importPath" which needs to be a valid npm package name (e.g. my-awesome-lib or @myorg/my-lib)`
@ -112,6 +108,10 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
createFiles(host, options); createFiles(host, options);
if (options.isUsingTsSolutionConfig) {
await addProjectToTsSolutionWorkspace(host, options.projectRoot);
}
const lintTask = await addLinting(host, options); const lintTask = await addLinting(host, options);
tasks.push(lintTask); tasks.push(lintTask);

View File

@ -99,7 +99,7 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
opts.prefix !== undefined ? `--prefix=${opts.prefix}` : null, opts.prefix !== undefined ? `--prefix=${opts.prefix}` : null,
opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null, opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null,
opts.formatter ? `--formatter=${opts.formatter}` : null, opts.formatter ? `--formatter=${opts.formatter}` : null,
opts.workspaces ? `--workspaces` : null, opts.workspaces !== false ? `--workspaces` : `--no-workspaces`,
].filter((e) => !!e); ].filter((e) => !!e);
} }
} }

View File

@ -85,6 +85,7 @@ describe('@nx/workspace:generateWorkspaceFiles', () => {
appName, appName,
isCustomPreset: false, isCustomPreset: false,
nxCloud: nxCloud, nxCloud: nxCloud,
workspaces: true,
}); });
await formatFiles(tree); await formatFiles(tree);
const dir = join(__dirname, 'tmp', `${preset}-${nxCloud}`); const dir = join(__dirname, 'tmp', `${preset}-${nxCloud}`);

View File

@ -275,8 +275,8 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
options.preset === Preset.TsStandalone options.preset === Preset.TsStandalone
? './files-root-app' ? './files-root-app'
: (options.preset === Preset.TS && : (options.preset === Preset.TS &&
process.env.NX_ADD_PLUGINS !== 'false' && options.workspaces &&
process.env.NX_ADD_TS_PLUGIN !== 'false') || process.env.NX_ADD_PLUGINS !== 'false') ||
options.preset === Preset.NPM options.preset === Preset.NPM
? './files-package-based-repo' ? './files-package-based-repo'
: './files-integrated-repo'; : './files-integrated-repo';
@ -294,7 +294,7 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
async function createReadme( async function createReadme(
tree: Tree, tree: Tree,
{ name, appName, directory, preset, nxCloud }: NormalizedSchema, { name, appName, directory, preset, nxCloud, workspaces }: NormalizedSchema,
nxCloudToken?: string nxCloudToken?: string
) { ) {
const formattedNames = names(name); const formattedNames = names(name);
@ -314,8 +314,7 @@ async function createReadme(
isJsStandalone: preset === Preset.TsStandalone, isJsStandalone: preset === Preset.TsStandalone,
isTsPreset: preset === Preset.TS, isTsPreset: preset === Preset.TS,
isUsingNewTsSolutionSetup: isUsingNewTsSolutionSetup:
process.env.NX_ADD_PLUGINS !== 'false' && process.env.NX_ADD_PLUGINS !== 'false' && workspaces,
process.env.NX_ADD_TS_PLUGIN !== 'false',
isEmptyRepo: !appName, isEmptyRepo: !appName,
appName, appName,
generateAppCmd: presetInfo.generateAppCmd, generateAppCmd: presetInfo.generateAppCmd,
@ -416,7 +415,7 @@ function setUpWorkspacesInPackageJson(tree: Tree, options: NormalizedSchema) {
options.preset === Preset.NPM || options.preset === Preset.NPM ||
(options.preset === Preset.TS && (options.preset === Preset.TS &&
process.env.NX_ADD_PLUGINS !== 'false' && process.env.NX_ADD_PLUGINS !== 'false' &&
process.env.NX_ADD_TS_PLUGIN !== 'false') || options.workspaces) ||
((options.preset === Preset.Expo || ((options.preset === Preset.Expo ||
options.preset === Preset.NextJs || options.preset === Preset.NextJs ||
options.preset === Preset.ReactMonorepo || options.preset === Preset.ReactMonorepo ||

View File

@ -105,7 +105,7 @@
"workspaces": { "workspaces": {
"description": "Whether to use package manager workspaces.", "description": "Whether to use package manager workspaces.",
"type": "boolean", "type": "boolean",
"default": false "default": true
} }
}, },
"additionalProperties": true "additionalProperties": true

View File

@ -309,9 +309,7 @@ async function createPreset(tree: Tree, options: Schema) {
const { initGenerator } = require('@nx' + '/js'); const { initGenerator } = require('@nx' + '/js');
return initGenerator(tree, { return initGenerator(tree, {
formatter: options.formatter, formatter: options.formatter,
addTsPlugin: addTsPlugin: process.env.NX_ADD_PLUGINS !== 'false' && options.workspaces,
process.env.NX_ADD_PLUGINS !== 'false' &&
process.env.NX_ADD_TS_PLUGIN !== 'false',
}); });
} else if (options.preset === Preset.TsStandalone) { } else if (options.preset === Preset.TsStandalone) {
const { libraryGenerator } = require('@nx' + '/js'); const { libraryGenerator } = require('@nx' + '/js');

View File

@ -122,7 +122,7 @@
"workspaces": { "workspaces": {
"description": "Whether to use package manager workspaces.", "description": "Whether to use package manager workspaces.",
"type": "boolean", "type": "boolean",
"default": false "default": true
} }
}, },
"required": ["preset", "name"] "required": ["preset", "name"]