獨立元件提供更簡化的方式來建置 Angular 應用程式。獨立元件、指令與管道旨在減少對 NgModule 的需求,簡化撰寫體驗。現有的應用程式可以選擇性地逐步採用新的獨立風格,不會造成任何破壞性變更。
這支原理圖能協助將既有專案中的元件、指令與管道轉換為獨立模式。原理圖會盡可能自動轉換程式碼,但可能仍需要專案作者進行一些手動修正。
使用下列指令執行這支原理圖:
ng generate @angular/core:standalone
更新之前
使用這支原理圖之前,請確認專案符合以下條件:
- 使用 Angular 15.2.0 或更新的版本。
- 建置時沒有任何編譯錯誤。
- 位於乾淨的 Git 分支,且所有工作都已儲存。
原理圖選項
| 選項 | 說明 |
|---|---|
mode |
要執行的轉換。可用選項的詳情請參閱下方的遷移模式。 |
path |
要遷移的路徑,相對於專案根目錄。你可以利用這個選項,逐步遷移專案的各個部分。 |
遷移步驟
遷移流程由三個步驟組成。你需要多次執行它,並手動檢查專案是否能正確建置且行為符合預期。
NOTE: 雖然原理圖能自動更新大部分程式碼,但有些邊界情況需要開發者介入處理。 你應預留時間,在遷移的每個步驟後進行手動修正。此外,原理圖新產生的程式碼可能不符合你的程式碼格式規則。
請依照下列順序執行遷移,並在每個步驟之間驗證你的程式碼能正確建置與執行:
- 執行
ng g @angular/core:standalone並選取 "Convert all components, directives and pipes to standalone" - 執行
ng g @angular/core:standalone並選取 "Remove unnecessary NgModule classes" - 執行
ng g @angular/core:standalone並選取 "Bootstrap the application using standalone APIs" - 執行所有程式碼檢查(lint)與格式檢查,修正所有失敗項目,並提交結果
遷移之後
恭喜,你的應用程式已經轉換為獨立模式 🎉。以下是一些你現在可以考慮進行的選用後續步驟:
- 尋找並移除任何殘留的
NgModule宣告:由於「移除不必要的 NgModules」步驟無法自動移除所有模組,你可能需要手動移除其餘的宣告。 - 執行專案的單元測試並修正所有失敗項目。
- 如果專案使用自動格式化,執行所有程式碼格式化工具。
- 執行專案中的所有程式碼檢查工具並修正新增的警告。有些檢查工具支援
--fix旗標,可以自動解決部分警告。
遷移模式
這項遷移有以下模式:
- 將宣告轉換為獨立模式。
- 移除不必要的 NgModules。
- 切換到獨立模式的啟動 API。 你應依照給定的順序執行這些遷移。
將宣告轉換為獨立模式
在此模式下,遷移會移除 standalone: false,並將相依性加入元件、指令與管道的 imports 陣列,把它們全部轉換為獨立模式。
HELPFUL: 原理圖在此步驟會忽略用來啟動元件的 NgModules,因為它們很可能是供 bootstrapModule 使用的根模組,而不是與獨立模式相容的 bootstrapApplication。原理圖會在「切換到獨立模式的啟動 API」步驟中自動轉換這些宣告。
變更前:
shared.module.ts
@NgModule({
imports: [CommonModule],
declarations: [Greeter],
exports: [Greeter],
})
export class SharedModule {}
greeter.ts
@Component({
selector: 'greeter',
template: '<div *ngIf="showGreeting">Hello</div>',
standalone: false,
})
export class Greeter {
showGreeting = true;
}
變更後:
shared.module.ts
@NgModule({
imports: [CommonModule, Greeter],
exports: [Greeter],
})
export class SharedModule {}
greeter.ts
@Component({
selector: 'greeter',
template: '<div *ngIf="showGreeting">Hello</div>',
imports: [NgIf],
})
export class Greeter {
showGreeting = true;
}
移除不必要的 NgModules
將所有宣告轉換為獨立模式之後,許多 NgModules 都可以安全地移除。這個步驟會刪除這類模組宣告,並盡可能刪除對應的參照。如果遷移無法自動刪除某個參照,會留下下列 TODO 註解,讓你可以手動刪除該 NgModule:
/* TODO(standalone-migration): clean up removed NgModule reference manually */
遷移會在模組符合下列條件時,認定它可以安全移除:
- 沒有
declarations。 - 沒有
providers。 - 沒有
bootstrap元件。 - 沒有參照
ModuleWithProviders符號或無法移除之模組的imports。 - 沒有類別成員。空的建構函式會被忽略。
變更前:
importer.module.ts
@NgModule({
imports: [FooComponent, BarPipe],
exports: [FooComponent, BarPipe],
})
export class ImporterModule {}
變更後:
importer.module.ts
// Does not exist!
切換到獨立模式的啟動 API
這個步驟會將所有 bootstrapModule 的用法轉換為新的、基於獨立模式的 bootstrapApplication。它也會移除根元件的 standalone: false,並刪除根 NgModule。如果根模組有任何 providers 或 imports,遷移會嘗試將盡可能多的這類設定複製到新的啟動呼叫中。
變更前:
./app/app.module.ts
import {NgModule} from '@angular/core';
import {App} from './app';
@NgModule({
declarations: [App],
bootstrap: [App],
})
export class AppModule {}
./app/app.ts
@Component({
selector: 'app',
template: 'hello',
standalone: false,
})
export class App {}
./main.ts
import {platformBrowser} from '@angular/platform-browser';
import {AppModule} from './app/app.module';
platformBrowser()
.bootstrapModule(AppModule)
.catch((e) => console.error(e));
變更後:
./app/app.module.ts
// Does not exist!
./app/app.ts
@Component({
selector: 'app',
template: 'hello',
})
export class App {}
./main.ts
import {bootstrapApplication} from '@angular/platform-browser';
import {App} from './app/app';
bootstrapApplication(App).catch((e) => console.error(e));
常見問題
以下常見問題可能會妨礙原理圖正確運作:
- 編譯錯誤:如果專案有編譯錯誤,Angular 就無法正確分析並遷移它。
- 未包含在 tsconfig 中的檔案:原理圖會分析專案的
tsconfig.json檔案,來決定要遷移哪些檔案。任何未被 tsconfig 涵蓋的檔案都會被原理圖排除。 - 無法靜態分析的程式碼:原理圖使用靜態分析來理解你的程式碼,並決定要在哪些地方進行變更。對於中繼資料無法在建置時靜態分析的類別,遷移可能會略過它們。
限制
由於這項遷移的規模與複雜度,有些情況是原理圖無法處理的:
- 因為單元測試不是預先(AoT)編譯的,加入到單元測試中元件的
imports可能不完全正確。 - 原理圖依賴對 Angular API 的直接呼叫。原理圖無法辨識 Angular API 的自訂包裝函式。例如,如果你定義了一個包裝
TestBed.configureTestingModule的自訂customConfigureTestModule函式,它宣告的元件可能無法被辨識。