使用source-map實現對已壓縮發佈的前端代碼的異常捕獲與記錄
代碼壓縮和依賴管理使用webpack
https://www.npmjs.com/package/source-map
npm install source-map --save-dev
(因爲用了webpack組織代碼,所以都可以放在-dev裏了)
在前端部署該代碼,並且在公共依賴包中添加以下內容:
import sourceMap from "source-map"; window.addEventListener("error", function (errorMessage, scriptURI, lineNumber, columnNumber, errorObj) { getMap(errorMessage.filename + ".map", function (data) { let smc = new sourceMap.SourceMapConsumer(data); let originPos = smc.originalPositionFor({ line: errorMessage.lineno, column: errorMessage.lineno }); let xhr = errorMessage.error.xhr || {}; let errMes = { message: errorMessage.message, filename: errorMessage.filename, scriptURI: scriptURI, lineNo: originPos.line, colNo: originPos.column, errorObj: errorObj, xhr:{ ...xhr, status:xhr.status, statusText:xhr.statusText, withCredentials:xhr.withCredentials } }; window.fetch("http://localhost:30010/error", { method: "POST", body: JSON.stringify(errMes), headers: {"Content-Type": "application/json"} }).then(function (res) { console.log(res); res.json().then(function (data) { console.log(data); }); }); }); }); function getMap(path,fn) { fetch(path, {method: "GET"}).then(function (res) { res.json().then(fn) }); }
上述代碼將在異常發生的時候,讀取發生異常的文件對應的.map文件,然後通過source-map包中的new sourceMap.SourceMapConsumer來獲取真正的行列號,然後將其發送至固定的服務器,我設置成了http://localhost;30010/error
對應的數據接收和處理的nodejs服務器代碼如下:
"use strict"; const express = require('express'); const app = express(); const bodyParser = require("body-parser"); const fs = require("fs"); const path = require("path"); // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: true })); // parse application/json app.use(bodyParser.json()); app.all('*', function (req, res, next) { let allowedOrigins = [ "http://localhost:8080", "http://localhost:12344", "http://localhost:3313", "http://localhost:63342" ]; // 這裏是允許跨域的的domain列表 let origin = req.headers.origin; if(allowedOrigins.indexOf(origin) > -1){ res.setHeader('Access-Control-Allow-Origin', origin); } res.header('Access-Control-Allow-Credentials', true);// Allow Cookie res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); next(); }); app.post("/error", function (req,res) { console.log(req.body); let fileName = (new Date()).toLocaleDateString().split("/").join("_") + ".txt"; let pathName = path.join(__dirname,"/log/" + fileName); fs.readdir("log", function (err,data) { console.log(err); console.log(data); let a; if (err != null) { fs.mkdir("log"); a = -1; } else { a = data.findIndex(function (item) { console.log(item); console.log(fileName); return item == fileName; }); } console.log(a); req.body.time = (new Date()).toLocaleTimeString(); let logData = JSON.stringify(req.body) + ",,,\n"; if (a != -1) { fs.appendFile(pathName,logData,"utf-8", function (err) { res.writeHead(200,{ "Content-Type":"text/plain;charset=utf-8" }); res.end(JSON.stringify({status:"接受異常"})); }); } else { fs.writeFile(pathName,logData,"utf-8", function (err) { res.writeHead(200,{ "Content-Type":"text/plain;charset=utf-8" }); res.end(JSON.stringify({status:"接受異常"})); }); } }); //res.writeHead(200,{ // "Content-Type":"text/plain;charset=utf-8" //}); //res.end(JSON.stringify({status:"接受異常"})); }); app.listen(30010);
當然也可以把使用source-map解析.map文件得到行列號的操作在服務器進行,只要服務器讀取本地的.map文件就可以了。
因爲我用了webpackServer,所以在一開始爲了方便就把原始行列號的獲取寫在客戶端了。實際部署中這一步肯定是要在服務端的。因爲map文件太大了。。。
轉載地址:https://www.cnblogs.com/Totooria-Hyperion/p/5799494.html