转载地址:https://www.cnblogs.com/Totooria-Hyperion/p/5799494.html
代码压缩和依赖管理使用webpack
webpack可以通过配置#nosources-source-map模式在本地生成对应文件,打包的在线文件没有soursemap映射文件,不会造成安全问题
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);