Skip to content

Commit dc6b6ea

Browse files
committed
feat(@schematics/angular): add migration to replace usages of @nguniversal/builders
This migration replaces usages of `@nguniversal/builders` with `@angular-devkit/build-angular`.
1 parent 2e0a6fe commit dc6b6ea

File tree

3 files changed

+165
-1
lines changed

3 files changed

+165
-1
lines changed
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
{
2-
"schematics": {}
2+
"schematics": {
3+
"replace-nguniversal-builders": {
4+
"version": "17.0.0",
5+
"factory": "./update-17/replace-nguniversal-builders",
6+
"description": "Replace usages of '@nguniversal/builders' with '@angular-devkit/build-angular'."
7+
}
8+
}
39
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import { Rule, chain } from '@angular-devkit/schematics';
10+
import { removePackageJsonDependency } from '../../utility/dependencies';
11+
import { allTargetOptions, updateWorkspace } from '../../utility/workspace';
12+
import { ProjectType } from '../../utility/workspace-models';
13+
14+
export default function (): Rule {
15+
return chain([
16+
updateWorkspace((workspace) => {
17+
for (const [, project] of workspace.projects) {
18+
if (project.extensions.projectType !== ProjectType.Application) {
19+
// Only interested in application projects since these changes only effects application builders
20+
continue;
21+
}
22+
23+
for (const [, target] of project.targets) {
24+
if (target.builder === '@nguniversal/builders:ssr-dev-server') {
25+
target.builder = '@angular-devkit/build-angular:ssr-dev-server';
26+
} else if (target.builder === '@nguniversal/builders:prerender') {
27+
target.builder = '@angular-devkit/build-angular:prerender';
28+
for (const [, options] of allTargetOptions(target, false)) {
29+
// Remove and replace builder options
30+
if (options['guessRoutes'] !== undefined) {
31+
options['discoverRoutes'] = options['guessRoutes'];
32+
delete options['guessRoutes'];
33+
}
34+
35+
if (options['numProcesses'] !== undefined) {
36+
delete options['numProcesses'];
37+
}
38+
}
39+
}
40+
}
41+
}
42+
}),
43+
(host) => {
44+
removePackageJsonDependency(host, '@nguniversal/builders');
45+
},
46+
]);
47+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import { EmptyTree } from '@angular-devkit/schematics';
10+
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
11+
import { ProjectType, WorkspaceSchema } from '../../utility/workspace-models';
12+
13+
function createWorkSpaceConfig(tree: UnitTestTree) {
14+
const angularConfig: WorkspaceSchema = {
15+
version: 1,
16+
projects: {
17+
app: {
18+
root: '/project/lib',
19+
sourceRoot: '/project/app/src',
20+
projectType: ProjectType.Application,
21+
prefix: 'app',
22+
architect: {
23+
'serve-ssr': {
24+
builder: '@nguniversal/builders:ssr-dev-server',
25+
options: {
26+
browserTarget: 'appprerender:build',
27+
serverTarget: 'appprerender:server',
28+
},
29+
configurations: {
30+
production: {
31+
browserTarget: 'appprerender:build:production',
32+
serverTarget: 'appprerender:server:production',
33+
},
34+
},
35+
},
36+
prerender: {
37+
builder: '@nguniversal/builders:prerender',
38+
options: {
39+
browserTarget: 'appprerender:build:production',
40+
serverTarget: 'appprerender:server:production',
41+
numProcesses: 1,
42+
guessRoutes: false,
43+
},
44+
},
45+
},
46+
},
47+
},
48+
};
49+
50+
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
51+
}
52+
53+
describe(`Migration to replace '@nguniversal/builders' with '@angular-devkit/build-angular'`, () => {
54+
const schematicName = 'replace-nguniversal-builders';
55+
56+
const schematicRunner = new SchematicTestRunner(
57+
'migrations',
58+
require.resolve('../migration-collection.json'),
59+
);
60+
61+
let tree: UnitTestTree;
62+
beforeEach(() => {
63+
tree = new UnitTestTree(new EmptyTree());
64+
createWorkSpaceConfig(tree);
65+
tree.create(
66+
'/package.json',
67+
JSON.stringify(
68+
{
69+
devDependencies: {
70+
'@nguniversal/builders': '0.0.0',
71+
},
72+
},
73+
undefined,
74+
2,
75+
),
76+
);
77+
});
78+
79+
it(`should remove '@nguniversal/builders' from devDependencies`, async () => {
80+
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
81+
const { devDependencies } = JSON.parse(newTree.readContent('/package.json'));
82+
expect(devDependencies['@nguniversal/builders']).toBeUndefined();
83+
});
84+
85+
it(`should replace '@nguniversal/builders:ssr-dev-server' target`, async () => {
86+
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
87+
const {
88+
projects: { app },
89+
} = JSON.parse(newTree.readContent('/angular.json'));
90+
expect(app.architect['serve-ssr'].builder).toBe('@angular-devkit/build-angular:ssr-dev-server');
91+
});
92+
93+
it(`should replace '@nguniversal/builders:prerender' target`, async () => {
94+
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
95+
const {
96+
projects: { app },
97+
} = JSON.parse(newTree.readContent('/angular.json'));
98+
expect(app.architect['prerender'].builder).toBe('@angular-devkit/build-angular:prerender');
99+
});
100+
101+
it(`should replace old '@nguniversal/builders:prerender' options`, async () => {
102+
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
103+
const {
104+
projects: { app },
105+
} = JSON.parse(newTree.readContent('/angular.json'));
106+
const { guessRoutes, numProcesses, discoverRoutes } = app.architect['prerender'].options;
107+
expect(guessRoutes).toBeUndefined();
108+
expect(discoverRoutes).toBeFalse();
109+
expect(numProcesses).toBeUndefined();
110+
});
111+
});

0 commit comments

Comments
 (0)