mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
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.
This commit is contained in:
parent
c57ba8c6e6
commit
bdb6ae9dbc
10 changed files with 28 additions and 162 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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' | '';
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
`),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<FeatureKind extends RouterFeatureKind>(
|
|||
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<boolean>(
|
||||
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`.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
: [],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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: '<div>simple standalone</div>'})
|
||||
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<unknown>) {
|
||||
await timeout();
|
||||
fixture.detectChanges();
|
||||
|
|
|
|||
Loading…
Reference in a new issue