Angular 17+独立配置:main.ts引导调用的导入与提供者最佳实践
背景
在将遗留Angular应用迁移到Angular 17独立API配置时,遵循官方迁移指南执行了第三步操作:
运行
ng g @angular/core:standalone并选择「使用独立API引导项目」
这一步会自动将根NgModule中的提供者和导入项复制到main.ts的bootstrapApplication调用中,生成的代码如下:
bootstrapApplication(AppComponent, { providers: [ importProvidersFrom(AppRoutingModule, BrowserModule, ReactiveFormsModule, MatToolbarModule, MatButtonModule, MatIconModule, FormsModule, MatFormFieldModule, MatInputModule, MatProgressSpinnerModule), provideAnimations(), provideHttpClient(withInterceptorsFromDi()) ] }).catch(err => console.error(err));
但其中的Angular Material模块等导入项,已经在需要使用它们的独立组件中单独导入了,因此产生以下两个疑问:
- 为什么这些导入项还要在bootstrap调用中导入?
- 未来使用新的导入项时,是否也需要添加到bootstrap调用中?例如使用Autocomplete时,是否需要同时将
MatAutocompleteModule添加到bootstrap调用和组件中?
问题解答
1. 迁移工具添加全局导入的原因
迁移工具这么做是为了保证迁移过程的平滑性,避免遗留代码在切换到独立API后立刻出现依赖缺失的报错。但从独立API的最佳实践来看,大部分UI类模块(比如Angular Material的各类Module、ReactiveFormsModule等)只需要在实际使用它们的独立组件的imports数组中按需导入即可,完全不需要全局注册到bootstrap的providers里。
而像provideAnimations()、provideHttpClient()这类属于全局服务或应用级基础功能的提供者,才需要在bootstrap或全局应用配置中注册,因为它们是整个应用都依赖的核心能力。
2. 新增导入项的处理方式
不需要将新的UI类导入项加到bootstrap调用中。比如新增MatAutocompleteModule时,只需要在使用该组件的独立组件的imports数组中导入即可。只有全局级别的服务、路由配置、全局拦截器这类应用层面的依赖,才需要加到全局配置里。
优化建议:重构为app.config.ts模式
迁移工具生成的代码包含很多不必要的全局导入,建议将全局配置抽离到单独的app.config.ts文件,让结构更清晰:
main.ts
bootstrapApplication(AppComponent, appConfig) .catch((err) => console.error(err));
app.config.ts
export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideAnimations(), provideHttpClient() ] };
原bootstrapApplication中的其他导入项要么已经过时(比如BrowserModule在独立API中会自动处理),要么应该仅在组件级别按需导入。
内容的提问来源于stack exchange,提问作者Winthorpe

