Как сделать так, чтобы React Create App Production Граница границы отображалась в исходном коде
Я использую компонент границы ошибок, чтобы ловить реагировать на ошибки, и он работает нормально.
Моя проблема в том, что в производственном приложении ведение журнала является бесполезным, поскольку стек компонентов выглядит следующим образом:
\n in t\n in t\n in t\n in t\n in t\n in div\n in t\n in u\n in n\n in t\n in t
В то время как в среде разработки стек компонентов более удобен:
in ErrorPage (created by Route)\n in Route (at Routes.js:60)\n in Switch (at Routes.js:46)\n in Router (created by BrowserRouter)\n in BrowserRouter (at Routes.js:45)\n in div (at Routes.js:43)\n in ThemeProvider (at theme.js:1262)\n in Theme (at Routes.js:42)\n in Provider (at Routes.js:41)\n in ErrorBoundary (at Routes.js:40)\n in Routes (at index.js:12)
То же самое происходит с сообщением. В производство мы получаем:
t.value (http://localhost:3333/static/js/main.5a3e606e.js:1:680858
Пока в dev:
Uncaught TypeError: Person is not a constructor
at ErrorPage._this.click2 (ErrorPage.js:12)
Есть ли способ заставить реагировать на ошибки отображаться в исходном коде и сделать журналирование действительно полезным в производстве?
ОБНОВЛЕНИЕ: я использую библиотеку под названием http://js.jsnlog.com/ которая обрабатывает журналы и фактически перехватывает все (даже обработчики событий). Вот так выглядит компонент Boundary https://pastebin.com/aBFtD7DB. Проблема не в том, чтобы поймать ошибки, а в том, что на производстве они бесполезны.
2 ответа
Я нашел решение этой проблемы с помощью библиотеки https://www.stacktracejs.com/.
Метод StackTrace.report() будет извлекать карту и получать необходимую вам унифицированную информацию!
Так что теперь моя React Boundary выглядит следующим образом. Я все еще использую window.onerror, чтобы убедиться, что я все поймаю.
Во-первых, не забудьте добавить stacktrace-gps
а также stacktrace-js
в ваш package.json
import React, { Component } from "react";
import StackTrace from "stacktrace-js";
window.onerror = function(msg, file, line, col, error) {
StackTrace.fromError(error).then(err => {
StackTrace.report(
err,
`//${window.location.hostname}:${process.env.REACT_APP_LOGGER_PORT || 3334}/jsnlog.logger`,
{
type: "window.onerror",
url: window.location.href,
userId: window.userId,
agent: window.navigator.userAgent,
date: new Date(),
msg: msg
}
);
});
};
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
componentDidCatch(error, errorInfo) {
this.setState({ error });
StackTrace.fromError(error).then(err => {
StackTrace.report(
err,
`//${window.location.hostname}:${process.env.REACT_APP_LOGGER_PORT || 3334}/jsnlog.logger`,
{
type: "React boundary",
url: window.location.href,
userId: window.userId,
agent: window.navigator.userAgent,
date: new Date(),
msg: error.toString()
}
);
});
}
render() {
if (this.state.error) {
//render fallback UI
return (
<div className="snap text-center">
<p>We're sorry — something's gone wrong.</p>
<p>Our team has been notified</p>
</div>
);
} else {
//when there's not an error, render children untouched
return this.props.children;
}
}
}
export default ErrorBoundary;
Во-первых, важно создать исходную карту. Я сделал это, добавив devtools в конфигурацию webpack для создания исходной карты. Краткий фрагмент этого выглядит следующим образом:
devtools: "source-map",
new UglifyJsPlugin({
sourceMap: true
})
После создания исходных карт я использовал библиотеку https://www.stacktracejs.com/.
Однако, чтобы уменьшить размер пакета на производстве, я не импортировал весь пакет stacktrace. Я реализовал разделение кода на стороне клиента и на стороне сервера.
Клиентская сторона: я импортировал парсер ошибок. Это создает объект, который содержит имя файла, номер строки, номер столбца и имя функции. Я отправляю объект, созданный с помощью этого на сервер.
import ErrorStackParser from "error-stack-parser";
componentDidCatch(error) {
let params = {stackframes: ErrorStackParser.parse(error)};
let url = 'https://example.com';
axios.post(url, params)
}
На стороне сервера я импортировал "stacktrace-gps" и "stackframe" и использовал их, чтобы найти их, чтобы получить номер строки и столбец фактического кода из исходной карты.
const StackTraceGPS = require("stacktrace-gps");
const request = require("request");
var logger = function(req, res) {
let stackframes = req.body.stackframes;
let stackframe = new StackFrame(
stackframes[0]
); /* Getting stack of the topmost element as it contains the most important information */
/* We send extra ajax function to fetch source maps from url */
const gps = new StackTraceGPS({
ajax: url => {
return new Promise((resolve, reject) => {
request(
{
url,
method: "get"
},
(error, response) => {
if (error) {
reject(error);
} else {
resolve(response.body);
}
}
);
});
}
});
gps.pinpoint(stackframe).then(
info => {
console.log(info); /* Actual file Info*/
},
err => {
console.log(err);
}
);
};
Это уменьшает размер пакета и дает возможность регистрировать ошибки на стороне сервера.