外部依賴和API的關聯主要可以分成以下幾類:
- 後端API請求: 前端應用與後端服務進行數據交換的方式,通常包括向 RESTful API 發送 HTTP 請求。
- 全域狀態管理: 使應用中的狀態可以在不同組件之間共享和管理,並且透過動作來控制狀態變更,確保狀態的統一性和可追蹤性。
- 第三方服務: 應用集成的外部系統或工具,用來提供額外的功能,如身份驗證、支付處理或數據分析。
首先談談後端API,要快速找到一個 Component 與後端 API 之間的關係,可以透過以下幾個來追蹤:
檢查Component的constructor是否注入了與API有關的Service,抑或是使用Angular的Inject()注入,因為一般情況下,後端API會透過服務進行抽象而非Component中直接呼叫。
//建構子注入
constructor(private apiService: ApiService) { }
//Inject Function注入
private apiService2 = Inject(ApiService2);
//在OnInit時候呼叫了apiService中的方法
ngOnInit(): void {
this.apiService.getData().subscribe(response => {
this.data = response;
});
}
前往被注入的Service檔案,檢查內部是否有進行http請求。
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get('https://api.example.com/data');
}
}
也可能會遇到HttpClient因所有請求都有固定的邏輯處理,所以被抽象成一隻自訂Service的情況。必要時會需要多看幾層。
通常前端習慣將該專案會使用到的各個Domain寫在environment檔案中,並且透過angular.json中不同的configuration進行檔案置換來切換環境。可以透過檢查這裡的domain來找到那些位置呼叫了後端API。
export const environment = {
production: false,
apiBaseUrl: 'https://api.example.com'
};
以NgRx為例,我們常在Effects裡面處理Api請求,所以別忘了看看Component或Service中有無透過NgRx的Dispatch語法發起Action,觸發Effect進行API呼叫。
@Injectable()
export class DataEffects {
loadData$ = createEffect(() =>
this.actions$.pipe(
ofType(loadData),
mergeMap(() => this.apiService.getData()
.pipe(
map(data => loadDataSuccess({ data })),
catchError(() => of(loadDataFailure()))
))
)
);
}
接著是關於全域狀態管理的部分,在Angular專案中,我們經常會遇到跨Component的資料,且這些資料是有狀態的。比如,一個商城中有複數頁面需要顯示會員帳戶剩餘的點數,且點數必須是即時的,此時我們會希望會員點數這項資料在專案中有獨立的儲存點。此時就是使用全域狀態管理工具的時候,而其中最常和Angular搭配的就是NgRx了。
NgRx核心概念包括:
- Actions:用來描述應用中發生的事件(事件觸發的動作)。
- Reducers:用來根據 actions 改變應用狀態的純函數。
- Store:存儲應用的全局狀態,並且它是一個可觀察物件,可以訂閱其變化。
- Effects:用來處理 side effects(副作用),例如 HTTP 請求。這些 effects 允許透過 RxJS 的操作符對 actions 作出反應,並且可以在完成異步操作後發送新的 actions。
延伸閱讀: Mike大神的NgRx大全
尋找Component中是否使用NgRx的方式非常簡單,
檢查Component的constructor或Inject()是否注入了Store,因為NgRx 通常依賴於 Store。
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
constructor(private store: Store<AppState>) {}
//發起Action
this.store.dispatch(new LoadItems());
//訂閱狀態
this.items$ = this.store.select(selectItems);
最後是第三方服務,其實NgRx就算是一種第三方服務,可以發現通常特點是會有一些沒看過的語法糖或是套件包的import。他的查找方式不外乎語前面相似,不過我可能會額外注意下面幾個位置。(其實這部分,若公司內部沒有文件真的不太容易找)
- index.html有無注入腳本
- package.json的套件包
- http呼叫有無外部的domain
- angular.json 有無script
- html中有無奇怪的html tag
- ts檔中有無特殊語法糖
若上述的項目都更新到圖表上,目前圖表大致會長這樣
除了WebServer的部分,我們基本都把關聯串起來了。
關於WebServer的部分我認為這真的只有靠文件記錄或是詢問同事了,前端的靜態資源是被放在公司的哪台主機或是AWS的哪一個S3 Bucket這的確不太能透過TraceCode就找到。
比較可以給方向的地方應該會是,若專案是有做自動化部屬的,那麼大概率可以在專案中找到部屬用的yml檔案,可以往那去尋找應該是可以找到的。如果是全手動部屬那就比較難了。加上部屬環境後圖表大致會長這樣。
到這系統架構圖的部分就告一段落,下一篇文章我們會前進系統流程圖!