Angular 9.1.0在項目路徑包含軟鏈接時編譯某些包時報錯,9.1.1已修正

背景

這是一個多種因素綜合導致的bug,排查問題花了一些時間,特別是版本9.1.09.1.1這種小版本號的差別導致不同的運行結果容易被忽視。

某個部署環境之前的用於編譯的Angular的版本是9.1.0,項目路徑是硬鏈接。編譯正常,整理存儲時,改成了軟鏈接,編譯就失敗了。而開發機上編譯正常,改用軟鏈接也在開發機上測試過,因此在開始調研的時候就忽視了這個問題。調查的彎路就略過了,整理一個最小重現的情況。

最小重現的排查過程

@angular/compiler-cli的版本爲9.1.0是,也就是package.json中爲:

"@angular/compiler-cli": "9.1.0",

運行編譯命令

yarn run build

可以看到編譯7個目標

						Compiling @angular/core : es2015 as esm2015
						
						Compiling @angular/common : es2015 as esm2015
						
						Compiling @angular/platform-browser : es2015 as esm2015
						
						Compiling @angular/platform-browser-dynamic : es2015 as esm2015
						
						Compiling @angular/common/http : es2015 as esm2015
						
						Compiling @angular/router : es2015 as esm2015
						
						Compiling @nguniversal/common : es2015 as esm2015

然後就是報錯

    ERROR in ./node_modules/@angular/common/http/http.d.ts:2801:22 - error NG6002: Appears in the NgModule.imports of AppModule, but could not be resolved to an NgModule class.
    
    This likely means that the library (@angular/common/http) which declares HttpClientModule has not been processed correctly by ngcc, or is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy.
    
    2801 export declare class HttpClientModule {
                              ~~~~~~~~~~~~~~~~

其中IvyAngular的編譯引擎,從版本9開始作爲默認選項,在這裏花了很長時間看文檔,沒有找到有針對性的資料。加之之前一直認爲node_modules中只是下載的包,所以開始調查的時候沒有看node_modules裏面,後來比較細緻調查的時候,翻看裏面的文件,發現這個文件夾:

./node_modules/@angular/core/__ivy_ngcc__

這時候才注意到Ivy是把中間結果編譯在這裏,之前一直想當然的認爲可能是在某個臨時文件夾中。

然後按照編譯目標逐個對照發現

./node_modules/@angular/common/__ivy_ngcc__

僅包含common

							└── fesm2015
							    ├── common.js
							    └── common.js.map

而開發機上還包含http.jshttp.js.map

						└── fesm2015
						    ├── common.js
						    ├── common.js.map
						    ├── http.js
						    └── http.js.map

少編譯了一個目標,然而並沒有在這個環節報錯,因此在後面的環節報錯時,就被誤導了一直在後面繞圈。

發現問題後,就逐步縮小差異,最後定位到了@angular/compiler-cli版本,當版本爲9.1.0時,報錯如前所示。升級到9.1.1後,儘管只是最小的版本號,http.jshttp.js.map兩個文件出現了,編譯也正常了。翻了一下Angular 9.1.1的發佈說明,2020年4月7日,這個時間點正好是部署環境升級到了9.1.0,而開發機後來又自動升級,因而導致結果不一致。如果兩邊都出錯的話,也就不會這麼大費周章了。

9.1.1 (2020-04-07)
Bug Fixes
compiler: avoid undefined expressions in holey array (#36343) (90cae34)
compiler: resolve enum values in binary operations (#36461) (cbc25bb), closes #35584
compiler-cli: pass real source spans where they are empty (#31805) (4894220)
core: avoid migration error when non-existent symbol is imported (#36367) (dff52ec), closes #36346
core: ngOnDestroy on multi providers called with incorrect context (#35840) (af42694), closes #35231
core: run APP_INITIALIZERs before accessing LOCALE_ID token in Ivy TestBed (#36237) (5c28af0), closes #36230
core: undecorated-classes-with-decorated-fields migration does not decorate derived classes (#35339) (5ff5a11), closes #34376
core: undecorated-classes migration should handle derived abstract classes (#35339) (a631b99)
language-service: infer type of elements of array-like objects (#36312) (ff523c9), closes #36191
language-service: use the HtmlAst to get the span of HTML tag (#36371) (ffa4e11)
ngcc: add process title (#36448) (136596d), closes /github.com/angular/angular/issues/36414#issuecomment-609644282
ngcc: allow ngcc configuration to match pre-release versions of packages (#36370) (cb0a2a0)
ngcc: correctly detect imported TypeScript helpers (#36284) (879457c), closes #36089
ngcc: correctly identify relative Windows-style import paths (#36372) (0daa488)
ngcc: correctly identify the package path of secondary entry-points (#36249) (e53b686), closes #35747
ngcc: detect non-emitted, non-imported TypeScript helpers (#36418) (93b32d3)
ngcc: do not spawn more processes than intended in parallel mode (#36280) (6ea232e), closes #35719 #36278 /github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts#L429 /github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L108 /github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L110 /github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L199
ngcc: do not write entry-point manifest outside node_modules (#36299) (bb8744d), closes #36296
ngcc: don't crash on cyclic source-map references (#36452) (56af303), closes #35727 #35757
ngcc: handle bad path mappings when finding entry-points (#36331) (7bb3588), closes #36313 #36283
ngcc: handle entry-points within container folders (#36305) (392ef93), closes #35756 #36216
ngcc: sniff main property for ESM5 format (#36396) (93cbef2), closes #35788
ngcc: support ignoring deep-imports via package config (#36423) (31eaf78), closes #35750
ngcc: support simple browser property in entry-points (#36396) (b0d680d), closes #36062
platform-server: update xhr2 dependency (#36366) (14ae3c0), closes #36358
router: state data missing in routerLink (#36462) (0e7a89a), closes #33173

最後

儘管問題解決了,但是對照了如上所述的Angular 9.1.1的發佈說明,仍舊沒有找到是哪條修正了這個問題。
前端是一個神奇的領域,已經開始踩當月的坑了,現在特別能理解前端同學爲什麼會喊學不動了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章