什麼是原始碼對映?

前端小智發表於2023-04-20
微信搜尋 【大遷世界】, 我會第一時間和你分享前端行業趨勢,學習途徑等等。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

先看下本篇主要內容:

文篇主要介紹原始碼對映,原始碼對映(Source maps)是以.map結尾的檔案,例如example.min.js.mapstyles.css.map。大多數構建工具都可以生成原始碼對映檔案,例如Vite、webpack、Rollup、Parcel、esbuild等,一些工具預設包含原始碼對映,而其他工具則需要額外的配置才能生成它們。

使用原始碼對映可以方便地在開發過程中進行除錯,因為它們提供了一種將壓縮、混淆和最佳化的程式碼還原為原始原始碼的方法。這對於診斷和修復錯誤非常有幫助,特別是在生產環境中。原始碼對映還可以幫助你確定哪些程式碼行負責執行特定的功能,以及從哪裡呼叫了特定的函式。

儘管原始碼對映非常有用,但是它們會增加檔案大小並增加伺服器的負載。因此,在生產環境中通常會禁用它們,而在開發過程中啟用它們以便進行除錯。如果你使用的構建工具不支援原始碼對映,則有可能需要手動編寫它們。

下面是正文~~~~

今天,我們要談論原始碼對映,這是現代 Web 開發中非常重要的工具,可以顯著地簡化除錯過程。在本文中,我們將探討原始碼對映的基礎知識,它們是如何生成的,以及它們如何提高除錯體驗。

需要原始碼對映

回到過去的美好時光,我們使用純HTML、CSS和JavaScript構建Web應用程式,並將相同的檔案部署到Web上。

然而,隨著我們現在構建更復雜的Web應用程式,開發工作流可能涉及使用各種工具。例如:

  • 模板語言和HTML前處理器:Pug,Nunjucks,Markdown
  • CSS 前處理器:SCSS、LESS、PostCSS
  • JavaScript 框架:Angular、React、Vue、Svelte
  • JavaScript元框架:Next.js,Nuxt,Astro
  • 高階程式語言:TypeScript、Dart、CoffeeScript

image.png

這些工具需要構建過程將我們的程式碼轉換為標準的 HTML、JavaScript 和 CSS,以便瀏覽器能夠理解。此外,為了最佳化效能,通常會壓縮(例如使用 Terser 來縮小和混淆 JavaScript)和合並這些檔案,減小它們的大小並使它們更適合於Web。

例如,使用構建工具,我們可以將以下TypeScript檔案轉換並壓縮為一行JavaScript程式碼。

/* A TypeScript demo: example.ts */

document.querySelector('button')?.addEventListener('click', () => {
  const num: number = Math.floor(Math.random() * 101);
  const greet: string = 'Hello';
  (document.querySelector('p') as HTMLParagraphElement).innerText = `${greet}, you are no. ${num}!`;
  console.log(num);
});

一個壓縮版本將是:

/* A compressed JavaScript version of the TypeScript demo: example.min.js  */

document.querySelector("button")?.addEventListener("click",(()=>{const e=Math.floor(101*Math.random());document.querySelector("p").innerText=`Hello, you are no. ${e}!`,console.log(e)}));

然而,這種最佳化可能會使除錯變得更具挑戰性。將所有內容壓縮到單行中並縮短變數名稱的壓縮程式碼可能會使問題的源頭難以確定。這就是源對映的作用——它們將編譯後的程式碼對映回原始程式碼。

生成原始碼對映

源對映是以 .map 結尾的檔案(例如, example.min.js.map 和 styles.css.map )。它們可以由大多數構建工具生成,例如 Vite、webpack、Rollup、Parcel、esbuild 等等。

一些工具預設包含原始碼對映,而其他一些工具可能需要額外的配置才能生成它們。

/* Example configuration: vite.config.js */
/* https://vitejs.dev/config/ */

export default defineConfig({
  build: {
    sourcemap: true, // enable production source maps
  },
  css: {
    devSourcemap: true // enable CSS source maps during development
  }
})

理解原始碼對映

這些源對映檔案包含有關編譯程式碼如何對映到原始程式碼的基本資訊,使開發人員能夠輕鬆除錯。這是一個源對映的示例。

{
  "mappings": "AAAAA,SAASC,cAAc,WAAWC, ...",
  "sources": ["src/script.ts"],
  "sourcesContent": ["document.querySelector('button')..."],
  "names": ["document","querySelector", ...],
  "version": 3,
  "file": "example.min.js.map"
}

源對映的最關鍵方面是 mappings 欄位。它使用 VLQ 基於 64 編碼的字串將編譯檔案中的行和位置對映到相應的原始檔案。可以使用源對映視覺化工具(如 source-map-visualizationSource Map Visualization)來視覺化此對映。

image.png

左側生成的列顯示壓縮內容,右側原始列顯示原始來源。視覺化工具會為原始列中的每一行和生成列中對應的程式碼進行著色編碼。

對映部分顯示了程式碼的解碼對映。例如,條目 65-> 2:2 的意思是:

  • 生成的程式碼:單詞 const 在壓縮內容中的位置為65。
  • 原始程式碼:單詞 const 在原始內容中的第2行第2列開始。

image.png

瀏覽器開發者工具應用這些源對映,幫助我們更快地定位除錯問題,直接在瀏覽器中進行。

image.png

該圖顯示了瀏覽器開發者工具如何應用源對映,並顯示檔案之間的對映關係。

源對映支援擴充套件。擴充套件是以 x_ 命名約定開頭的自定義欄位。一個例子是由 Chrome DevTools 提出的 x_google_ignoreList 擴充套件欄位。請參閱 x_google_ignoreList 以瞭解這些擴充套件如何幫助您專注於我們的程式碼。

它不完美

在我們的示例中,變數 greet 在構建過程中被最佳化掉了。該值直接嵌入到最終的字串輸出中。

image.png

在這種情況下,當我們除錯程式碼時,開發人員工具可能無法推斷和顯示實際值。這不僅是瀏覽器開發人員工具的挑戰,也使程式碼監視和分析更加困難。

image.png

當然,這是一個可以解決的問題。其中一種方法是像其他程式語言一樣,在源對映中包含範圍資訊,以便進行除錯。

然而,這需要整個生態系統共同努力改進源對映規範和實現。目前正在積極討論如何透過源對映來提高除錯效能。

我們期待著改進原始碼對映,使除錯變得更加簡單!

原文:https://web.dev/source-maps/

程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章