Skip to content

Commit

Permalink
feat(angular): integrate withEventReplay() in `provideClientHydrati…
Browse files Browse the repository at this point in the history
…on` for ssr apps
  • Loading branch information
leosvelperez committed Nov 12, 2024
1 parent 4a76f00 commit 59d8738
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ exports[`Host App Generator --ssr should generate the correct files 1`] = `
import {
BrowserModule,
provideClientHydration,
withEventReplay,
} from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
Expand All @@ -61,7 +62,7 @@ import { NxWelcomeComponent } from './nx-welcome.component';
@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
providers: [provideClientHydration()],
providers: [provideClientHydration(withEventReplay())],
bootstrap: [AppComponent],
})
export class AppModule {}
Expand Down Expand Up @@ -405,11 +406,14 @@ exports[`Host App Generator --ssr should generate the correct files for standalo
"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import {
provideClientHydration,
withEventReplay,
} from '@angular/platform-browser';
export const appConfig: ApplicationConfig = {
providers: [
provideClientHydration(),
provideClientHydration(withEventReplay()),
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(appRoutes),
],
Expand Down Expand Up @@ -627,11 +631,14 @@ exports[`Host App Generator --ssr should generate the correct files for standalo
"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import {
provideClientHydration,
withEventReplay,
} from '@angular/platform-browser';
export const appConfig: ApplicationConfig = {
providers: [
provideClientHydration(),
provideClientHydration(withEventReplay()),
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(appRoutes),
],
Expand Down Expand Up @@ -703,6 +710,7 @@ exports[`Host App Generator --ssr should generate the correct files when --types
import {
BrowserModule,
provideClientHydration,
withEventReplay,
} from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
Expand All @@ -712,7 +720,7 @@ import { NxWelcomeComponent } from './nx-welcome.component';
@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
providers: [provideClientHydration()],
providers: [provideClientHydration(withEventReplay())],
bootstrap: [AppComponent],
})
export class AppModule {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ export const appConfig: ApplicationConfig = {
"import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideClientHydration, withEventReplay } from '@angular/platform-browser';
export const appConfig: ApplicationConfig = {
providers: [provideClientHydration(),provideRouter(appRoutes)],
providers: [provideClientHydration(withEventReplay()),provideRouter(appRoutes)],
};
"
`);
Expand Down Expand Up @@ -98,7 +98,7 @@ export class AppModule {}
expect(tree.read('app1/src/app/app.module.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { NgModule } from '@angular/core';
import { BrowserModule, provideClientHydration } from '@angular/platform-browser';
import { BrowserModule, provideClientHydration, withEventReplay } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { appRoutes } from './app.routes';
Expand All @@ -108,7 +108,7 @@ export class AppModule {}
declarations: [AppComponent, NxWelcomeComponent],
imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
bootstrap: [AppComponent],
providers: [provideClientHydration()],
providers: [provideClientHydration(withEventReplay())],
})
export class AppModule {}
"
Expand Down
30 changes: 19 additions & 11 deletions packages/angular/src/generators/setup-ssr/lib/add-hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
addProviderToAppConfig,
addProviderToModule,
} from '../../../utils/nx-devkit/ast-utils';
import { getInstalledAngularVersionInfo } from '../../utils/version-utils';
import { type Schema } from '../schema';

let tsModule: typeof import('typescript');
Expand Down Expand Up @@ -60,25 +61,32 @@ export function addHydration(tree: Tree, options: Schema) {
);
};

const { major: angularMajorVersion } = getInstalledAngularVersionInfo(tree);

sourceFile = addImport(
sourceFile,
'provideClientHydration',
'@angular/platform-browser',
pathToClientConfigFile
);

if (options.standalone) {
addProviderToAppConfig(
tree,
pathToClientConfigFile,
'provideClientHydration()'
);
} else {
addProviderToModule(
tree,
if (angularMajorVersion >= 19) {
sourceFile = addImport(
sourceFile,
pathToClientConfigFile,
'provideClientHydration()'
'withEventReplay',
'@angular/platform-browser',
pathToClientConfigFile
);
}

const provider =
angularMajorVersion >= 19
? 'provideClientHydration(withEventReplay())'
: 'provideClientHydration()';

if (options.standalone) {
addProviderToAppConfig(tree, pathToClientConfigFile, provider);
} else {
addProviderToModule(tree, sourceFile, pathToClientConfigFile, provider);
}
}
103 changes: 96 additions & 7 deletions packages/angular/src/generators/setup-ssr/setup-ssr.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ describe('setupSSR', () => {
import {
BrowserModule,
provideClientHydration,
withEventReplay,
} from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
Expand All @@ -90,7 +91,7 @@ describe('setupSSR', () => {
@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
providers: [provideClientHydration()],
providers: [provideClientHydration(withEventReplay())],
bootstrap: [AppComponent],
})
export class AppModule {}
Expand Down Expand Up @@ -269,7 +270,7 @@ describe('setupSSR', () => {
expect(tree.read('app1/src/app/app.module.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { NgModule } from '@angular/core';
import { BrowserModule, provideClientHydration } from '@angular/platform-browser';
import { BrowserModule, provideClientHydration, withEventReplay } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { appRoutes } from './app.routes';
Expand All @@ -281,7 +282,7 @@ describe('setupSSR', () => {
BrowserModule,
RouterModule.forRoot(appRoutes),
],
providers: [provideClientHydration()],
providers: [provideClientHydration(withEventReplay())],
bootstrap: [AppComponent],
})
export class AppModule {}
Expand Down Expand Up @@ -444,7 +445,7 @@ describe('setupSSR', () => {
expect(tree.read('app1/src/app/app.module.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { NgModule } from '@angular/core';
import { BrowserModule, provideClientHydration } from '@angular/platform-browser';
import { BrowserModule, provideClientHydration, withEventReplay } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { appRoutes } from './app.routes';
Expand All @@ -456,7 +457,7 @@ describe('setupSSR', () => {
BrowserModule,
RouterModule.forRoot(appRoutes),
],
providers: [provideClientHydration()],
providers: [provideClientHydration(withEventReplay())],
bootstrap: [AppComponent],
})
export class AppModule {}
Expand Down Expand Up @@ -486,10 +487,10 @@ describe('setupSSR', () => {
"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideClientHydration, withEventReplay } from '@angular/platform-browser';
export const appConfig: ApplicationConfig = {
providers: [provideClientHydration(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
providers: [provideClientHydration(withEventReplay()),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
};
"
`);
Expand Down Expand Up @@ -616,5 +617,93 @@ describe('setupSSR', () => {
);
expect(pkgJson.devDependencies['@nguniversal/builders']).toBeUndefined();
});

it('should add hydration correctly for NgModule apps', async () => {
const tree = createTreeWithEmptyWorkspace();
updateJson(tree, 'package.json', (json) => ({
...json,
dependencies: { '@angular/core': '17.2.0' },
}));
await generateTestApplication(tree, {
directory: 'app1',
standalone: false,
skipFormat: true,
});

await setupSsr(tree, {
project: 'app1',
hydration: true,
skipFormat: true,
});

expect(tree.read('app1/src/app/app.module.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { NgModule } from '@angular/core';
import { BrowserModule, provideClientHydration } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { appRoutes } from './app.routes';
import { NxWelcomeComponent } from './nx-welcome.component';
@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
],
providers: [provideClientHydration()],
bootstrap: [AppComponent],
})
export class AppModule {}
"
`);
});

it('should add hydration correctly to standalone', async () => {
const tree = createTreeWithEmptyWorkspace();
updateJson(tree, 'package.json', (json) => ({
...json,
dependencies: { '@angular/core': '17.2.0' },
}));
await generateTestApplication(tree, {
directory: 'app1',
skipFormat: true,
});

await setupSsr(tree, {
project: 'app1',
hydration: true,
skipFormat: true,
});

expect(tree.read('app1/src/app/app.config.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
export const appConfig: ApplicationConfig = {
providers: [provideClientHydration(),provideRouter(appRoutes) ]
};
"
`);

expect(tree.read('app1/src/app/app.config.server.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering()
]
};
export const config = mergeApplicationConfig(appConfig, serverConfig);
"
`);
});
});
});

0 comments on commit 59d8738

Please sign in to comment.