Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(@schematics/angular): remove generation of BrowserModule.withServerTransition #24909

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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