使用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