UI5 Source code map機制的細節介紹

i042416發表於2018-05-06

在我的部落格A debugging issue caused by source code mapping裡我介紹了在我做SAP C4C開發時遇到的一個曾經困擾我很久的問題,最後結論是這個問題由於JavaScript的source code map機制在Chrome開發者工具裡起作用,其實是working as designed的一種行為。但是當時因為時間限制,沒有去深入學習JavaScript source code map的更多細節。

在這篇文章裡我用一個簡單的UI5應用來研究該機制。這個應用的UI僅僅包含一個Button,點選之後彈出一個Message Toast。

下面是我XML view和Controller的實現。

UI5 Source code map機制的細節介紹
UI5 Source code map機制的細節介紹

開啟Chrome開發者工具裡的source code map開關:

UI5 Source code map機制的細節介紹

然後瀏覽器裡訪問這個UI5應用,我們就能在Chrome開發者工具裡看到這些UI5庫檔案的除錯版本(.dbg.js)。但是在Chrome開發者工具的Network標籤裡,我們觀察不到這些除錯版本檔案的載入。那麼問題來了:這些.dbg.js檔案從哪裡來的?

UI5 Source code map機制的細節介紹
UI5 Source code map機制的細節介紹

當關閉Chrome開發者工具的source code map功能之後,我們在Chrome開發者工具裡再也觀察不到這些.dbg.js檔案了。將下圖和source code map開啟時的截圖做比較:

UI5 Source code map機制的細節介紹

如何在本地找到sap-ui-core.js.map檔案

單擊sap-ui-core.js,在其最後一行1875行,看到該行內容:

 //# sourceMappingURL=sap-ui-core.js.map 

這個檔案的字尾.map給了我們提示:其作用就是維護位置對映關係,將sap-ui-core.js(壓縮之後的檔案)裡的程式碼位置對映到壓縮之前的程式碼位置(來自壓縮之前的檔名,程式碼行數,程式碼列數,涉及到的壓縮之前的JavaScript變數名)。

UI5 Source code map機制的細節介紹

但是,同樣的,我在開發者工具的Network標籤裡也觀察不到這個.map檔案被載入。

UI5 Source code map機制的細節介紹

在Chrome裡輸入url: "chrome://net-internals/#events", 結果顯示確實有一個url請求去訪問sap-ui-core.js.map, 只是因為本地磁碟快取能響應該請求, 因此沒有產生真正的網路請求:

UI5 Source code map機制的細節介紹

在Chrome裡輸入"chrome://cache"能看到Chrome本地的所有快取,從這裡我成功找到了檔案sap-ui-core.js.map的本地快取。

UI5 Source code map機制的細節介紹

單擊該超連結能看到這條快取的抬頭資訊。但是快取的具體檔案內容顯示格式為HEX,沒法直接分析。

UI5 Source code map機制的細節介紹

因此我使用了工具Cache viewer for Google Chrome Web browser, 將該快取匯出成本地檔案。

UI5 Source code map機制的細節介紹

sap-ui-core.js.map檔案內容一覽

這篇部落格Introduction to JavaScript Source Maps介紹了JavaScript source code map的基本知識。

檔案sap-ui-core.js.map的內容:

UI5 Source code map機制的細節介紹
  • version: 3

.map檔案的各組成部分的作用和含義定義在一個叫做Source Map Revision Proposal的協議文件裡,在我的例子sap-ui-core.js.map裡使用了該協議的第三版。

  • sources:

這是一個陣列,包含了所有用於生成壓縮之後的js檔案的原始檔案的名稱。

  • names:

這是一個陣列,包含了原始js檔案裡出現的JavaScript變數和屬性名稱。

下面是一個例子,體現了原始檔案之一Device-dbg.js裡的變數名稱和其在sap-ui-core.js.map檔案裡的names陣列裡的對應記錄,方便您理解。

UI5 Source code map機制的細節介紹
  • mappings:

.map檔案最重要的部分,定義了原始檔案內的位置和生成壓縮版本檔案內位置的對應關係。對應關係記錄的粒度是基於壓縮之後檔案的每一行,用分號隔開。這樣做的好處是無需再分配而外的位來維護壓縮檔案位置的行號資訊。

UI5 Source code map機制的細節介紹

回到我的例子,壓縮檔案sap-ui-core.js一共包含1874行,因此sap-ui-core.js.map一共出現了1874次分號,每個分號內又是一個很長的字串,由一系列逗號隔開,這些由逗號隔開的字串片段稱為Segment。每個Segment維護了一個位置的對映關係。

UI5 Source code map機制的細節介紹

如何生成.map檔案

有很多開源的元件用於生成.map檔案,其中之一是Google Closure compiler。假設我想基於我的測試應用裡的controller實現檔案App.controller.js生成一個壓縮版本的檔案:

Google網站下載compile.jar, 然後生成一個名為script-min.js的壓縮檔案和script-min.js.map:

 java -jar compile.jar --js App.controller.js --create_source_map ./script-min.js.map --source_map_format=V3 --js_output_file script-min.js 

生成的壓縮檔案script-min.js只有1行內容:

UI5 Source code map機制的細節介紹

生成的script-min.js.map內容:

UI5 Source code map機制的細節介紹

可以使用vlq.js將這些segment解碼:

UI5 Source code map機制的細節介紹

瀏覽器開啟該html,產生如下輸出:每個segment由4或5個字元組成。

UI5 Source code map機制的細節介紹

每一位的對應含義:

  • 第一位,表示這個位置在轉換後的壓縮檔案的第幾列。

  • 第二位,sources陣列中的索引,表示這個位置來自哪一個原始檔案。

  • 第三位,表示這個位置屬於原始檔案的第幾行。

  • 第四位,表示這個位置屬於原始檔案的第幾列。

  • 第五位,names陣列中的索引,表示這個位置屬於原始檔中的哪一個變數。

關於VLQ編碼的更多細節,可以閱讀這篇部落格Source Maps under the hood – VLQ, Base64 and Yoda

要獲取更多Jerry的原創技術文章,請關注公眾號"汪子熙"或者掃描下面二維碼:

UI5 Source code map機制的細節介紹
UI5 Source code map機制的細節介紹

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2153871/,如需轉載,請註明出處,否則將追究法律責任。

相關文章