diff --git a/projects/example-app/project.json b/projects/example-app/project.json
index 9a194298aa..bba5104512 100644
--- a/projects/example-app/project.json
+++ b/projects/example-app/project.json
@@ -7,12 +7,12 @@
"generators": {},
"targets": {
"build": {
- "executor": "@angular-devkit/build-angular:browser",
+ "executor": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/projects/example-app",
"index": "projects/example-app/src/index.html",
- "main": "projects/example-app/src/main.ts",
- "polyfills": "projects/example-app/src/polyfills.ts",
+ "browser": "projects/example-app/src/main.ts",
+ "polyfills": ["zone.js"],
"tsConfig": "projects/example-app/tsconfig.app.json",
"assets": [
"projects/example-app/src/favicon.ico",
@@ -24,20 +24,23 @@
"configurations": {
"production": {
"budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "500kb",
+ "maximumError": "1mb"
+ },
{
"type": "anyComponentStyle",
- "maximumWarning": "6kb"
+ "maximumWarning": "2kb",
+ "maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
- "buildOptimizer": false,
"optimization": false,
- "vendorChunk": true,
"extractLicenses": false,
- "sourceMap": true,
- "namedChunks": true
+ "sourceMap": true
}
},
"defaultConfiguration": "production",
diff --git a/projects/example-app/src/app/app-routing.module.ts b/projects/example-app/src/app/app-routing.module.ts
deleted file mode 100644
index cba7ce2327..0000000000
--- a/projects/example-app/src/app/app-routing.module.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { NgModule } from '@angular/core';
-import { Routes, RouterModule } from '@angular/router';
-
-import { authGuard } from '@example-app/auth/services';
-import { NotFoundPageComponent } from '@example-app/core/containers';
-
-export const routes: Routes = [
- { path: '', redirectTo: '/books', pathMatch: 'full' },
- {
- path: 'books',
- loadChildren: () =>
- import('@example-app/books/books.module').then((m) => m.BooksModule),
- canActivate: [authGuard],
- },
- {
- path: '**',
- component: NotFoundPageComponent,
- data: { title: 'Not found' },
- },
-];
-
-@NgModule({
- imports: [
- RouterModule.forRoot(routes, {
- useHash: true,
- }),
- ],
- exports: [RouterModule],
-})
-export class AppRoutingModule {}
diff --git a/projects/example-app/src/app/app.config.ts b/projects/example-app/src/app/app.config.ts
new file mode 100644
index 0000000000..1c431140e8
--- /dev/null
+++ b/projects/example-app/src/app/app.config.ts
@@ -0,0 +1,88 @@
+import { ApplicationConfig } from '@angular/core';
+import { provideHttpClient } from '@angular/common/http';
+import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
+
+import { provideStore } from '@ngrx/store';
+import { provideEffects } from '@ngrx/effects';
+import { provideRouterStore } from '@ngrx/router-store';
+import { provideStoreDevtools } from '@ngrx/store-devtools';
+
+import { rootReducers, metaReducers } from '@example-app/reducers';
+
+import { APP_ROUTES } from '@example-app/app.routing';
+import { UserEffects, RouterEffects } from '@example-app/core/effects';
+import {
+ provideRouter,
+ withComponentInputBinding,
+ withHashLocation,
+} from '@angular/router';
+import { AuthEffects } from './auth/effects';
+import { provideAuth } from '@example-app/auth/reducers';
+import { provideLayout } from '@example-app/core/reducers/layout.reducer';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideAnimationsAsync(),
+ provideHttpClient(),
+ provideRouter(APP_ROUTES, withHashLocation(), withComponentInputBinding()),
+
+ /**
+ * provideStore() is imported once in the root providers, accepting a reducer
+ * function or object map of reducer functions. If passed an object of
+ * reducers, combineReducers will be run creating your application
+ * meta-reducer. This returns all providers for an @ngrx/store
+ * based application.
+ */
+ provideStore(rootReducers, {
+ metaReducers,
+ runtimeChecks: {
+ // strictStateImmutability and strictActionImmutability are enabled by default
+ strictStateSerializability: true,
+ strictActionSerializability: true,
+ strictActionWithinNgZone: true,
+ strictActionTypeUniqueness: true,
+ },
+ }),
+
+ /**
+ * The layout feature manages the visibility of the sidenav.
+ */
+ provideLayout(),
+
+ /**
+ * The Auth state is provided here to ensure that the login details
+ * are available as soon as the application starts.
+ *
+ * It could also be part of the `rootReducers`, but is separated
+ * because of demonstration purposes.
+ */
+ provideAuth(),
+
+ /**
+ * @ngrx/router-store keeps router state up-to-date in the store.
+ */
+ provideRouterStore(),
+
+ /**
+ * Store devtools instrument the store retaining past versions of state
+ * and recalculating new states. This enables powerful time-travel
+ * debugging.
+ *
+ * To use the debugger, install the Redux Devtools extension for either
+ * Chrome or Firefox
+ *
+ * See: https://github.com/zalmoxisus/redux-devtools-extension
+ */
+ provideStoreDevtools({
+ name: 'NgRx Book Store App',
+ // In a production build you would want to disable the Store Devtools
+ // logOnly: !isDevMode(),
+ }),
+
+ /**
+ * The provideEffects() function is used to register effect classes
+ * so they are initialized when the application starts.
+ */
+ provideEffects(UserEffects, RouterEffects, AuthEffects),
+ ],
+};
diff --git a/projects/example-app/src/app/app.module.ts b/projects/example-app/src/app/app.module.ts
deleted file mode 100644
index 1f66f73f6a..0000000000
--- a/projects/example-app/src/app/app.module.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { HttpClientModule } from '@angular/common/http';
-import { BrowserModule } from '@angular/platform-browser';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-
-import { StoreModule } from '@ngrx/store';
-import { EffectsModule } from '@ngrx/effects';
-import { StoreRouterConnectingModule } from '@ngrx/router-store';
-import { StoreDevtoolsModule } from '@ngrx/store-devtools';
-
-import { AuthModule } from '@example-app/auth';
-
-import { rootReducers, metaReducers } from '@example-app/reducers';
-
-import { CoreModule } from '@example-app/core';
-import { AppRoutingModule } from '@example-app/app-routing.module';
-import { UserEffects, RouterEffects } from '@example-app/core/effects';
-import { AppComponent } from '@example-app/core/containers';
-
-@NgModule({
- imports: [
- CommonModule,
- BrowserModule,
- BrowserAnimationsModule,
- HttpClientModule,
- AuthModule,
- AppRoutingModule,
-
- /**
- * StoreModule.forRoot is imported once in the root module, accepting a reducer
- * function or object map of reducer functions. If passed an object of
- * reducers, combineReducers will be run creating your application
- * meta-reducer. This returns all providers for an @ngrx/store
- * based application.
- */
- StoreModule.forRoot(rootReducers, {
- metaReducers,
- runtimeChecks: {
- // strictStateImmutability and strictActionImmutability are enabled by default
- strictStateSerializability: true,
- strictActionSerializability: true,
- strictActionWithinNgZone: true,
- strictActionTypeUniqueness: true,
- },
- }),
-
- /**
- * @ngrx/router-store keeps router state up-to-date in the store.
- */
- StoreRouterConnectingModule.forRoot(),
-
- /**
- * Store devtools instrument the store retaining past versions of state
- * and recalculating new states. This enables powerful time-travel
- * debugging.
- *
- * To use the debugger, install the Redux Devtools extension for either
- * Chrome or Firefox
- *
- * See: https://github.com/zalmoxisus/redux-devtools-extension
- */
- StoreDevtoolsModule.instrument({
- name: 'NgRx Book Store App',
- // In a production build you would want to disable the Store Devtools
- // logOnly: !isDevMode(),
- }),
-
- /**
- * EffectsModule.forRoot() is imported once in the root module and
- * sets up the effects class to be initialized immediately when the
- * application starts.
- *
- * See: https://ngrx.io/guide/effects#registering-root-effects
- */
- EffectsModule.forRoot(UserEffects, RouterEffects),
- CoreModule,
- ],
- bootstrap: [AppComponent],
-})
-export class AppModule {}
diff --git a/projects/example-app/src/app/app.routing.ts b/projects/example-app/src/app/app.routing.ts
new file mode 100644
index 0000000000..911c3ed7aa
--- /dev/null
+++ b/projects/example-app/src/app/app.routing.ts
@@ -0,0 +1,22 @@
+import { Routes } from '@angular/router';
+
+import { authGuard } from '@example-app/auth/services';
+import { NotFoundPageComponent } from '@example-app/core/containers';
+
+export const APP_ROUTES: Routes = [
+ {
+ path: 'login',
+ loadChildren: () => import('@example-app/auth/auth.routes'),
+ },
+ { path: '', redirectTo: '/books', pathMatch: 'full' },
+ {
+ path: 'books',
+ loadChildren: () => import('@example-app/books/books.routes'),
+ canActivate: [authGuard],
+ },
+ {
+ path: '**',
+ component: NotFoundPageComponent,
+ data: { title: 'Not found' },
+ },
+];
diff --git a/projects/example-app/src/app/auth/auth-routing.module.ts b/projects/example-app/src/app/auth/auth-routing.module.ts
deleted file mode 100644
index 62ceda18b6..0000000000
--- a/projects/example-app/src/app/auth/auth-routing.module.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { NgModule } from '@angular/core';
-import { Routes, RouterModule } from '@angular/router';
-import { LoginPageComponent } from '@example-app/auth/containers';
-
-const routes: Routes = [
- { path: 'login', component: LoginPageComponent, data: { title: 'Login' } },
-];
-
-@NgModule({
- imports: [RouterModule.forChild(routes)],
- exports: [RouterModule],
-})
-export class AuthRoutingModule {}
diff --git a/projects/example-app/src/app/auth/auth.module.ts b/projects/example-app/src/app/auth/auth.module.ts
deleted file mode 100644
index 39527caa8a..0000000000
--- a/projects/example-app/src/app/auth/auth.module.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { ReactiveFormsModule } from '@angular/forms';
-import { StoreModule } from '@ngrx/store';
-import { EffectsModule } from '@ngrx/effects';
-import { LoginPageComponent } from '@example-app/auth/containers';
-import {
- LoginFormComponent,
- LogoutConfirmationDialogComponent,
-} from '@example-app/auth/components';
-
-import { AuthEffects } from '@example-app/auth/effects';
-import * as fromAuth from '@example-app/auth/reducers';
-import { MaterialModule } from '@example-app/material';
-import { AuthRoutingModule } from './auth-routing.module';
-
-export const COMPONENTS = [
- LoginPageComponent,
- LoginFormComponent,
- LogoutConfirmationDialogComponent,
-];
-
-@NgModule({
- imports: [
- CommonModule,
- ReactiveFormsModule,
- MaterialModule,
- AuthRoutingModule,
- StoreModule.forFeature({
- name: fromAuth.authFeatureKey,
- reducer: fromAuth.reducers,
- }),
- EffectsModule.forFeature(AuthEffects),
- ],
- declarations: COMPONENTS,
-})
-export class AuthModule {}
diff --git a/projects/example-app/src/app/auth/auth.routes.ts b/projects/example-app/src/app/auth/auth.routes.ts
new file mode 100644
index 0000000000..4cc736f9f9
--- /dev/null
+++ b/projects/example-app/src/app/auth/auth.routes.ts
@@ -0,0 +1,10 @@
+import { Routes } from '@angular/router';
+import { LoginPageComponent } from '@example-app/auth/containers';
+
+export default [
+ {
+ path: '',
+ component: LoginPageComponent,
+ data: { title: 'Login' },
+ },
+] satisfies Routes;
diff --git a/projects/example-app/src/app/auth/components/__snapshots__/login-form.component.spec.ts.snap b/projects/example-app/src/app/auth/components/__snapshots__/login-form.component.spec.ts.snap
index 061d31df28..3e06030902 100644
--- a/projects/example-app/src/app/auth/components/__snapshots__/login-form.component.spec.ts.snap
+++ b/projects/example-app/src/app/auth/components/__snapshots__/login-form.component.spec.ts.snap
@@ -2,48 +2,145 @@
exports[`Login Page should compile 1`] = `
- {{ errorMessage }} + @if (errorMessage()) { +
+ {{ errorMessage() }}
+ }