摘要: Source Map還是很神奇的。
- 公眾號:前端小苑
Fundebug經授權轉載並修改,版權歸原作者所有。
工作中,生產環境程式碼是編譯後程式碼,蒐集到報錯資訊的行和列無法在原始碼中對應,很多時候只能靠“經驗”去猜,本文針對這種情況,開發了一個npm命令列小工具,幫助快速定位報錯的原始碼位置,提升效率。
由於現在構建工具盛行,前端部署的程式碼都是經過編譯,壓縮後的,於是乎,SoueceMap就扮演了一個十分重要的角色,用來作為原始碼和編譯程式碼之間的對映,方便定位問題。
測試SourceMap功能
首先全域性安裝reverse-sourcemap
npm install --global reverse-sourcemap
複製程式碼
選擇編譯後的程式碼進行測試,下面是vue專案編譯生成的程式碼。
在命令列執行命令,將main.js反編譯回原始碼,並輸出到sourcecode目錄下。
reverse-sourcemap -v dist/main.a8ebc11c3f03786d8e3b.js.map -o sourcecode
複製程式碼
上面是執行命令輸出的sourcecode目錄,生成的目錄結構和原始碼目錄一致,開啟一個檔案,和原始碼做下對比:
可以看出,反編譯出的程式碼無論目錄結構還是具體程式碼都和原始碼一致。
生產環境程式碼報錯如何定位原始碼位置
如果使用了Fundebug的Source Map功能的話,則可以很方便的定位出錯位置:
如果沒有使用監控工具的話,生產環境的程式碼,經過壓縮、編譯,很不利於Debug。針對這個問題,需要準備一份生產環境程式碼的map檔案,為了方便,可以在專案的package.json增加debug命令用來生成map檔案。這條命令除了開啟sourcemap,其他的具體webpack配置和生產環境配置相同。
"scripts": {
"start": "vue-cli-service serve --mode dev",
"stage": "vue-cli-service build --mode staging",
"online": "vue-cli-service build",
"debug": "vue-cli-service build --mode debug"
}
複製程式碼
有了map檔案,通過SourceMap提供的API就可以定位到原始碼的位置。下面是實現的核心程式碼。
// Get file content
const sourceMap = require('source-map');
const readFile = function (filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, {encoding:'utf-8'}, function(error, data) {
if (error) {
console.log(error)
return reject(error);
}
resolve(JSON.parse(data));
});
});
};
// Find the source location
async function searchSource(filePath, line, column) {
const rawSourceMap = await readFile(filePath)
const consumer = await new sourceMap.SourceMapConsumer(rawSourceMap);
const res = consumer.originalPositionFor({
'line' : line,
'column' : column
});
consumer.destroy()
return res
}
複製程式碼
最重要的就是使用SourceMap提供的 originalPositionFor API。 SourceMapConsumer.prototype.originalPositionFor(generatedPosition)
originalPositionFor API的引數為一個包含line和column屬性的物件
line 編譯生成程式碼的行號,從1開始
column 編譯生成程式碼的列號,從0開始
這個方法會返回一個具有以下屬性的物件
{
"source": "webpack:///src/pages/common/403.vue?c891", // 原始碼檔案的位置,如果無法獲取,返回null。
"line": 4, // 原始碼的行號,從1開始,如果無法獲取,返回null。
"column": 24, // 原始碼的列號,從0開始,如果無法獲取,返回null。
"name": "get" // 原始碼的標識,如果無法獲取,返回null。
}
複製程式碼
原始碼定位工具
為了使用方便,我將這個功能做成了一個命令列小工具。全域性安裝後,不需要做任何配置就可以使用。
安裝
npm install --global source-location
複製程式碼
引數介紹
Usage: sl [options]
Options:
-v, --version output the version number
-p, --source-flie-path The generated source file 編譯後的map檔案
-l, --ine The line number in the generated source 編譯後程式碼行號
-c, --column The column number in the generated source 編譯後程式碼列號
-h, --help output usage information
複製程式碼
使用案例
終端執行命令:
sl -p dist/1.f47efcb58028826c7c05.js.map -l 1 -c 34
複製程式碼
命令列將會輸出:原始碼的檔案路徑:path,原始碼行號:line,原始碼標識:name。
專案的github地址: github.com/front-end-y… 如有錯誤歡迎指出。
最後,推薦大家使用Fundebug,一款很好用的BUG監控工具,支援Source Map功能~