部署前端以前,開發者一般會對代碼進行打包壓縮,這樣能夠減小代碼大小,從而有效提升訪問速度。然而,壓縮代碼的報錯信息是很難Debug的,由於它的行號和列號已經失真。這時就須要Source Map來還原真實的出錯位置了。javascript
前端代碼愈來愈複雜的狀況下,開發者一般會使用webpack、UglifyJS2等工具對代碼進行打包變換,這樣能夠減小代碼大小,有效提升訪問速度。關於變換代碼的緣由,這裏不妨引用一下大神阮一峯的JavaScript Source Map 詳解:html
- 壓縮,減少體積。好比jQuery 1.9的源碼,壓縮前是252KB,壓縮後是32KB。
- 多個文件合併,減小HTTP請求數。
- 其餘語言編譯成JavaScript。最多見的例子就是CoffeeScript。
下面是一個簡單的「hello World」程序hello.js前端
function sayHello() {
var name = "Fundebug";
var greeting = "Hello, " + Name;
console.log(greeting);
}
sayHello();
複製代碼
使用UglifyJS2對源代碼進行壓縮變換:java
uglifyjs hello.js \
-m toplevel=true \
-c unused=true,collapse_vars=true \
-o hello.min.js
複製代碼
壓縮後的代碼hello.min.jswebpack
function o(){var o="Hello, "+Name;console.log(o)}o();
複製代碼
使用Firefox執行hello.js的報錯信息是這樣:git
ReferenceError: Name is not defined
sayHello file:///Users/fundebug/sourcemap-tutorial/hello.js:4:9
<匿名> file:///Users/fundebug/sourcemap-tutorial/hello.js:8:1
複製代碼
而hello.min.js的報錯信息是這樣:github
ReferenceError: Name is not defined
o file:///Users/fundebug/sourcemap-tutorial/hello.min.js:1:18
<匿名> file:///Users/fundebug/sourcemap-tutorial/hello.min.js:1:59
複製代碼
對比壓縮先後的出錯信息,咱們會發現,錯誤行號和列號已經失真,且函數名也通過了變換。而對於真實的前端項目,開發者會將數十個源文件壓縮爲一個文件,這時,錯誤的列號可能多達數千,且出錯的真實文件名也是很難肯定的,這樣的話,壓縮代碼的報錯信息是很難Debug的。web
而Source Map則能夠用於還原真實的出錯位置,幫助開發者更快的Debug。小程序
使用UglifyJS2時指定source-map選項便可生成Source Map:微信小程序
uglifyjs hello.js \
-m toplevel=true \
-c unused=true,collapse_vars=true \
--source-map hello.min.js.map \
--source-map-include-sources \
--source-map-root \
-o hello.min.js
複製代碼
各類主流前端任務管理工具,打包工具都支持生成Source Map,具體能夠查看生成Source Map - Fundebug文檔。
生成的hello.min.js多了sourceMappingURL,表示Source Map文件的位置。
function o(){var o="Hello, "+Name;console.log(o)}o();
//# sourceMappingURL=hello.min.js.map
複製代碼
生成的Source Map爲hello.min.js.map:
{
"version": 3,
"sources": ["hello.js"],
"names": ["sayHello", "greeting", "Name", "console", "log"],
"mappings": "AAAA,QAASA,KAEL,GACIC,GAAW,UAAYC,IAC3BC,SAAQC,IAAIH,GAGhBD",
"file": "hello.min.js",
"sourceRoot": "",
"sourcesContent": ["function sayHello()\n{\n var name = \"Fundebug\";\n var greeting = \"Hello, \" + Name;\n console.log(greeting);\n}\n\nsayHello();\n"]
}
複製代碼
由hello.min.js.map可知,Source Map是一個JSON文件,而它包含了代碼轉換先後的位置信息。也就是說,給定一個轉換以後的壓縮代碼的位置,就能夠經過Source Map獲取轉換以前的代碼位置,反過來也同樣。Source Map各個屬性的含義以下:
Source Map真正神奇之處在於mappings屬性,它記錄了位置是如何對應的。JavaScript Source Map 詳解已經有很好的解釋,這裏再也不贅述。
主流瀏覽器均支持Source Map功能,不過Chrome與Firefox須要一些簡單的配置,具體步驟請參考How to enable source maps。下面以MacBook上的Chrome瀏覽器爲例,介紹一下配置方法:
使用快捷鍵option + command + i;或者在菜單欄選擇視圖->開發者->開發者工具
使用快捷鍵fn + F1;或者點擊右上角的三個點的圖標,選擇Settings
在Sources中,選中Enable JavaScript source maps
爲了測試,我寫了一個簡單的HTML文件hello.min.html
<head>
<script type="text/javascript" src="hello.min.js"></script>
</head>
複製代碼
使用Chrome打開hello.min.html,在控制檯看到的錯誤以下:
Uncaught ReferenceError: Name is not defined
at o (hello.min.js:1)
at hello.min.js:1
複製代碼
報錯的文件仍然爲hello.min.js,須要刷新一下Source Map纔有做用:
Uncaught ReferenceError: Name is not defined
at o (hello.js:4)
at hello.js:8
複製代碼
注意,Chrome的報錯信息沒有列號,所以4爲錯誤的行號。Chrome不只能夠經過Source Map還原真實的出錯位置,還能夠根據Source Map的sourcesContent還原出錯的源代碼。點擊出錯位置,便可跳轉到源碼,這樣Debug將很是方便。
Fundebug專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了6億+錯誤事件,獲得了Google、360、金山軟件等衆多知名用戶的承認。歡迎免費試用!
轉載時請註明做者Fundebug以及本文地址:
blog.fundebug.com/2017/03/13/…