1. 程式人生 > 其它 >在生產環境中除錯 Angular 應用程式而不顯示源對映

在生產環境中除錯 Angular 應用程式而不顯示源對映

當我們的 Angular 應用程式部署到生產環境時,我們經常會遇到與我們在開發過程中編輯的不同的程式碼。我們的程式碼在構建過程中會以各種方式進行修改和優化。

TypeScript 被 transpiled, minified 和 uglifed。生成的 JavaScript 包儘可能小,並且能夠在瀏覽器中執行。

所有這些概念都很棒,因為它們提高了我們應用程式的效能。但是,這也給生產系統的故障排查帶來了一些困難。

SourceMap 是一個解決方案。

從本質上講,源對映是一個 JSON 檔案,其中包含將轉譯後的程式碼映射回原始源所需的所有資訊。很酷!
從技術上講,源對映只是一個包含以下欄位的 JSON 檔案:

  • version : 表示源對映規範版本
  • file : 此源對映所屬的轉譯檔案的名稱
  • sourceRoot : basePath — 源相對於這裡
  • sources : 原始原始檔的路徑(例如 TypeScript 檔案)
  • sourcesContent : 可選屬性,可以包含您的整個原始碼。當原始碼在此屬性中內聯時,無需託管原始碼即可檢索。
  • names:程式碼中找到的方法或變數名稱
  • mappings:這是整個魔術發生的地方。從技術上講,對映屬性是一個非常大的字串,其中包含Base64 VLQ(可變長度數量)值。這些值有助於找到原始檔中的原始位置。

如何檢索源對映?

要檢索源對映,我們需要告訴瀏覽器它們所在的位置。我們可以通過新增以下行在檔案末尾指定
sourceMappingURL:

例子:

//# sourceMappingURL=pathToSourceMaps

有了這些資訊,瀏覽器就可以下載源對映檔案並解釋其內容以建立對映。

注意:瀏覽器僅在開發者工具開啟時下載源地圖。對於普通使用者,沒有效能影響。

除了在檔案末尾添加註釋之外,您還可以SourceMap在獲取 minified 的 JavaScript 檔案的響應中將路徑作為HTTP 標頭的值傳送。

SourceMap: pathToSourceMap

第二種可能性使您可以在伺服器端切換源對映,而無需更改 minified 之後的 JavaScript 檔案。

開發和生產期間的源對映

開發和生產版本不同。

在開發過程中,擁有完整的源圖是有意義的,因為我們專注於工具、開發經驗或 hot module 替換。

另一方面,在生產中,我們專注於效能——使用 small bundles 快速初始載入。

應該在生產過程中啟用源對映嗎?

這個問題的答案很大程度上取決於您的專案。如果您正在從事開源專案,那麼肯定是這樣。

但是我們大多數人在日常工作中並不從事開源專案。在企業專案中,您有充分的理由不想公開您的原始碼。

  • 我們不想暴露易於閱讀的應用程式程式碼給外界。
  • 更快的構建
  • 不想暴露 source map 的提供源頭

下面介紹如何在生產環境啟用 Source Map,但是不暴露其來源。

Angular CLI 允許我們配置是否需要源對映。然後它將這些資訊傳遞給底層的 Webpack。

要探索 Angular 中的源對映,讓我們從一個由 Angular CLI 生成的全新 Angular 專案開始。

ng new sourceMapInspector

Component 實現很簡單:

public changeTitle(): void {
  this.title = 'awesome app';
}

模板裡的消費程式碼:

<button (click)="changeTitle()">Change title</button>

使用 ng serve 命令。

源對映幫助我們在開發工具中顯示我們的原始源。

我們現在可以開啟app.component.ts並在changeTitle函式內放置一個斷點。通過單擊“更改標題”按鈕,我們然後點選了我們的斷點。

如果我們檢視 main.js 檔案的最後一行,我們可以看到瀏覽器獲取源對映的位置。

//# sourceMappingURL=main.js.map
這對開發非常有用。我們有完整的源對映,可以輕鬆除錯我們的程式碼。

讓我們檢查一下 Angular 中的生產構建在源對映方面的行為。我們可以使用以下命令執行 prod 構建。

ng build --prod

該 dist 資料夾現在包含沒有 source map 的捆綁檔案。讓我們切換到該dist資料夾並在 HTTP 伺服器上執行該應用程式,以瞭解它在生產中的外觀。

可以使用 npm 模組http-server作為本地 Web 伺服器。
http-server 是一個簡單的、零配置的命令列 http 伺服器,可以安裝 npm i -g http-server

因此,讓我們執行我們的生產版本並開啟開發工具來除錯我們的功能。

在生產模式下,沒有來源,也沒有可供點選的 Webpack 選單項。

我們在哪裡設定斷點?我們需要手動在轉換後的 JavaScript 檔案中找到我們的函式,這很麻煩。
我們在第 7841 行設定了斷點,即使我們的應用程式只包含幾行程式碼。

將源對映新增到 Angular 生產構建

angular.json 檔案包含一個 architect 屬性,允許我們指定是否要為我們的生產構建使用源對映。

要啟用源對映,我們需要將 sourceMap 屬性更改為 true或通過傳遞 --source-map 給我們的 ng build 命令來覆蓋它。

這種方法會將源對映新增到我們的生產構建中並在生產中獲取它們,以便每個人都可以訪問我們的源。

對源對映的細粒度控制️

Angular 7.2 為我們提供了對源對映的更細粒度控制。該 sourceMap 屬性現在接受具有以下屬性的物件,而不是一個簡單的 boolean 值。

"sourceMap": {
  "hidden": true,
  "scripts": true,
  "styles": true
}

scripts 和 styles 屬性允許我們只為 scripts 或者 styles 生成 source map.

而 hidden 屬性,顧名思義,可以生成隱藏的 source map.

源對映本身對於常規構建或帶有隱藏源對映的構建沒有區別。只有生成的包在一行中有所不同——webpack 新增的用於檢索源對映的註釋。

讓我們看一下使用源對映生成的包。

注意最後的一行註釋語句。當我們開啟開發工具時,瀏覽器將解釋此註釋並嘗試獲取源對映。現在讓我們看一下使用隱藏源對映生成的包。

我們可以看到檔案末尾沒有添加註釋。因此瀏覽器不會嘗試獲取源對映。如果有一種方法可以使用一些簡單的 npm 指令碼來處理生產環境中的源對映呢?

上傳本地源地圖

我們總是可以在本地重新生成源對映並在以後上傳它們。

"sourceMap": { 
  "hidden": true, 
  "scripts": true, 
  "styles": true 
}

接下來,我們需要建立一個 postbuild 指令碼,該指令碼僅刪除我們剛剛生成的源對映。

"postbuild": "rm dist/sourceMapInspector/*.map"

該 postbuild 指令碼是必需的,否則我們將提供源對映。由於缺少 comment,它們不會被解析。但他們仍然被提供。

為了在生產中進行除錯,我們手動上傳源對映。但是我們從哪裡得到它們呢?我們剛剛刪除了它們。
答案很簡單,我們需要重新生成它們。

"build:sourcemaps": "ng build --prod --output-path=localSourceMaps"

我們現在可以使用 Chrome 開發工具從本地檔案系統上傳源對映。因此,開啟開發工具並右鍵單擊您的main[hash].js. 現在輸入上面指令碼生成的源對映的路徑。

必須按以下方式新增路徑:file///pathToFile.

更多Jerry的原創文章,盡在:"汪子熙":