Skip to content

Commit

Permalink
feat(@schematics/angular): remove generation of `BrowserModule.withSe…
Browse files Browse the repository at this point in the history
…rverTransition`

 This commit removes generation of `.withServerTransition` in the universal schematic as is deprecated.

 DEPRECATED: the `app-id` option in the app-shell and universal schematics has been deprecated without replacement. See: angular/angular#49422 for more information about the rational of this change.
  • Loading branch information
alan-agius4 authored and angular-robot[bot] committed Mar 24, 2023
1 parent c09c1b3 commit c9e84d0
Show file tree
Hide file tree
Showing 7 changed files with 7 additions and 105 deletions.
Expand Up @@ -58,7 +58,7 @@ describe('AppShell Builder', () => {
AppComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
BrowserModule,
AppRoutingModule,
RouterModule
],
Expand Down Expand Up @@ -116,14 +116,6 @@ describe('AppShell Builder', () => {
};

it('works (basic)', async () => {
host.replaceInFile(
'src/app/app.module.ts',
/ {4}BrowserModule/,
`
BrowserModule.withServerTransition({ appId: 'some-app' })
`,
);

const run = await architect.scheduleTarget(target);
const output = await run.result;
await run.stop();
Expand Down
3 changes: 2 additions & 1 deletion packages/schematics/angular/app-shell/schema.json
Expand Up @@ -22,7 +22,8 @@
"type": "string",
"format": "html-selector",
"description": "The application ID to use in withServerTransition().",
"default": "serverApp"
"default": "serverApp",
"x-deprecated": "This option is no longer used."
},
"main": {
"type": "string",
Expand Down
52 changes: 0 additions & 52 deletions packages/schematics/angular/universal/index.ts
Expand Up @@ -21,15 +21,12 @@ import {
url,
} from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import * as ts from '../third_party/github.com/Microsoft/TypeScript/lib/typescript';
import { findNode, getDecoratorMetadata } from '../utility/ast-utils';
import {
NodeDependencyType,
addPackageJsonDependency,
getPackageJsonDependency,
} from '../utility/dependencies';
import { latestVersions } from '../utility/latest-versions';
import { findBootstrapModulePath } from '../utility/ng-ast-utils';
import { relativePathToWorkspaceRoot } from '../utility/paths';
import { targetBuildNotFoundError } from '../utility/project-targets';
import { getWorkspace, updateWorkspace } from '../utility/workspace';
Expand Down Expand Up @@ -95,54 +92,6 @@ function updateConfigFile(options: UniversalOptions, tsConfigDirectory: Path): R
});
}

function findBrowserModuleImport(host: Tree, modulePath: string): ts.Node {
const moduleFileText = host.readText(modulePath);
const source = ts.createSourceFile(modulePath, moduleFileText, ts.ScriptTarget.Latest, true);

const decoratorMetadata = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0];
const browserModuleNode = findNode(decoratorMetadata, ts.SyntaxKind.Identifier, 'BrowserModule');

if (browserModuleNode === null) {
throw new SchematicsException(`Cannot find BrowserModule import in ${modulePath}`);
}

return browserModuleNode;
}

function addServerTransition(
options: UniversalOptions,
mainFile: string,
clientProjectRoot: string,
): Rule {
return (host: Tree) => {
const mainPath = normalize('/' + mainFile);

const bootstrapModuleRelativePath = findBootstrapModulePath(host, mainPath);
const bootstrapModulePath = normalize(
`/${clientProjectRoot}/src/${bootstrapModuleRelativePath}.ts`,
);

const browserModuleImport = findBrowserModuleImport(host, bootstrapModulePath);
const transitionCallRecorder = host.beginUpdate(bootstrapModulePath);
const position = browserModuleImport.pos + browserModuleImport.getFullWidth();
const browserModuleFullImport = browserModuleImport.parent;

if (browserModuleFullImport.getText() === 'BrowserModule.withServerTransition') {
// Remove any existing withServerTransition as otherwise we might have incorrect configuration.
transitionCallRecorder.remove(
position,
browserModuleFullImport.parent.getFullWidth() - browserModuleImport.getFullWidth(),
);
}

transitionCallRecorder.insertLeft(
position,
`.withServerTransition({ appId: '${options.appId}' })`,
);
host.commitUpdate(transitionCallRecorder);
};
}

function addDependencies(): Rule {
return (host: Tree) => {
const coreDep = getPackageJsonDependency(host, '@angular/core');
Expand Down Expand Up @@ -214,7 +163,6 @@ export default function (options: UniversalOptions): Rule {
mergeWith(rootSource),
addDependencies(),
updateConfigFile(options, tsConfigDirectory),
addServerTransition(options, clientBuildOptions.main, clientProject.root),
]);
};
}
40 changes: 0 additions & 40 deletions packages/schematics/angular/universal/index_spec.ts
Expand Up @@ -151,46 +151,6 @@ describe('Universal Schematic', () => {
expect(targets.build.options.outputPath).toEqual('dist/bar/browser');
});

it('should add a server transition to BrowserModule import', async () => {
const tree = await schematicRunner.runSchematic('universal', defaultOptions, appTree);
const filePath = '/projects/bar/src/app/app.module.ts';
const contents = tree.readContent(filePath);
expect(contents).toMatch(/BrowserModule\.withServerTransition\({ appId: 'serverApp' }\)/);
});

it('should replace existing `withServerTransition` in BrowserModule import', async () => {
const filePath = '/projects/bar/src/app/app.module.ts';
appTree.overwrite(
filePath,
`
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'foo' }),
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
`,
);
const tree = await schematicRunner.runSchematic('universal', defaultOptions, appTree);
const contents = tree.readContent(filePath);
console.log(contents);

expect(contents).toContain(`BrowserModule.withServerTransition({ appId: 'serverApp' }),`);
expect(contents).not.toContain(`withServerTransition({ appId: 'foo' })`);
});

it('should install npm dependencies', async () => {
await schematicRunner.runSchematic('universal', defaultOptions, appTree);
expect(schematicRunner.tasks.length).toBe(1);
Expand Down
3 changes: 2 additions & 1 deletion packages/schematics/angular/universal/schema.json
Expand Up @@ -17,7 +17,8 @@
"type": "string",
"format": "html-selector",
"description": "The application identifier to use for transition.",
"default": "serverApp"
"default": "serverApp",
"x-deprecated": "This option is no longer used."
},
"main": {
"type": "string",
Expand Down
2 changes: 1 addition & 1 deletion packages/schematics/angular/utility/ng-ast-utils.ts
Expand Up @@ -46,7 +46,7 @@ export function findBootstrapModuleCall(host: Tree, mainPath: string): ts.CallEx
return bootstrapCall;
}

export function findBootstrapModulePath(host: Tree, mainPath: string): string {
function findBootstrapModulePath(host: Tree, mainPath: string): string {
const bootstrapCall = findBootstrapModuleCall(host, mainPath);
if (!bootstrapCall) {
throw new SchematicsException('Bootstrap call not found');
Expand Down
Expand Up @@ -68,7 +68,7 @@ export default async function () {
export default () => bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(BrowserModule.withServerTransition({ appId: 'app' })),
importProvidersFrom(BrowserModule),
importProvidersFrom(ServerModule),
provideRouter([{ path: 'shell', component: AppShellComponent }]),
],
Expand Down

0 comments on commit c9e84d0

Please sign in to comment.