feat(angular): remove decorate-angular-cli (#14226)

This commit is contained in:
Colum Ferry 2023-01-09 21:34:09 +00:00 committed by GitHub
parent c82f7c3848
commit a5707c8b75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 4 additions and 218 deletions

View File

@ -16,7 +16,6 @@ This will enable you to use the Nx CLI in your existing Angular CLI workspace wh
- The `nx`, `@nrwl/workspace` and `prettier` packages will be installed. - The `nx`, `@nrwl/workspace` and `prettier` packages will be installed.
- An `nx.json` file will be created in the root of your workspace. - An `nx.json` file will be created in the root of your workspace.
- A `decorate-angular-cli.js` file will be added to the root of your workspace, and a `postinstall` script will be added to your `package.json` to run this script when your dependencies are updated. (The script forwards the `ng` commands to the Nx CLI (`nx`) to enable features such as [Computation Caching](/concepts/how-caching-works).)
- For an Angular 15+ repo, the `angular.json` file is split into separate `project.json` files for each project. - For an Angular 15+ repo, the `angular.json` file is split into separate `project.json` files for each project.
After the process completes, you can continue using the same `serve/build/lint/test` commands you are used to. After the process completes, you can continue using the same `serve/build/lint/test` commands you are used to.
@ -104,7 +103,6 @@ After the changes are applied, your workspace file structure should look similar
├── .gitignore ├── .gitignore
├── .prettierignore ├── .prettierignore
├── .prettierrc ├── .prettierrc
├── decorate-angular-cli.js
├── karma.conf.js ├── karma.conf.js
├── nx.json ├── nx.json
├── package.json ├── package.json
@ -359,7 +357,6 @@ The script will make the following changes:
- If you opted into Nx Cloud, `@nrwl/nx-cloud` will be installed as well. - If you opted into Nx Cloud, `@nrwl/nx-cloud` will be installed as well.
- If your project's Angular version is greater than or equal to version 13, then the `@nrwl/angular` package will be installed as well. - If your project's Angular version is greater than or equal to version 13, then the `@nrwl/angular` package will be installed as well.
- Creates an `nx.json` file in the root of your workspace. - Creates an `nx.json` file in the root of your workspace.
- Adds a `decorate-angular-cli.js` to the root of your workspace, and a `postinstall` script in your `package.json` to run the script when your dependencies are updated. The script forwards the `ng` commands to the Nx CLI (`nx`) to enable features such as [Computation Caching](/concepts/how-caching-works).
By running this command and accepting Nx Cloud, Nx distributed caching is now enabled. By running this command and accepting Nx Cloud, Nx distributed caching is now enabled.

View File

@ -129,12 +129,11 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
const updatedPackageJson = readJson('package.json'); const updatedPackageJson = readJson('package.json');
expect(updatedPackageJson.description).toEqual('some description'); expect(updatedPackageJson.description).toEqual('some description');
expect(updatedPackageJson.scripts).toEqual({ expect(updatedPackageJson.scripts).toEqual({
ng: 'nx', ng: 'ng',
start: 'nx serve', start: 'nx serve',
build: 'nx build', build: 'nx build',
watch: 'nx build --watch --configuration development', watch: 'nx build --watch --configuration development',
test: 'nx test', test: 'nx test',
postinstall: 'node ./decorate-angular-cli.js',
}); });
expect(updatedPackageJson.devDependencies['@nrwl/workspace']).toBeDefined(); expect(updatedPackageJson.devDependencies['@nrwl/workspace']).toBeDefined();
expect(updatedPackageJson.devDependencies['@angular/cli']).toBeDefined(); expect(updatedPackageJson.devDependencies['@angular/cli']).toBeDefined();

View File

@ -148,33 +148,14 @@ describe('workspace', () => {
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, {});
expect(readJson(tree, 'package.json').scripts).toStrictEqual({ expect(readJson(tree, 'package.json').scripts).toStrictEqual({
ng: 'nx', ng: 'ng',
start: 'nx serve', start: 'nx serve',
build: 'nx build', build: 'nx build',
watch: 'nx build --watch --configuration development', watch: 'nx build --watch --configuration development',
test: 'nx test', test: 'nx test',
postinstall: 'node ./decorate-angular-cli.js',
}); });
}); });
it('should handle existing postinstall script', async () => {
tree.write(
'package.json',
JSON.stringify({
name: '@my-org/my-monorepo',
scripts: {
postinstall: 'node some-awesome-script.js',
},
})
);
await migrateFromAngularCli(tree, {});
expect(readJson(tree, 'package.json').scripts.postinstall).toEqual(
'node some-awesome-script.js && node ./decorate-angular-cli.js'
);
});
it('should remove the angular.json file', async () => { it('should remove the angular.json file', async () => {
tree.write( tree.write(
'/angular.json', '/angular.json',
@ -586,14 +567,6 @@ describe('workspace', () => {
expect(readJson(tree, 'nx.json')).toMatchSnapshot(); expect(readJson(tree, 'nx.json')).toMatchSnapshot();
}); });
it('should create decorate-angular-cli.js', async () => {
await migrateFromAngularCli(tree, { preserveAngularCliLayout: true });
expect(tree.exists('/decorate-angular-cli.js')).toBe(true);
const { scripts } = readJson(tree, 'package.json');
expect(scripts.postinstall).toBe('node ./decorate-angular-cli.js');
});
it('should support multiple projects', async () => { it('should support multiple projects', async () => {
const angularJson = { const angularJson = {
$schema: './node_modules/@angular/cli/lib/config/schema.json', $schema: './node_modules/@angular/cli/lib/config/schema.json',
@ -663,11 +636,9 @@ describe('workspace', () => {
await migrateFromAngularCli(tree, { preserveAngularCliLayout: true }); await migrateFromAngularCli(tree, { preserveAngularCliLayout: true });
expect(tree.exists('angular.json')).toBe(false); expect(tree.exists('angular.json')).toBe(false);
expect(tree.exists('decorate-angular-cli.js')).toBe(true);
expect(tree.exists('.prettierignore')).toBe(true); expect(tree.exists('.prettierignore')).toBe(true);
expect(tree.exists('.prettierrc')).toBe(true); expect(tree.exists('.prettierrc')).toBe(true);
const { scripts } = readJson(tree, 'package.json'); const { scripts } = readJson(tree, 'package.json');
expect(scripts.postinstall).toBe('node ./decorate-angular-cli.js');
expect(readJson(tree, 'nx.json')).toMatchSnapshot(); expect(readJson(tree, 'nx.json')).toMatchSnapshot();
expect(readJson(tree, 'project.json')).toMatchSnapshot(); expect(readJson(tree, 'project.json')).toMatchSnapshot();
expect(readJson(tree, 'projects/app2/project.json')).toMatchSnapshot(); expect(readJson(tree, 'projects/app2/project.json')).toMatchSnapshot();

View File

@ -16,7 +16,6 @@ import {
createNxJson, createNxJson,
createRootKarmaConfig, createRootKarmaConfig,
createWorkspaceFiles, createWorkspaceFiles,
decorateAngularCli,
deleteAngularJson, deleteAngularJson,
deleteGitKeepFilesIfNotNeeded, deleteGitKeepFilesIfNotNeeded,
formatFilesTask, formatFilesTask,
@ -53,7 +52,6 @@ export async function migrateFromAngularCli(
} }
); );
createNxJson(tree, options, angularJson.defaultProject); createNxJson(tree, options, angularJson.defaultProject);
decorateAngularCli(tree);
updateVsCodeRecommendedExtensions(tree); updateVsCodeRecommendedExtensions(tree);
await updatePrettierConfig(tree); await updatePrettierConfig(tree);
@ -96,7 +94,6 @@ export async function migrateFromAngularCli(
updateWorkspaceConfigDefaults(tree); updateWorkspaceConfigDefaults(tree);
updateRootTsConfig(tree); updateRootTsConfig(tree);
updatePackageJson(tree); updatePackageJson(tree);
decorateAngularCli(tree);
await createWorkspaceFiles(tree); await createWorkspaceFiles(tree);
// migrate all projects // migrate all projects

View File

@ -16,9 +16,6 @@ import { deduceDefaultBase } from '@nrwl/workspace/src/utilities/default-base';
import { resolveUserExistingPrettierConfig } from '@nrwl/workspace/src/utilities/prettier'; import { resolveUserExistingPrettierConfig } from '@nrwl/workspace/src/utilities/prettier';
import { getRootTsConfigPathInTree } from '@nrwl/workspace/src/utilities/typescript'; import { getRootTsConfigPathInTree } from '@nrwl/workspace/src/utilities/typescript';
import { prettierVersion } from '@nrwl/workspace/src/utils/versions'; import { prettierVersion } from '@nrwl/workspace/src/utils/versions';
import { readFileSync } from 'fs';
import { readModulePackageJson } from 'nx/src/utils/package-json';
import { dirname, join } from 'path';
import { angularDevkitVersion, nxVersion } from '../../../utils/versions'; import { angularDevkitVersion, nxVersion } from '../../../utils/versions';
import type { ProjectMigrator } from '../migrators'; import type { ProjectMigrator } from '../migrators';
import type { GeneratorOptions } from '../schema'; import type { GeneratorOptions } from '../schema';
@ -136,37 +133,6 @@ function getWorkspaceCommonTargets(tree: Tree): {
return targets; return targets;
} }
export function decorateAngularCli(tree: Tree): void {
const nrwlWorkspacePath = readModulePackageJson('@nrwl/workspace').path;
const decorateCli = readFileSync(
join(
dirname(nrwlWorkspacePath),
'src/generators/utils/decorate-angular-cli.js__tmpl__'
),
'utf-8'
);
tree.write('decorate-angular-cli.js', decorateCli);
updateJson(tree, 'package.json', (json) => {
if (
json.scripts &&
json.scripts.postinstall &&
!json.scripts.postinstall.includes('decorate-angular-cli.js')
) {
// if exists, add execution of this script
json.scripts.postinstall += ' && node ./decorate-angular-cli.js';
} else {
json.scripts ??= {};
// if doesn't exist, set to execute this script
json.scripts.postinstall = 'node ./decorate-angular-cli.js';
}
if (json.scripts.ng) {
json.scripts.ng = 'nx';
}
return json;
});
}
export function updateWorkspaceConfigDefaults(tree: Tree): void { export function updateWorkspaceConfigDefaults(tree: Tree): void {
const nxJson = readNxJson(tree); const nxJson = readNxJson(tree);
delete (nxJson as any).newProjectRoot; delete (nxJson as any).newProjectRoot;

View File

@ -1 +0,0 @@
export * from 'nx/src/adapter/decorate-cli';

View File

@ -1,16 +0,0 @@
import { readFileSync, writeFileSync } from 'fs';
export function decorateCli() {
const path = 'node_modules/@angular/cli/lib/cli/index.js';
const angularCLIInit = readFileSync(path, 'utf-8');
const start = angularCLIInit.indexOf(`(options) {`) + 11;
const newContent = `${angularCLIInit.slice(0, start)}
if (!process.env['NX_CLI_SET']) {
require('nx/bin/nx');
return new Promise(function(res, rej) {});
}
${angularCLIInit.substring(start)}
`;
writeFileSync(path, newContent);
}

View File

@ -55,11 +55,6 @@
"ignore": ["**/tsconfig*.json", "project.json", ".eslintrc.json"], "ignore": ["**/tsconfig*.json", "project.json", ".eslintrc.json"],
"output": "/" "output": "/"
}, },
{
"input": "packages/workspace",
"glob": "**/**/decorate-angular-cli.js__tmpl__",
"output": "/"
},
{ {
"input": "packages/workspace", "input": "packages/workspace",
"glob": "**/*.{js,css,html,svg}", "glob": "**/*.{js,css,html,svg}",

View File

@ -14,10 +14,7 @@ Object {
"license": "MIT", "license": "MIT",
"name": "my-workspace", "name": "my-workspace",
"private": true, "private": true,
"scripts": Object { "scripts": Object {},
"ng": "nx",
"postinstall": "node ./decorate-angular-cli.js",
},
"version": "0.0.0", "version": "0.0.0",
} }
`; `;

View File

@ -198,37 +198,6 @@ describe('@nrwl/workspace:generateWorkspaceFiles', () => {
expect(recommendations).toMatchSnapshot(); expect(recommendations).toMatchSnapshot();
}); });
it('should add decorate-angular-cli when used with angular cli', async () => {
await generateWorkspaceFiles(tree, {
name: 'proj',
directory: 'proj',
preset: Preset.AngularMonorepo,
defaultBase: 'main',
});
expect(tree.exists('/proj/decorate-angular-cli.js')).toBe(true);
const { scripts } = readJson(tree, '/proj/package.json');
expect(scripts).toMatchInlineSnapshot(`
Object {
"ng": "nx",
"postinstall": "node ./decorate-angular-cli.js",
}
`);
});
it('should not add decorate-angular-cli when used with nx cli', async () => {
await generateWorkspaceFiles(tree, {
name: 'proj',
directory: 'proj',
preset: Preset.Empty,
defaultBase: 'main',
});
expect(tree.exists('/proj/decorate-angular-cli.js')).toBe(false);
const { scripts } = readJson(tree, '/proj/package.json');
expect(scripts).toMatchInlineSnapshot(`Object {}`);
});
it('should create a workspace using NPM preset (npm package manager)', async () => { it('should create a workspace using NPM preset (npm package manager)', async () => {
tree.write('/proj/package.json', JSON.stringify({})); tree.write('/proj/package.json', JSON.stringify({}));
await generateWorkspaceFiles(tree, { await generateWorkspaceFiles(tree, {

View File

@ -15,7 +15,6 @@ import {
prettierVersion, prettierVersion,
typescriptVersion, typescriptVersion,
} from '../../utils/versions'; } from '../../utils/versions';
import { readFileSync } from 'fs';
import { join, join as pathJoin } from 'path'; import { join, join as pathJoin } from 'path';
import { Preset } from '../utils/presets'; import { Preset } from '../utils/presets';
import { deduceDefaultBase } from '../../utilities/default-base'; import { deduceDefaultBase } from '../../utilities/default-base';
@ -37,9 +36,7 @@ export async function generateWorkspaceFiles(
createFiles(tree, options); createFiles(tree, options);
createNxJson(tree, options); createNxJson(tree, options);
createPrettierrc(tree, options); createPrettierrc(tree, options);
if (options.preset === Preset.AngularMonorepo) {
decorateAngularClI(tree, options);
}
const [packageMajor] = getPackageManagerVersion( const [packageMajor] = getPackageManagerVersion(
options.packageManager as PackageManager options.packageManager as PackageManager
).split('.'); ).split('.');
@ -56,13 +53,6 @@ export async function generateWorkspaceFiles(
await formatFiles(tree); await formatFiles(tree);
} }
function decorateAngularClI(tree: Tree, options: NormalizedSchema) {
const decorateCli = readFileSync(
pathJoin(__dirname as any, '..', 'utils', 'decorate-angular-cli.js__tmpl__')
).toString();
tree.write(join(options.directory, 'decorate-angular-cli.js'), decorateCli);
}
function setPresetProperty(tree: Tree, options: NormalizedSchema) { function setPresetProperty(tree: Tree, options: NormalizedSchema) {
updateJson(tree, join(options.directory, 'nx.json'), (json) => { updateJson(tree, join(options.directory, 'nx.json'), (json) => {
if (options.preset === Preset.Core || options.preset === Preset.NPM) { if (options.preset === Preset.Core || options.preset === Preset.NPM) {
@ -204,16 +194,6 @@ function createYarnrcYml(tree: Tree, options: NormalizedSchema) {
} }
function addNpmScripts(tree: Tree, options: NormalizedSchema) { function addNpmScripts(tree: Tree, options: NormalizedSchema) {
if (options.preset === Preset.AngularMonorepo) {
updateJson(tree, join(options.directory, 'package.json'), (json) => {
Object.assign(json.scripts, {
ng: 'nx',
postinstall: 'node ./decorate-angular-cli.js',
});
return json;
});
}
if ( if (
options.preset === Preset.AngularStandalone || options.preset === Preset.AngularStandalone ||
options.preset === Preset.ReactStandalone options.preset === Preset.ReactStandalone

View File

@ -1,68 +0,0 @@
/**
* This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching
* and faster execution of tasks.
*
* It does this by:
*
* - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command.
* - Symlinking the ng to nx command, so all commands run through the Nx CLI
* - Updating the package.json postinstall script to give you control over this script
*
* The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it.
* Every command you run should work the same when using the Nx CLI, except faster.
*
* Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case,
* will point to nx, which will perform optimizations before running your task.
*
* To opt out of this patch:
* - Replace occurrences of nx with ng in your package.json
* - Remove the script from your postinstall script in your package.json
* - Delete and reinstall your node_modules
*/
const fs = require('fs');
const os = require('os');
const cp = require('child_process');
const isWindows = os.platform() === 'win32';
let output;
try {
output = require('@nrwl/workspace').output;
} catch (e) {
console.warn('Angular CLI could not be decorated to enable computation caching. Please ensure @nrwl/workspace is installed.');
process.exit(0);
}
/**
* Symlink of ng to nx, so you can keep using `ng build/test/lint` and still
* invoke the Nx CLI and get the benefits of computation caching.
*/
function symlinkNgCLItoNxCLI() {
try {
const ngPath = './node_modules/.bin/ng';
const nxPath = './node_modules/.bin/nx';
if (isWindows) {
/**
* This is the most reliable way to create symlink-like behavior on Windows.
* Such that it works in all shells and works with npx.
*/
['', '.cmd', '.ps1'].forEach(ext => {
if (fs.existsSync(nxPath + ext)) fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext));
});
} else {
// If unix-based, symlink
cp.execSync(`ln -sf ./nx ${ngPath}`);
}
}
catch(e) {
output.error({ title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message });
throw e;
}
}
try {
symlinkNgCLItoNxCLI();
require('nx/src/adapter/decorate-cli').decorateCli();
output.log({ title: 'Angular CLI has been decorated to enable computation caching.' });
} catch(e) {
output.error({ title: 'Decoration of the Angular CLI did not complete successfully' });
}