From bdb6ae9dbc080cd6ce4f5058c65f6b2bd853beda Mon Sep 17 00:00:00 2001 From: Matthieu Riegler Date: Tue, 24 Feb 2026 09:33:46 +0100 Subject: [PATCH] refactor(router): remove deprecated `provideRoutes` function. `provideRoutes` was deprecated in v15. BREAKING CHANGE: `provideRoutes()` has been removed. Use `provideRouter()` or `ROUTES` as multi token if necessary. --- .../migrations/route-lazy-loading.md | 1 - goldens/public-api/router/index.api.md | 3 -- .../ng-generate/route-lazy-loading/README.md | 1 - .../route-lazy-loading/to-lazy-routes.ts | 8 ++- .../ng-generate/route-lazy-loading/util.ts | 19 +------ .../schematics/test/standalone_routes_spec.ts | 53 ++----------------- packages/router/src/index.ts | 35 ++++++------ packages/router/src/provide_router.ts | 53 ------------------- packages/router/src/router_module.ts | 6 --- packages/router/test/standalone.spec.ts | 11 +--- 10 files changed, 28 insertions(+), 162 deletions(-) diff --git a/adev/src/content/reference/migrations/route-lazy-loading.md b/adev/src/content/reference/migrations/route-lazy-loading.md index 1b20191201c..f0dfbdbb81b 100644 --- a/adev/src/content/reference/migrations/route-lazy-loading.md +++ b/adev/src/content/reference/migrations/route-lazy-loading.md @@ -25,7 +25,6 @@ The schematic will attempt to find all the places where the application routes a - `RouterModule.forRoot` and `RouterModule.forChild` - `Router.resetConfig` - `provideRouter` -- `provideRoutes` - variables of type `Routes` or `Route[]` (e.g. `const routes: Routes = [{...}]`) The migration will check all the components in the routes, check if they are standalone and eagerly loaded, and if so, it will convert them to lazy loaded routes. diff --git a/goldens/public-api/router/index.api.md b/goldens/public-api/router/index.api.md index 41993801e01..0f97489134a 100644 --- a/goldens/public-api/router/index.api.md +++ b/goldens/public-api/router/index.api.md @@ -589,9 +589,6 @@ export const PRIMARY_OUTLET = "primary"; // @public export function provideRouter(routes: Routes, ...features: RouterFeatures[]): EnvironmentProviders; -// @public @deprecated -export function provideRoutes(routes: Routes): Provider[]; - // @public export type QueryParamsHandling = 'merge' | 'preserve' | 'replace' | ''; diff --git a/packages/core/schematics/ng-generate/route-lazy-loading/README.md b/packages/core/schematics/ng-generate/route-lazy-loading/README.md index a1c93815c5e..34a0ce583ec 100644 --- a/packages/core/schematics/ng-generate/route-lazy-loading/README.md +++ b/packages/core/schematics/ng-generate/route-lazy-loading/README.md @@ -27,7 +27,6 @@ The schematic will attempt to find all the places where the application routes a - `RouterModule.forRoot` and `RouterModule.forChild` - `Router.resetConfig` - `provideRouter` -- `provideRoutes` - variables of type `Routes` or `Route[]` (e.g. `const routes: Routes = [{...}]`) The migration will check all the components in the routes, check if they are standalone and eagerly loaded, and if so, it will convert them to lazy loaded routes. diff --git a/packages/core/schematics/ng-generate/route-lazy-loading/to-lazy-routes.ts b/packages/core/schematics/ng-generate/route-lazy-loading/to-lazy-routes.ts index 0f8a8fd93c5..92f639dac56 100644 --- a/packages/core/schematics/ng-generate/route-lazy-loading/to-lazy-routes.ts +++ b/packages/core/schematics/ng-generate/route-lazy-loading/to-lazy-routes.ts @@ -15,10 +15,9 @@ import {findClassDeclaration} from '../../utils/typescript/class_declaration'; import {findLiteralProperty} from '../../utils/typescript/property_name'; import { isAngularRoutesArray, - isProvideRoutesCallExpression, + isProvideRouterCallExpression, isRouterCallExpression, isRouterModuleCallExpression, - isRouterProviderCallExpression, isStandaloneComponent, } from './util'; @@ -79,9 +78,8 @@ function findRoutesArrayToMigrate(sourceFile: ts.SourceFile, typeChecker: ts.Typ if (ts.isCallExpression(node)) { if ( isRouterModuleCallExpression(node, typeChecker) || - isRouterProviderCallExpression(node, typeChecker) || isRouterCallExpression(node, typeChecker) || - isProvideRoutesCallExpression(node, typeChecker) + isProvideRouterCallExpression(node, typeChecker) ) { const arg = node.arguments[0]; // ex: RouterModule.forRoot(routes) or provideRouter(routes) const routeFileImports = sourceFile.statements.filter(ts.isImportDeclaration); @@ -95,7 +93,7 @@ function findRoutesArrayToMigrate(sourceFile: ts.SourceFile, typeChecker: ts.Typ }); } else if (ts.isIdentifier(arg)) { // ex: reference to routes array: RouterModule.forRoot(routes) - // RouterModule.forRoot(routes), provideRouter(routes), provideRoutes(routes) + // RouterModule.forRoot(routes), provideRouter(routes) const symbol = typeChecker.getSymbolAtLocation(arg); if (!symbol?.declarations) return; diff --git a/packages/core/schematics/ng-generate/route-lazy-loading/util.ts b/packages/core/schematics/ng-generate/route-lazy-loading/util.ts index cf1bd7021c2..ef58de945e8 100644 --- a/packages/core/schematics/ng-generate/route-lazy-loading/util.ts +++ b/packages/core/schematics/ng-generate/route-lazy-loading/util.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.dev/license */ -import ts from 'typescript'; import {findAngularDecorator, ReflectionHost} from '@angular/compiler-cli/private/migrations'; +import ts from 'typescript'; import {findLiteralProperty} from '../../utils/typescript/property_name'; /** @@ -103,26 +103,11 @@ export function isRouterCallExpression(node: ts.CallExpression, typeChecker: ts. return false; } -/** - * Checks whether a node is a call expression to router provide function. - * Example: provideRoutes(routes) - */ -export function isRouterProviderCallExpression( - node: ts.CallExpression, - typeChecker: ts.TypeChecker, -) { - if (ts.isIdentifier(node.expression)) { - const moduleSymbol = typeChecker.getSymbolAtLocation(node.expression); - return moduleSymbol && moduleSymbol.name === 'provideRoutes'; - } - return false; -} - /** * Checks whether a node is a call expression to provideRouter function. * Example: provideRouter(routes) */ -export function isProvideRoutesCallExpression( +export function isProvideRouterCallExpression( node: ts.CallExpression, typeChecker: ts.TypeChecker, ) { diff --git a/packages/core/schematics/test/standalone_routes_spec.ts b/packages/core/schematics/test/standalone_routes_spec.ts index 50bd2808aeb..cc27f2f37b1 100644 --- a/packages/core/schematics/test/standalone_routes_spec.ts +++ b/packages/core/schematics/test/standalone_routes_spec.ts @@ -10,8 +10,8 @@ import {getSystemPath, normalize, virtualFs} from '@angular-devkit/core'; import {TempScopedNodeJsSyncHost} from '@angular-devkit/core/node/testing'; import {HostTree} from '@angular-devkit/schematics'; import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing/index.js'; -import {resolve} from 'path'; import {rmSync} from 'node:fs'; +import {resolve} from 'path'; describe('route lazy loading migration', () => { let runner: SchematicTestRunner; @@ -285,55 +285,12 @@ describe('route lazy loading migration', () => { ); }); - it('should support provideRoutes', async () => { - writeFile( - 'app.module.ts', - ` - import {NgModule} from '@angular/core'; - import {provideRoutes} from '@angular/router'; - import {TestComponent} from './test'; - - const routes = [{path: 'test', component: TestComponent}]; - - @NgModule({ - providers: [provideRoutes(routes)], - }) - export class AppModule {} - `, - ); - - writeFile( - 'test.ts', - ` - import {Component} from '@angular/core'; - @Component({template: 'hello', standalone: true}) - export class TestComponent {} - `, - ); - - await runMigration('route-lazy-loading'); - - expect(stripWhitespace(tree.readContent('app.module.ts'))).toContain( - stripWhitespace(` - import {NgModule} from '@angular/core'; - import {provideRoutes} from '@angular/router'; - - const routes = [{path: 'test', loadComponent: () => import('./test').then(m => m.TestComponent)}]; - - @NgModule({ - providers: [provideRoutes(routes)], - }) - export class AppModule {} - `), - ); - }); - it('should skip not standalone components', async () => { writeFile( 'app.module.ts', ` import {NgModule} from '@angular/core'; - import {provideRoutes} from '@angular/router'; + import {provideRouter} from '@angular/router'; import {TestComponent} from './test'; import {StandaloneByDefaultComponent} from './standalone-by-default'; import {NotStandaloneComponent} from './not-standalone'; @@ -345,7 +302,7 @@ describe('route lazy loading migration', () => { ]; @NgModule({ - providers: [provideRoutes(routes)], + providers: [provideRouter(routes)], }) export class AppModule {} `, @@ -386,7 +343,7 @@ describe('route lazy loading migration', () => { expect(stripWhitespace(tree.readContent('app.module.ts'))).toContain( stripWhitespace(` import {NgModule} from '@angular/core'; - import {provideRoutes} from '@angular/router'; + import {provideRouter} from '@angular/router'; import {NotStandaloneComponent} from './not-standalone'; const routes = [ @@ -396,7 +353,7 @@ describe('route lazy loading migration', () => { ]; @NgModule({ - providers: [provideRoutes(routes)], + providers: [provideRouter(routes)], }) export class AppModule {} `), diff --git a/packages/router/src/index.ts b/packages/router/src/index.ts index 9d5a3e114a8..fc8dceee41c 100644 --- a/packages/router/src/index.ts +++ b/packages/router/src/index.ts @@ -9,7 +9,7 @@ export {createUrlTreeFromSnapshot} from './create_url_tree'; export {RouterLink, RouterLinkWithHref} from './directives/router_link'; export {RouterLinkActive} from './directives/router_link_active'; -export {RouterOutlet, ROUTER_OUTLET_DATA, RouterOutletContract} from './directives/router_outlet'; +export {ROUTER_OUTLET_DATA, RouterOutlet, RouterOutletContract} from './directives/router_outlet'; export { ActivationEnd, ActivationStart, @@ -35,21 +35,29 @@ export { Scroll, } from './events'; export { + CanActivate, + CanActivateChild, CanActivateChildFn, - MaybeAsync, - GuardResult, CanActivateFn, + CanDeactivate, CanDeactivateFn, + CanLoad, CanLoadFn, + CanMatch, CanMatchFn, Data, DefaultExport, + GuardResult, LoadChildren, LoadChildrenCallback, + MaybeAsync, NavigationBehaviorOptions, OnSameUrlNavigation, + PartialMatchRouteSnapshot, QueryParamsHandling, + RedirectCommand, RedirectFunction, + Resolve, ResolveData, ResolveFn, Route, @@ -57,14 +65,6 @@ export { RunGuardsAndResolvers, UrlMatcher, UrlMatchResult, - RedirectCommand, - CanActivate, - CanActivateChild, - CanDeactivate, - CanLoad, - CanMatch, - Resolve, - PartialMatchRouteSnapshot, } from './models'; export {ViewTransitionInfo, ViewTransitionsFeatureOptions} from './utils/view_transition'; @@ -75,36 +75,35 @@ export { ComponentInputBindingFeature, DebugTracingFeature, DisabledInitialNavigationFeature, - withViewTransitions, - ViewTransitionsFeature, EnabledBlockingInitialNavigationFeature, InitialNavigationFeature, InMemoryScrollingFeature, NavigationErrorHandlerFeature, PreloadingFeature, provideRouter, - withExperimentalPlatformNavigation, - provideRoutes, RouterConfigurationFeature, RouterFeature, RouterFeatures, RouterHashLocationFeature, + ViewTransitionsFeature, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, + withExperimentalAutoCleanupInjectors, + withExperimentalPlatformNavigation, withHashLocation, withInMemoryScrolling, withNavigationErrorHandler, withPreloading, withRouterConfig, - withExperimentalAutoCleanupInjectors, + withViewTransitions, } from './provide_router'; export { BaseRouteReuseStrategy, - DetachedRouteHandle, destroyDetachedRouteHandle, + DetachedRouteHandle, RouteReuseStrategy, } from './route_reuse_strategy'; export {Router} from './router'; @@ -134,12 +133,12 @@ export {convertToParamMap, defaultUrlMatcher, ParamMap, Params, PRIMARY_OUTLET} export {UrlHandlingStrategy} from './url_handling_strategy'; export { DefaultUrlSerializer, + isActive, IsActiveMatchOptions, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, - isActive, } from './url_tree'; export { mapToCanActivate, diff --git a/packages/router/src/provide_router.ts b/packages/router/src/provide_router.ts index 4d265cf886b..164540ea3d2 100644 --- a/packages/router/src/provide_router.ts +++ b/packages/router/src/provide_router.ts @@ -106,9 +106,6 @@ export function provideRouter(routes: Routes, ...features: RouterFeatures[]): En return makeEnvironmentProviders([ {provide: ROUTES, multi: true, useValue: routes}, - typeof ngDevMode === 'undefined' || ngDevMode - ? {provide: ROUTER_IS_PROVIDED, useValue: true} - : [], {provide: ActivatedRoute, useFactory: rootRoute}, {provide: APP_BOOTSTRAP_LISTENER, multi: true, useFactory: getBootstrapListener}, features.map((feature) => feature.ɵproviders), @@ -139,56 +136,6 @@ function routerFeature( return {ɵkind: kind, ɵproviders: providers}; } -/** - * An Injection token used to indicate whether `provideRouter` or `RouterModule.forRoot` was ever - * called. - */ -export const ROUTER_IS_PROVIDED = new InjectionToken( - typeof ngDevMode !== 'undefined' && ngDevMode ? 'Router is provided' : '', - { - factory: () => false, - }, -); - -const routerIsProvidedDevModeCheck = { - provide: ENVIRONMENT_INITIALIZER, - multi: true, - useFactory() { - return () => { - if (!inject(ROUTER_IS_PROVIDED)) { - console.warn( - '`provideRoutes` was called without `provideRouter` or `RouterModule.forRoot`. ' + - 'This is likely a mistake.', - ); - } - }; - }, -}; - -/** - * Registers a DI provider for a set of routes. - * @param routes The route configuration to provide. - * - * @usageNotes - * - * ```ts - * @NgModule({ - * providers: [provideRoutes(ROUTES)] - * }) - * class LazyLoadedChildModule {} - * ``` - * - * @deprecated If necessary, provide routes using the `ROUTES` `InjectionToken`. - * @see {@link ROUTES} - * @publicApi - */ -export function provideRoutes(routes: Routes): Provider[] { - return [ - {provide: ROUTES, multi: true, useValue: routes}, - typeof ngDevMode === 'undefined' || ngDevMode ? routerIsProvidedDevModeCheck : [], - ]; -} - /** * A type alias for providers returned by `withInMemoryScrolling` for use with `provideRouter`. * diff --git a/packages/router/src/router_module.ts b/packages/router/src/router_module.ts index 2e24ed2faf6..f5e20a51caf 100644 --- a/packages/router/src/router_module.ts +++ b/packages/router/src/router_module.ts @@ -34,7 +34,6 @@ import {NAVIGATION_ERROR_HANDLER} from './navigation_transition'; import { getBootstrapListener, rootRoute, - ROUTER_IS_PROVIDED, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, @@ -73,11 +72,6 @@ export const ROUTER_PROVIDERS: Provider[] = [ ChildrenOutletContexts, {provide: ActivatedRoute, useFactory: rootRoute}, RouterConfigLoader, - // Only used to warn when `provideRoutes` is used without `RouterModule` or `provideRouter`. Can - // be removed when `provideRoutes` is removed. - typeof ngDevMode === 'undefined' || ngDevMode - ? {provide: ROUTER_IS_PROVIDED, useValue: true} - : [], ]; /** diff --git a/packages/router/test/standalone.spec.ts b/packages/router/test/standalone.spec.ts index 8a7eeed0bd7..dd9e3a2f837 100644 --- a/packages/router/test/standalone.spec.ts +++ b/packages/router/test/standalone.spec.ts @@ -9,8 +9,8 @@ import {Component, inject, Injectable, InjectionToken, NgModule} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; -import {provideRoutes, Router, RouterModule, ROUTES} from '../index'; import {timeout} from '@angular/private/testing'; +import {Router, RouterModule} from '../index'; @Component({template: '
simple standalone
'}) export class SimpleStandaloneComponent {} @@ -546,15 +546,6 @@ describe('standalone in Router API', () => { }); }); -describe('provideRoutes', () => { - it('warns if provideRoutes is used without provideRouter, RouterModule, or RouterModule.forRoot', () => { - spyOn(console, 'warn'); - TestBed.configureTestingModule({providers: [provideRoutes([])]}); - TestBed.inject(ROUTES); - expect(console.warn).toHaveBeenCalled(); - }); -}); - async function advanceAsync(fixture: ComponentFixture) { await timeout(); fixture.detectChanges();