Skip to content

Commit 1759446

Browse files
committed
fix(@schematics/angular): do not add unnecessary dependency on @angular/ssr during migration
Prior to this change the Universal migration ran and added `@angular/ssr` even the workspace did not depend on `@nguniversal/` packages. Closes #26083 (cherry picked from commit c07cbd5)
1 parent dbdc7b2 commit 1759446

File tree

2 files changed

+66
-37
lines changed

2 files changed

+66
-37
lines changed

packages/schematics/angular/migrations/update-17/replace-nguniversal-engines.ts

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import { DirEntry, Rule, chain } from '@angular-devkit/schematics';
1010
import { addDependency } from '../../utility';
11-
import { removePackageJsonDependency } from '../../utility/dependencies';
11+
import { getPackageJsonDependency, removePackageJsonDependency } from '../../utility/dependencies';
1212
import { latestVersions } from '../../utility/latest-versions';
1313
import { allTargetOptions, getWorkspace } from '../../utility/workspace';
1414
import { Builders, ProjectType } from '../../utility/workspace-models';
@@ -36,6 +36,8 @@ function* visit(directory: DirEntry): IterableIterator<[fileName: string, conten
3636
}
3737
}
3838

39+
const UNIVERSAL_PACKAGES = ['@nguniversal/common', '@nguniversal/express-engine'];
40+
3941
/**
4042
* Regexp to match Universal packages.
4143
* @nguniversal/common/engine
@@ -45,53 +47,61 @@ function* visit(directory: DirEntry): IterableIterator<[fileName: string, conten
4547
const NGUNIVERSAL_PACKAGE_REGEXP = /@nguniversal\/(common(\/engine)?|express-engine)/g;
4648

4749
export default function (): Rule {
48-
return chain([
49-
async (tree) => {
50-
// Replace server file.
51-
const workspace = await getWorkspace(tree);
52-
for (const [, project] of workspace.projects) {
53-
if (project.extensions.projectType !== ProjectType.Application) {
54-
continue;
55-
}
50+
return async (tree) => {
51+
const hasUniversalDeps = UNIVERSAL_PACKAGES.some((d) => getPackageJsonDependency(tree, d));
52+
if (!hasUniversalDeps) {
53+
return;
54+
}
5655

57-
const serverMainFiles = new Map<string /** Main Path */, string /** Output Path */>();
58-
for (const [, target] of project.targets) {
59-
if (target.builder !== Builders.Server) {
56+
return chain([
57+
async (tree) => {
58+
// Replace server file.
59+
const workspace = await getWorkspace(tree);
60+
for (const [, project] of workspace.projects) {
61+
if (project.extensions.projectType !== ProjectType.Application) {
6062
continue;
6163
}
6264

63-
const outputPath = project.targets.get('build')?.options?.outputPath;
65+
const serverMainFiles = new Map<string /** Main Path */, string /** Output Path */>();
66+
for (const [, target] of project.targets) {
67+
if (target.builder !== Builders.Server) {
68+
continue;
69+
}
70+
71+
const outputPath = project.targets.get('build')?.options?.outputPath;
6472

65-
for (const [, { main }] of allTargetOptions(target, false)) {
66-
if (
67-
typeof main === 'string' &&
68-
typeof outputPath === 'string' &&
69-
tree.readText(main).includes('ngExpressEngine')
70-
) {
71-
serverMainFiles.set(main, outputPath);
73+
for (const [, { main }] of allTargetOptions(target, false)) {
74+
if (
75+
typeof main === 'string' &&
76+
typeof outputPath === 'string' &&
77+
tree.readText(main).includes('ngExpressEngine')
78+
) {
79+
serverMainFiles.set(main, outputPath);
80+
}
7281
}
7382
}
74-
}
7583

76-
// Replace server file
77-
for (const [path, outputPath] of serverMainFiles.entries()) {
78-
tree.rename(path, path + '.bak');
79-
tree.create(path, getServerFileContents(outputPath));
84+
// Replace server file
85+
for (const [path, outputPath] of serverMainFiles.entries()) {
86+
tree.rename(path, path + '.bak');
87+
tree.create(path, getServerFileContents(outputPath));
88+
}
8089
}
81-
}
8290

83-
// Replace all import specifiers in all files.
84-
for (const file of visit(tree.root)) {
85-
const [path, content] = file;
86-
tree.overwrite(path, content.replaceAll(NGUNIVERSAL_PACKAGE_REGEXP, '@angular/ssr'));
87-
}
91+
// Replace all import specifiers in all files.
92+
for (const file of visit(tree.root)) {
93+
const [path, content] = file;
94+
tree.overwrite(path, content.replaceAll(NGUNIVERSAL_PACKAGE_REGEXP, '@angular/ssr'));
95+
}
8896

89-
// Remove universal packages from deps.
90-
removePackageJsonDependency(tree, '@nguniversal/express-engine');
91-
removePackageJsonDependency(tree, '@nguniversal/common');
92-
},
93-
addDependency('@angular/ssr', latestVersions.AngularSSR),
94-
]);
97+
// Remove universal packages from deps.
98+
for (const name of UNIVERSAL_PACKAGES) {
99+
removePackageJsonDependency(tree, name);
100+
}
101+
},
102+
addDependency('@angular/ssr', latestVersions.AngularSSR),
103+
]);
104+
};
95105
}
96106

97107
function getServerFileContents(outputPath: string): string {

packages/schematics/angular/migrations/update-17/replace-nguniversal-engines_spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,25 @@ if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
160160
expect(dependencies['@angular/ssr']).toBeDefined();
161161
});
162162

163+
it(`should not add '@angular/ssr' when there is no dependency on '@nguniversal'`, async () => {
164+
tree.overwrite(
165+
'/package.json',
166+
JSON.stringify(
167+
{
168+
dependencies: {
169+
'@angular/common': '0.0.0',
170+
},
171+
},
172+
undefined,
173+
2,
174+
),
175+
);
176+
177+
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
178+
const { dependencies } = JSON.parse(newTree.readContent('/package.json'));
179+
expect(dependencies['@angular/ssr']).toBeUndefined();
180+
});
181+
163182
it(`should replace imports from '@nguniversal/common' to '@angular/ssr'`, async () => {
164183
tree.create(
165184
'file.ts',

0 commit comments

Comments
 (0)