From 02b18dc5b0da1dddaa0d7f638fcb3fbca8275302 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Thu, 10 Nov 2022 12:03:57 -0800 Subject: [PATCH] refactor(router): Simplify router defaults by making the defaults Injectable (#48022) The router has several default strategy implementations that are either assigned via `new XStrategy()` property assignements or via the factory function for the `Router` itself. These can be simplified by providing the default implementation in the strategy `Injectable`. Custom implementations can still override the defaults by specifying them in the `providers` list. Notably, this change also makes the `UrlHandlingStrategy` and `RouteReuseStrategy` defaults injectable via DI rather than having to indirectly grab them by going through the `Router` instance and accessing the properties. PR Close #48022 --- goldens/public-api/router/index.md | 8 ++++++ .../size-tracking/integration-payloads.json | 2 +- .../router/bundle.golden_symbols.json | 21 +++++++++++++++ packages/router/src/route_reuse_strategy.ts | 7 +++-- packages/router/src/router.ts | 26 +++++-------------- packages/router/src/url_handling_strategy.ts | 4 +++ 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/goldens/public-api/router/index.md b/goldens/public-api/router/index.md index 83749ad7eef..835b57f6aab 100644 --- a/goldens/public-api/router/index.md +++ b/goldens/public-api/router/index.md @@ -690,6 +690,10 @@ export abstract class RouteReuseStrategy { abstract shouldDetach(route: ActivatedRouteSnapshot): boolean; abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void; + // (undocumented) + static ɵfac: i0.ɵɵFactoryDeclaration; + // (undocumented) + static ɵprov: i0.ɵɵInjectableDeclaration; } // @public @@ -941,6 +945,10 @@ export abstract class UrlHandlingStrategy { abstract extract(url: UrlTree): UrlTree; abstract merge(newUrlPart: UrlTree, rawUrl: UrlTree): UrlTree; abstract shouldProcessUrl(url: UrlTree): boolean; + // (undocumented) + static ɵfac: i0.ɵɵFactoryDeclaration; + // (undocumented) + static ɵprov: i0.ɵɵInjectableDeclaration; } // @public diff --git a/goldens/size-tracking/integration-payloads.json b/goldens/size-tracking/integration-payloads.json index 7a7418127ac..43d1860a16e 100644 --- a/goldens/size-tracking/integration-payloads.json +++ b/goldens/size-tracking/integration-payloads.json @@ -33,7 +33,7 @@ "cli-hello-world-lazy": { "uncompressed": { "runtime": 2835, - "main": 225113, + "main": 225766, "polyfills": 33842, "src_app_lazy_lazy_routes_ts": 487 } diff --git a/packages/core/test/bundling/router/bundle.golden_symbols.json b/packages/core/test/bundling/router/bundle.golden_symbols.json index 5cea13d6743..5f562fbfc9f 100644 --- a/packages/core/test/bundling/router/bundle.golden_symbols.json +++ b/packages/core/test/bundling/router/bundle.golden_symbols.json @@ -125,9 +125,15 @@ { "name": "DefaultIfEmptySubscriber" }, + { + "name": "DefaultRouteReuseStrategy" + }, { "name": "DefaultTitleStrategy" }, + { + "name": "DefaultUrlHandlingStrategy" + }, { "name": "DefaultUrlSerializer" }, @@ -464,6 +470,9 @@ { "name": "RootViewRef" }, + { + "name": "RouteReuseStrategy" + }, { "name": "RouteTitleKey" }, @@ -617,6 +626,9 @@ { "name": "UnsubscriptionError" }, + { + "name": "UrlHandlingStrategy" + }, { "name": "UrlParser" }, @@ -1088,6 +1100,9 @@ { "name": "getFactoryDef" }, + { + "name": "getFactoryOf" + }, { "name": "getFirstLContainer" }, @@ -1346,6 +1361,9 @@ { "name": "isEnvironmentProviders" }, + { + "name": "isForwardRef" + }, { "name": "isFunction" }, @@ -1526,6 +1544,9 @@ { "name": "noMatch2" }, + { + "name": "noSideEffects" + }, { "name": "nodeChildrenAsMap" }, diff --git a/packages/router/src/route_reuse_strategy.ts b/packages/router/src/route_reuse_strategy.ts index f41b5bc57e8..82712cf9493 100644 --- a/packages/router/src/route_reuse_strategy.ts +++ b/packages/router/src/route_reuse_strategy.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {ComponentRef} from '@angular/core'; +import {ComponentRef, inject, Injectable} from '@angular/core'; import {OutletContext} from './router_outlet_context'; import {ActivatedRoute, ActivatedRouteSnapshot} from './router_state'; @@ -38,6 +38,7 @@ export type DetachedRouteHandleInternal = { * * @publicApi */ +@Injectable({providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy)}) export abstract class RouteReuseStrategy { /** Determines if this route (and its subtree) should be detached to be reused later */ abstract shouldDetach(route: ActivatedRouteSnapshot): boolean; @@ -110,4 +111,6 @@ export abstract class BaseRouteReuseStrategy implements RouteReuseStrategy { } } -export class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {} +@Injectable({providedIn: 'root'}) +export class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy { +} diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index a87462fcd3e..8445626e6da 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -23,14 +23,14 @@ import {checkGuards} from './operators/check_guards'; import {recognize} from './operators/recognize'; import {resolveData} from './operators/resolve_data'; import {switchTap} from './operators/switch_tap'; -import {DefaultTitleStrategy, TitleStrategy} from './page_title_strategy'; -import {DefaultRouteReuseStrategy, RouteReuseStrategy} from './route_reuse_strategy'; +import {TitleStrategy} from './page_title_strategy'; +import {RouteReuseStrategy} from './route_reuse_strategy'; import {ErrorHandler, ExtraOptions, ROUTER_CONFIGURATION} from './router_config'; import {RouterConfigLoader, ROUTES} from './router_config_loader'; import {ChildrenOutletContexts} from './router_outlet_context'; import {ActivatedRoute, ActivatedRouteSnapshot, createEmptyState, RouterState, RouterStateSnapshot} from './router_state'; import {Params} from './shared'; -import {DefaultUrlHandlingStrategy, UrlHandlingStrategy} from './url_handling_strategy'; +import {UrlHandlingStrategy} from './url_handling_strategy'; import {containsTree, IsActiveMatchOptions, isUrlTree, UrlSerializer, UrlTree} from './url_tree'; import {flatten} from './utils/collection'; import {standardizeConfig, validateConfig} from './utils/config'; @@ -325,23 +325,9 @@ export function setupRouter() { const compiler = inject(Compiler); const config = inject(ROUTES, {optional: true}) ?? []; const opts = inject(ROUTER_CONFIGURATION, {optional: true}) ?? {}; - const defaultTitleStrategy = inject(DefaultTitleStrategy); - const titleStrategy = inject(TitleStrategy, {optional: true}); - const urlHandlingStrategy = inject(UrlHandlingStrategy, {optional: true}); - const routeReuseStrategy = inject(RouteReuseStrategy, {optional: true}); const router = new Router(null, urlSerializer, contexts, location, injector, compiler, flatten(config)); - if (urlHandlingStrategy) { - router.urlHandlingStrategy = urlHandlingStrategy; - } - - if (routeReuseStrategy) { - router.routeReuseStrategy = routeReuseStrategy; - } - - router.titleStrategy = titleStrategy ?? defaultTitleStrategy; - assignExtraOptionsToRouter(opts, router); return router; @@ -475,17 +461,17 @@ export class Router { * A strategy for extracting and merging URLs. * Used for AngularJS to Angular migrations. */ - urlHandlingStrategy: UrlHandlingStrategy = new DefaultUrlHandlingStrategy(); + urlHandlingStrategy = inject(UrlHandlingStrategy); /** * A strategy for re-using routes. */ - routeReuseStrategy: RouteReuseStrategy = new DefaultRouteReuseStrategy(); + routeReuseStrategy = inject(RouteReuseStrategy); /** * A strategy for setting the title based on the `routerState`. */ - titleStrategy?: TitleStrategy; + titleStrategy?: TitleStrategy = inject(TitleStrategy); /** * How to handle a navigation request to the current URL. One of: diff --git a/packages/router/src/url_handling_strategy.ts b/packages/router/src/url_handling_strategy.ts index 067421c5fff..8127ce2c5e1 100644 --- a/packages/router/src/url_handling_strategy.ts +++ b/packages/router/src/url_handling_strategy.ts @@ -6,6 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ +import {inject, Injectable} from '@angular/core'; + import {UrlTree} from './url_tree'; /** @@ -15,6 +17,7 @@ import {UrlTree} from './url_tree'; * * @publicApi */ +@Injectable({providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy)}) export abstract class UrlHandlingStrategy { /** * Tells the router if this URL should be processed. @@ -41,6 +44,7 @@ export abstract class UrlHandlingStrategy { /** * @publicApi */ +@Injectable({providedIn: 'root'}) export class DefaultUrlHandlingStrategy implements UrlHandlingStrategy { shouldProcessUrl(url: UrlTree): boolean { return true;