مرحبا،
أنا في موقف نريد إرسال أخطاء فيه ، على جانب الخادم والعميل ، إلى أداة Sentry.
يستخدم تطبيقنا Express كخادم مخصص. في الأساس ، ننشئ تطبيقًا سريعًا ، ونطبق بعض البرامج الوسيطة ولكن نفوض كل الوظائف الحقيقية إلى مقبض next.js:
const app = nextJs({ dev: process.env.NODE_ENV !== 'production' });
const handler = routes.getRequestHandler(app);
const expressApp = express();
...
...
expressApp.use(morgan('combined', { stream: logger.stream }));
expressApp.use(statsdMiddleware);
// Add security
expressApp.use(helmet());
// Sentry handler
expressApp.use(sentry.requestHandler());
// Load locale and translation messages
expressApp.use(i18n);
// Next.js handler
expressApp.use(handler);
// Sentry error handler.
// MUST be placed before any other express error handler !!!
expressApp.use(sentry.errorHandler());
باستخدام هذا الأسلوب ، يتحكم next.js في عملية العرض ويتم التقاط أي خطأ بواسطة next.js والطريقة الوحيدة التي يجب معالجتها هي تجاوز ملف الصفحة _error.js
.
ضمن هذا الملف _error.js
، أحتاج إلى طريقة عالمية للإبلاغ عن الأخطاء إلى Sentry. يوجد حاليًا مكتبتان ( raven
للعقدة و raven-js
por javascript). تكمن المشكلة في أنه لا يمكنني استيراد كلاهما لأن raven
يعمل مع SSR ولكنه يفشل عندما يبني webpack الحزمة ، ويفشل أيضًا raven-js
بسبب تبعية XMLHTTPRequest أيضًا.
هل هناك طريقة لإخطاري بخطأ next.js على الخادم؟
لتسجيل الأخطاء من جانب العميل ، قمنا بما يلي:
https://gist.github.com/jgautheron/044b88307d934d486f59ae87c5a5a5a0
يرسل بشكل أساسي أخطاء إلى الخادم ، والتي يتم طباعتها في النهاية على stdout
وتم التقاطها بواسطة برنامج تشغيل التسجيل Docker
الخاص بنا.
لقد اكتشفنا أخطاء SSR بنجاح باستخدام react-guard
دون الحاجة إلى تجاوز ملفات Core Next.
أنا أيضا أواجه هذه المشكلة. أتساءل: هل سيكون مجرد إرجاع الوعد المرفوض من handleRequest
كافياً؟ أي تغيير الرمز هنا ليكون:
handleRequest (req, res, parsedUrl) {
// .....snip....
return this.run(req, res, parsedUrl)
.catch((err) => {
if (!this.quiet) console.error(err)
res.statusCode = 500
res.end(STATUS_CODES[500])
// rethrow error to create new, rejected promise
throw err;
})
}
ثم في كود المستخدم:
const app = nextJs({ dev: process.env.NODE_ENV !== 'production' });
const nextJsHandler = app.getRequestHandler();
const expressApp = express();
app.prepare().then(() => {
// invoke express middlewares
// ...
// time to run next
expressApp.use(function(req, res, next) {
nextJsHandler(req, res).catch(e => {
// use rejected promise to forward error to next express middleware
next(e)
})
});
// Use standard express error middlewares to handle the error from next
// this makes it easy to log to sentry etc.
})
arunodarauchg هل تعتقد ان التغيير I المقترحة أعلاه مباشرة العمل؟ إذا كان الأمر كذلك ، يسعدني تقديم PR
توافق على إعادة طرح الخطأ حتى نتمكن من التلاعب به.
تحتاج أيضًا إلى إعادة طرح renderToHTML
أيضًا ...
أنا أيضًا في موقف نريد إرسال أخطاء فيه ، على جانب الخادم والعميل ، إلى خدمة مشابهة لخدمة Sentry.
أعتقد أن الميزة الأكثر قيمة لهذه الخدمات / الأدوات هي الإبلاغ عن المشكلات غير المتوقعة ، والتي في تجربتي هي أخطاء لم يتم اكتشافها في البرية (أي من جانب العميل). لسوء الحظ ، كما تم التأكيد سابقًا في المشكلة ذات الصلة رقم 2334 ، فإن معالجات جانب العميل في Next.js يحتفظون بهذه الأخطاء لأنفسهم ، مع عدم وجود طريقة ممكنة لتمريرها إلى Sentry من هذه الأداة الأخرى.
إن ما يضايقنا بشكل خاص هو هذا: يتم إعادة تقديم الصفحة المعروضة من جانب الخادم بشكل صحيح كصفحة خطأ إذا حدث استثناء غير معلوم قبل عرض React من جانب العميل . يمكن اعتبار هذا إما ميزة رائعة ، ولكنه أيضًا تجربة محبطة للمطور ، لأنه يدمر بشكل أساسي فوائد تقديم مستند تم تقديمه بالفعل ، على جزء مفاجئ من العملاء.
فيما يلي نموذج لصفحة توضح المشكلة:
import React from 'react';
// Works well in Node 8, but crashes in Chrome<56, Firefox<48, Edge<15, Safari<10, any IE…
const whoops = 'Phew, I made it to the client-side…'.padEnd(80);
export default () => <pre>{whoops}</pre>;
يمكن عرض الكود أعلاه بشكل مثالي من جانب الخادم وتسليمه إلى العميل ، فقط ليصبح فلاش محتوى غير مرغوب فيه قبل أن يتم استبدال الصفحة بأكملها من جانب العميل برسالة مخيفة "حدث خطأ غير متوقع" في معظم المتصفحات ، دون أي طريقة ممكنة للإبلاغ عن الخطأ إلى Sentry (أو أي خدمة / أداة أخرى).
هذا "البلع خطأ" كما يمنع أي ضغط من مستوى onerror معالج، والتي معظم الخطأ من جانب العميل أدوات الإبلاغ هوك على (أو أكثر حداثة، ولكن ليس على نطاق واسع، onunhandledrejection ، والتي قد تكون أكثر ملاءمة بالنظر إلى طبيعة المتزامن من جانب العميل الشفرة).
بقدر ما أستطيع أن أقول ، يتم ابتلاع هذا النوع من أخطاء العميل قبل التفاعل في كتلة try
/ catch
في عميل / index.js Next.js حيث Component
يتم إعادة تعيين ErrorComponent
(حاليًا الأسطر 67-72 ).
أعزائي مؤلفي Next.js والمشرفين عليه ، من أجل التحكم في ما يتم تقديمه ، ما الذي تعتقد أنه سيكون مقبولًا / ممكنًا من بين الأفكار التالية:
catch
في client / index.js للتعامل مع هذا النوع من الأخطاء؟إدخال خطاف في كتلة الصيد هذه في client / index.js للتعامل مع هذا النوع من الخطأ؟
نقل الخطأ إلى معالج رفض خطأ / غير معالج ، إذا تم اكتشاف أي خطأ؟
هذا شيء تحدثنا عنه داخليًا. وسنتحدث قريبًا.
أنا أستخدم Sentry.io للإبلاغ عن الأخطاء والحل الذي نطبقه هو:
1- تكوين raven-node من جانب الخادم
2- قم بتكوين ravenjs من جانب العميل (قمنا بذلك على _document
.
من خلال هاتين الخطوتين ، نكتشف أي استثناءات لم تتم معالجتها على كل من العميل والخادم.
3- أنشئ صفحة _error
. يتم عرض أي خطأ بمجرد معالجة nextjs للطلب (بغض النظر عما إذا كان العميل أو الخادم) يتم عرض هذه الصفحة. في طريقة getInitialProps
لصفحة الخطأ _ قمنا بإبلاغ الحارس بالخطأ.
طريقة تحديد كيفية التحميل إذا تم حل استيراد raven-node أو ravenjs ديناميكيًا اعتمادًا على ما إذا كنا في العميل const Raven = require('raven-js');
أو جانب الخادم const Raven = require('raven');
.
لاحظ أننا قمنا بتكوين حزمة الويب على عدم تجميع الوحدة النمطية raven
(جانب الخادم الأول) مع تحديث next.config.js
بـ:
const webpack = require('webpack');
module.exports = {
// Do not show the X-Powered-By header in the responses
poweredByHeader: false,
webpack: (config) => {
config.plugins.push(new webpack.IgnorePlugin(/^raven$/));
return config;
},
};
تضمين التغريدة
2- قم بتكوين ravenjs من جانب العميل (قمنا بذلك في _document.
هل يمكنك أن تريني كيف قمت بتكوين raven-js على _document.js
؟ إنه لا يعمل بالنسبة لي ، عندما يحدث أي خطأ لا يحدث شيء على الحارس.
هل أحتاج إلى إرسال جميع الأخطاء يدويًا على صفحة _error.js
إلى الحارس؟
// _document constructor
constructor(props) {
super(props);
Raven
.config('...')
.install();
}
لا يزال Next.js ينتج أخطاء إلى console.error
على الخادم طالما أنك لم تضبطه على الوضع الصامت .
باستخدام Sentry ، يمكنك تمكين autoBreadcrumbs
لالتقاط هذا الناتج ، ثم التقاط رسالتك يدويًا. سيكون العنوان أقل وصفيًا ، لكنه سيظل يحتوي على تتبع المكدس الكامل.
مثال على التنفيذ:
const express = require('express');
const nextjs = require('next');
const Raven = require('raven');
const dev = process.env.NODE_ENV !== 'production';
// Must configure Raven before doing anything else with it
if (!dev) {
Raven.config('__DSN__', {
autoBreadcrumbs: true,
captureUnhandledRejections: true,
}).install();
}
const app = nextjs({ dev });
const handle = app.getRequestHandler();
const captureMessage = (req, res) => () => {
if (res.statusCode > 200) {
Raven.captureMessage(`Next.js Server Side Error: ${res.statusCode}`, {
req,
res,
});
}
};
app
.prepare()
.then(() => {
const server = express();
if (!dev) {
server.use((req, res, next) => {
res.on('close', captureMessage(req, res));
res.on('finish', captureMessage(req, res));
next();
});
}
[...]
server.get('/', (req, res) => {
return app.render(req, res, '/home', req.query)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen('3000', (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});
هذا مثال مفتعل للغاية مقتبس من الكود الفعلي. لم أختبره في هذا النموذج. اسمحوا لي أن أعرف إذا انهارت.
بالطبع ، سيكون من الأفضل أن يقوم Next.js بتمرير هذه الأخطاء إلى Express ، حتى نتمكن من استخدام التكامل Sentry / Express خارج الصندوق.
tusgavomelo آسف على الرد المتأخر.
لدينا التحديث. في تطبيقنا ، لدينا ملف مساعد مع طريقة مسؤولة للحصول على مثيل Raven مع مراعاة ما إذا كنا على جانب العميل أو الخادم.
let clientInstance;
let serverInstance;
const getRavenInstance = (key, config) => {
const clientSide = typeof window !== 'undefined';
if (clientSide) {
if (!clientInstance) {
const Raven = require('raven-js'); // eslint-disable-line global-require
Raven.config(key, config).install();
clientInstance = Raven;
}
return clientInstance;
}
if (!serverInstance) {
// NOTE: raven (for node) is not bundled by webpack (see rules in next.config.js).
const RavenNode = require('raven'); // eslint-disable-line global-require
RavenNode.config(key, config).install();
serverInstance = RavenNode;
}
return serverInstance;
};
يعمل هذا الرمز على جانب الخادم (عند وصول الطلب) وجانب العميل. ما فعلناه هو تكوين حزمة الويب (ملف next.config.js
) لتجنب تجميع الحزمة raven
.
acanimal ، هل يمكنك تقديم مثال عملي؟ يبدو أنني لا أحصل على تتبع المكدس الكامل؟ أو ربما يمكنك نشر الخاص بك _error.js
؟
أفعل شيئًا مثل RavenInstance.captureException(err)
في _error.js
، لكن لا يمكنني رؤية نوع الأخطاء التي حدثت وأين؟
export default class Error extends React.Component {
static getInitialProps({ res, err }) {
const RavenInstance = getRavenInstance('__SENTRY__')
if (!(err instanceof Error)) {
err = new Error(err && err.message)
}
RavenInstance.captureException(err)
// const statusCode = res ? res.statusCode : err ? err.statusCode : null;
return { }
}
render() {
return (
<div>
<p>An error occurred on server</p>
</div>
)
}
}
يبدو أن هذا هو المكان المناسب لطلب دعم مسجل مخصص نظرًا لأنه يجب تعيين quiet
على false
لمنع شاشة المسح التالية على إعادة بناء الوحدة وبالتالي إزالة الأخطاء من العرض ، ومع ذلك يتطلب الاختراق العملي الوحيد هنا ضبط quiet
على false.
تفاصيل الأخطاء متاحة أيضًا على تيار stderr.
process.stderr.write = error => yourErrorLog(error);
فلدي الحب _ unortodox_ الحلول
function installErrorHandler(app) {
const _renderErrorToHTML = app.renderErrorToHTML.bind(app)
const errorHandler = rollbar.errorHandler()
app.renderErrorToHTML = (err, req, res, pathname, query) => {
if (err) {
errorHandler(err, req, res, () => {})
}
return _renderErrorToHTML(err, req, res, pathname, query)
}
return app
}
// ¯\_(ツ)_/¯
نسخة مضغوطة من كيفية الحصول على Raven الصحيح للعقدة والمتصفح بدون تهيئة Webpack المخصصة. مستوحى من تعليق acanimal
// package.json
"browser": {
"raven": "raven-js"
}
// getRaven.js
const Raven = require('raven')
if (process.env.NODE_ENV === 'production') {
Raven.config('YOUR_SENTRY_DSN').install()
}
module.exports = Raven
تلخيص سريع لأي شخص يحقق في هذه المشكلة.
// pages/_error.js
import Raven from 'raven';
...
static async getInitialProps({ store, err, isServer }) {
if (isServer && err) {
// https://github.com/zeit/next.js/issues/1852
// eslint-disable-next-line global-require
const Raven = require('raven');
Raven.captureException(err);
}
...
// next.config.js
config.plugins.push(new webpack.IgnorePlugin(/^raven$/));
بفضل تعليق acanimal .
قم بتثبيت كل من raven
(تجاهل مع webpack كما هو مقترح في التعليقات السابقة) و raven-js
، ثم أنشئ مساعدًا لإنشاء مثيل Raven المتماثل ، على سبيل المثال lib/raven.js
import Raven from 'raven-js';
// https://gist.github.com/impressiver/5092952
const clientIgnores = {
ignoreErrors: [
'top.GLOBALS',
'originalCreateNotification',
'canvas.contentDocument',
'MyApp_RemoveAllHighlights',
'http://tt.epicplay.com',
"Can't find variable: ZiteReader",
'jigsaw is not defined',
'ComboSearch is not defined',
'http://loading.retry.widdit.com/',
'atomicFindClose',
'fb_xd_fragment',
'bmi_SafeAddOnload',
'EBCallBackMessageReceived',
'conduitPage',
'Script error.',
],
ignoreUrls: [
// Facebook flakiness
/graph\.facebook\.com/i,
// Facebook blocked
/connect\.facebook\.net\/en_US\/all\.js/i,
// Woopra flakiness
/eatdifferent\.com\.woopra-ns\.com/i,
/static\.woopra\.com\/js\/woopra\.js/i,
// Chrome extensions
/extensions\//i,
/^chrome:\/\//i,
// Other plugins
/127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
/webappstoolbarba\.texthelp\.com\//i,
/metrics\.itunes\.apple\.com\.edgesuite\.net\//i,
],
};
const options = {
autoBreadcrumbs: true,
captureUnhandledRejections: true,
};
let IsomorphicRaven = null;
if (process.browser === true) {
IsomorphicRaven = Raven;
IsomorphicRaven.config(SENTRY_PUBLIC_DSN, {
...clientIgnores,
...options,
}).install();
} else {
// https://arunoda.me/blog/ssr-and-server-only-modules
IsomorphicRaven = eval("require('raven')");
IsomorphicRaven.config(
SENTRY_DSN,
options,
).install();
}
export default IsomorphicRaven;
ثم يمكنك استخدامه في pages/_error.js
الخاص بك وسيعمل على جانب الخادم والعميل.
import NextError from 'next/error';
import IsomorphicRaven from 'lib/raven';
class MyError extends NextError {
static getInitialProps = async (context) => {
if (context.err) {
IsomorphicRaven.captureException(context.err);
}
const errorInitialProps = await NextError.getInitialProps(context);
return errorInitialProps;
};
}
export default MyError;
ها هي العلاقات العامة الخاصة بي من أجل برنامج Rollbar sourcemap wepback الإضافي https://github.com/thredup/rollbar-sourcemap-webpack-plugin/pull/56 مع دعم Next.js :)
tusgavomelo ، هل يمكنك توضيح كيفية الاستفادة من الخطأ الموجود في الدفق؟
"process.stderr.write = خطأ => yourErrorLog (خطأ)؛"
أين يجب أن نكتب هذا السطر من التعليمات البرمجية ، حتى يتم تسجيل الخطأ في وحدة تحكم Node؟
هذا هو جانب العميل فقط.
Rollbar.error('some error')
@ teekey99 هل لديك حل مشابه لـ @sentry/browser
؟ ربما التحديث مع مثال الحارس؟
sheerun لقد كنت أستخدم raven
و raven-js
حتى الآن. أدرك أنه من المحتمل أن يتم إهمال هذه الميزات نظرًا لإضافة جميع الميزات الجديدة الآن إلى @sentry/node
و @sentry/browser
. الشيء هو أنني لم أستخدم هذه المكتبات الجديدة في مشاريعي حتى الآن ، لكنني سأحاول النظر فيها. إذا كان لدي مثال عملي سأعود به.
تم تحديث مثال مع الحارس مؤخرًا.
timneutkens أرى أنه لا يدعم أخطاء من جانب الخادم حيث تتم تهيئة Sentry داخل التطبيق حيث فات الأوان للقبض على أخطاء الخادم. ربما يستخدم الحل المناسب @sentry/node
مكان ما
sheerun أنا أواجه نفس المشكلة. استخدام @sentry/node
ليس بالأمر السهل. يقترح الملف التمهيدي لمثال Sentry هذا استخدام خادم مخصص ، وهو موجود بالفعل في التطبيق الذي أعمل عليه. لالتقاط الاستثناءات في خادم Express.js المخصص الخاص بنا ، تحتاج إلى إدراج خطأ برنامج وسيط لمعالج خطأ Sentry كأول خطأ في معالجة البرامج الوسيطة . إذا أدخلت معالج خطأ Sentry مباشرةً بعد المعالج التالي ، فهذا يعني أن الخطأ قد ابتلعه بالفعل من قبل تلك النقطة ولا يراه Sentry.
لقد كنت أستخدم @sentry/browser
في getInitialProps
من _error.js
ويبدو أنه يعمل من جانب العميل والخادم. لا أعرف ما إذا كان من المفترض أن يكون لدى @sentry/browser
دعم من جانب الخادم ، لكني أحصل على الأحداث إلى Sentry.
على الرغم من أنني أتصل أيضًا بـ Sentry.init()
عبر @sentry/node
في ملف إدخال خادم Express مخصص ، لذلك ربما يكون هذا هو وضع بعض الحالات العالمية التي يستخدمها SSR.
إليك خلاصة الإعداد الذي أستخدمه: https://gist.github.com/mcdougal/7bf001417c3dc4b579da224b12776691
مثير للاهتمام!
هناك بالتأكيد نوع من الحالة العالمية تحدث هنا (وهو أمر مخيف بعض الشيء ، وربما هش وغير مرغوب فيه). تطبيق التغييرات في _error.js
:
ReferenceError: XMLHttpRequest is not defined
في سجلات الخادمError: Sentry syntheticException
غريب مسجل في Sentryسيكون من الجيد أن نفهم ما هو الحل الرسمي. يبدو أن مستندات Next's توصي باستخدام مكون <App>
مخصص الآن ، وهذا ما يفعله مثال "with Sentry" ، لكن هذا يعمل فقط من جانب العميل.
لن يحدث الإبلاغ عن الخطأ بالتأكيد حتى يتم عرض التطبيق لأول مرة. يمكن أن تفشل الطريقة التالية قبل ، على سبيل المثال عند عرض الصفحة. ربما يحدث ذلك عن طريق الصدفة في بعض الحالات بعد عرض التطبيق على جانب الخادم لأول مرة ، ولكن بالتأكيد ليس حلاً كاملاً.
مثال مع الحارس لا يعمل معي إماtimneutkens. يؤدي تشغيل المشروع واختباره باستخدام DSN الفعلي الخاص بي إلى تقديم 400 استجابة ولا يصل أي شيء إلى الحارس (الإصدار 7 من واجهة برمجة التطبيقات).
{"error":"Bad data reconstructing object (JSONDecodeError, Expecting value: line 1 column 1 (char 0))"}
mcdougal لم يعمل معي. لم يكن أمرًا رائعًا أن يكون لديك إعداد عالمي من جانب الخادم بحيث يصل بطريقة ما إلى العميل ، ولكن حتى مع هذا الاختراق ، سأحصل على رد 301 من الحارس.
لا أرى كيف يمكن أن يكون إعداد الحارس المستضاف ذاتيًا خطأ في التكوين ، حيث لا توجد العديد من الخيارات وتشغيله في مشاريع متعددة.
أنا أستخدم @sentry/browser
بنفس الطريقة التي يوصى بها في مثال with-sentry ، ويبدو أنه يرسل أخطاء من كل من الخادم والعميل إلى الحارس الخاص بي. ليس لدي أي تكوين خاص ، فقط نفس الكود مثل المثال.
Jauny هل أنت متأكد من أنه يرسل من الخادم؟ كيف اختبرت ذلك؟ يبدو أن الملف التمهيدي للمثال يشير إلى أنه لن يعمل على الخادم.
timrogers نعم بالفعل
يبدو أن المثال الحالي with-sentry لا يمسك بالأخطاء التي تم إلقاؤها في getInitialProps ، فقط تلك الموجودة في شجرة تقديم التطبيق .. في حالتي معظم الأخطاء من getInitialProps.
sheerun هل يمكنك تجربة حل mcdougal أعلاه؟ إنه ليس مثاليًا (أخطاء حراسة اصطناعية غريبة) ولكن لدي انطباع بأنه يحتوي على كل الأخطاء وأود أن أعرف ما إذا كان هذا غير صحيح. إذا كان هذا صحيحًا ، فمن المحتمل أن يحتاج مثال with-sentry إلى التحديث حتى يتمكن Next.js من تقديم المشورة بشأن كيفية القيام بذلك بشكل أفضل (من الأفضل جعله لا يتم تخطي معالج خطأ الحارس server.js؟).
يبدو أنه يعمل مع مسألتين رئيسيتين:
في الواقع ، بعد إجراء مزيد من الاختبارات ، لا يتم تشغيل getInitialProps من خطأ مخصص لسبب ما في الإنتاج عند حدوث خطأ على سبيل المثال داخل getInitialProps المخصص لتطبيق _app.
نعم ، لقد تلقيت بالتأكيد بعض السلوكيات الغريبة بعد الجري مع محاولتي لبضعة أيام. يبدو أن المشاكل الرئيسية التي نواجهها هي:
@sentry/browser
لـ CSR و @sentry/node
لـ SSRلقد كنت أفكر في محاولة استخدام الواردات البطيئة والحالة العالمية لحل #1
، شيء من هذا القبيل
const sentryInitialized = false;
# Inside some trigger point
const Sentry = ssr ? eval(`require('@sentry/node')`) : eval(`require('@sentry/browser')`);
if (!sentryInitialized) {
Sentry.init({dsn: SENTRY_DSN});
}
Sentry.captureException(err);
ربما يمكن استخدام واردات Next الديناميكية ، لكني لست على دراية بها بعد. لست متأكدًا أيضًا من تداعيات استدعاء require
كل مرة يتم فيها تشغيل رمز معالجة الخطأ. سوف أقوم بالتحديث إذا / عندما أجرب هذا.
بقدر مشكلة #2
، يبدو أن الاحتمالات هي:
_app.componentDidCatch
، والذي لا يتم إطلاقه من أجل SSR_error.getInitialProps
والذي به العديد من المشاكلشعوري الغريزي هو أنه ستكون هناك طريقة للقيام بذلك على الخادم عن طريق حقن معالج خطأ Sentry قبل Next ، لكنني لم أجربه بعد.
في الوقت الحالي ، لا يوفر Next أي خطافات لمساعدتك في القيام بذلك. إذا وجدنا أن هذا يعمل ، فيمكننا إضافتهم 👌
هناك خطر من أن هذا لن ينجح لأن Next يصطاد مبكرًا للغاية ، على الرغم من ذلك.
mcdougal Ah & #!٪ كنت سعيدًا جدًا عندما ربما يكون الحل الخاص بك جيدًا بما يكفي للتحقق من تغطية العميل / الخادم الحارس المطلوبة
عفوا عن جهلي الكامل ولكن هل نحتاج فقط بعد ذلك للسماح لنا بتعطيل معالج الأخطاء الخاص به بشكل مشروط بحيث يصبح معالج أخطاء الحارس nodejs هو الأول؟ بعض العلامات في next.config.js تسمى "disableErrorHandler"؟
Enalmada لا أعتقد أنك تريد تعطيل معالج الخطأ التالي لأنه سيكون هو الذي يعرض صفحة خطأ لطيفة. أنت فقط تريد إدراج برمجيات وسيطة أخرى قبله. أعتقد أن هذا سينجح ، لكني بحاجة إلى تجربته.
حتى مع هذا الإصلاح ، ما زلت لا أشعر أن معالجة الأخطاء من جانب العميل تعمل كما أتمنى :(
هذه المشكلة برمتها مخزية وهي حقًا مانع لتشغيل Next بأمان في الإنتاج.
لمعلوماتك ، أستورد في كل مكان @sentry/node
وأضع ما يلي في next.config.js:
if (!isServer) {
config.resolve.alias['@sentry/node$'] = '@sentry/browser'
}
والتي يمكن أن تكون أفضل من eval
من mcdougal
فيما يلي ملاحظاتي الإضافية حول مكون _app المخصص ومعالجة الأخطاء:
_app.js
لجميع الصفحات ، بما في ذلك _error.js
أو صفحات مثل 404 ، لذا فأنت تريد حقًا التأكد من عدم ظهور أي خطأ عند تمرير ctx.err
إليها .._error.js
(أطلق عليه حتى إذا كان ctx.err
موجودًا)class MyApp extends App {
static async getInitialProps (appContext) {
const { Component, ctx } = appContext
if (ctx.err) {
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { error: true, pageProps }
}
// here code that can throw an error, and then:
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
render() {
if (this.props.error) return super.render()
// rest of code that can throw an error
}
}
حتى الآن أجد أن إعداد الإبلاغ عن الأخطاء بشكل صحيح في next.js إجراء هش للغاية :(
شكرًا sheerun التي تبدو وكأنها محطة جيدة في الاتجاه الصحيح. أوافق على أن معالجة الأخطاء في الخطوة التالية ليست مثالية في الوقت الحالي ، وسيكون من الرائع رؤية بعض الوحدات / البرامج الوسيطة القابلة للتوسيع مضافة حتى نتمكن من إضافة معالجة الأخطاء عليها وما إلى ذلك.
يؤدي الافتقار إلى مكتبات متشابهة مثل الحراسة إلى تعقيد الأمور أيضًا ، لأن هذا يعني أنه لا يمكننا استيراد أي من المكتبات في مكوناتنا ، فنحن بحاجة إلى القيام بذلك ديناميكيًا في وقت التشغيل للتحقق دائمًا مما إذا كان الخطأ قد تم رفعه من جانب الخادم أو المستعرض.
هل هناك تحديث لهذه القضية؟ ما جربته حتى الآن هو ما يلي: لقد نقلت كل شفرة التتبع الخاصة بنا إلى _app.js
constructor(args: any) {
super(args)
Sentry.init({
dsn: 'blah',
environment: 'local',
})
Sentry.configureScope(scope => {
scope.setTag('errorOrigin', isServer ? 'SSR' : 'Client')
})
}
static async getInitialProps({ Component, router, ctx }: any) {
let pageProps = {}
try {
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
} catch (error) {
// console.log('we caught an error')
console.log(error)
Sentry.captureException(error)
throw error
}
return { pageProps }
}
إلى جانب الإضافة next.config.js من sheerun وتهيئة الحارس في server.js أيضًا if (!isServer) {
config.resolve.alias['@sentry/node$'] = '@sentry/browser'
}
يبدو أن هذا يتتبع جميع الأخطاء من جانب العميل ، ولكن على جانب الخادم يبدو أنه يتتبع الخطأ الأول الذي يحدث بعد إعادة تشغيل الخادم. لا يتم تعقب الأخطاء اللاحقة على الخادم بالرغم من ذلك. مع هذا النهج ، ليس لدي أي أخطاء اصطناعية في السجل ، ولكن هناك أخطاء حقيقية فقط.
لا يزال هذا يبدو مخادعًا تمامًا بالنسبة لي وبما أن التتبع من جانب الخادم يعمل فقط في المرة الأولى فإنه لا يزال غير قابل للاستخدام.
لقد أضفت أيضًا هذا الجزء من مثال with-Sentry
componentDidCatch(error: any, errorInfo: any) {
// if (process.env.FIAAS_NAMESPACE !== undefined) {
Sentry.configureScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key])
})
})
Sentry.captureException(error)
console.log('componentDidCatch')
// This is needed to render errors correctly in development / production
super.componentDidCatch(error, errorInfo)
// }
}
لكني لست متأكدًا تمامًا مما إذا كانت هناك حاجة إلى ذلك
في حالتي مع يعمل بدون مشاكل. كما يجب عليك عدم بدء الحارس
_app.js المنشئ ولكن خارج هذه الفئة تمامًا
يوم الأربعاء 21 نوفمبر 2018 الساعة 2:53 مساءً كتب abraxxas [email protected] :
هل هناك تحديث لهذه القضية؟ ما جربته حتى الآن هو ما يلي:
نقل كل شفرة التتبع الخاصة بنا إلى _app.js"
المُنشئ (args: any) {
سوبر (أرغس)
Sentry.init ({
dsn: "بلاه" ،
البيئة: "محلية" ،
})
Sentry.configureScope (النطاق => {
range.setTag ('errorOrigin' ، isServer؟ 'SSR': 'Client')
})
}getInitialProps غير متزامن ثابت ({Component، router، ctx}: أي) {
دع pageProps = {}try { if (Component.getInitialProps) { pageProps = await Component.getInitialProps(ctx) } } catch (error) { // console.log('we caught an error') console.log(error) Sentry.captureException(error) throw error } return { pageProps }
}
"
إلى جانب الإضافة next.config.js منsheerun
https://github.com/sheerun وتهيئة الحارس في server.js أيضًا إذا
(! isServer) {config.resolve.alias ['@ sentry / node $'] = '@ sentry / browser'}
يبدو أن هذا يتتبع جميع الأخطاء من جانب العميل ، ولكن من جانب الخادم
يبدو أنه يتعقب الخطأ الأول الذي يحدث بعد إعادة تشغيل
الخادم. لا يتم تعقب الأخطاء اللاحقة على الخادم بالرغم من ذلك. مع هذا
النهج ليس لدي أي أخطاء SyntheticErrors في السجل ، ولكن أخطاء حقيقية فقط.لا يزال هذا يبدو مخادعًا جدًا بالنسبة لي وبما أن التتبع من جانب الخادم هو
تعمل فقط في المرة الأولى التي لا تزال غير قابلة للاستخدام.-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/zeit/next.js/issues/1852#issuecomment-440668980 ، أو كتم الصوت
الخيط
https://github.com/notifications/unsubscribe-auth/AAR2DeIhoOj6PdWRA2VqiEZyrO5Jui8vks5uxVrHgaJpZM4NOQlp
.
حاولت إخراجها بالفعل وما زلت نفس السلوك. sheerun ، هل يمكنك نشر فكرة بسيطة عن الإعداد الخاص بك؟ لقد حاولت إعداده باستخدام المقتطفات التي قدمتها ولا يمكنني تشغيلها. يبدو الأمر برمته معقدًا للغاية بالنسبة لما كنت أتوقع أن يكون مهمة بسيطة نوعًا ما: (هل تقوم أيضًا بتهيئة الحارس على الخادم أم فقط في _app.js خارج الفصل الدراسي؟
سأقوم بتحديث مثال الحارس الرسمي ولكنني أخشى أن يتم رفضه باعتباره "معقدًا للغاية" يمكنني محاولة نشر شيء ما على الرغم من أنني سأجد الوقت ..
sheerun حتى محاولة التحديث إلى المثال الرسمي ستكون ذات قيمة كبيرة. أشعر أنه سيتم دمجها إذا كان حقًا هو الحد الأدنى من التعقيد الضروري لتشغيل ssr الحارس بدون SyntheticErrors أو تسجيل خطأ الخادم الأول الذي يحدث فقط. ثم يمكننا أن نذهب من هناك لاكتشاف طرق لتحسينها أو الدفع من أجل تحسينات nextjs الأساسية أو دعم متماثل الحراسة.
هنا يذهب .. https://github.com/zeit/next.js/pull/5727
والآن بعد أن أصبح لدينا مثال عملي معقد بالضرورة ، ما هي الخطوات التالية لتحسين الوضع:
الشيء الوحيد الذي يحتاجه المرء في next.js هو القدرة على إضافة برمجية وسيطة مخصصة في next.config.js وشيء مثل next.browser.js لتكوين البرنامج المساعد العالمي (isomorphic) (يتم استخدام next.config.js من بين أشياء أخرى لتهيئة webpack ، مما يعني أن الأشياء الأخرى المحددة في هذا الملف لا يمكن استخدامها في كود التطبيق ، لأنها قد تتسبب في تبعية دائرية).
بالنسبة لـ next.browser.js يمكن لـ next.js تحديد التكوين مثل مصمم التطبيق أو مكونات المستند. بهذه الطريقة يمكنني تنفيذ تكامل الحارس بالكامل كمكوِّن إضافي.
تحرير: لا أعرف ما إذا كان هناك تذكرة لهذا ، ولكن أعتقد أن timneutkens يقوم بالفعل باستخراج الخادم التالي في حزم منفصلة. أعتقد أن أفضل واجهة للمكوِّن الإضافي ستكون مثل:
module.exports = {
server: server => {
server.use(Sentry.Handlers.errorHandler())
}
}
لقد نفذت اقتراح واجهة برمجة التطبيقات هذه في # 6922
يسمح بإضافة أدوات تزيين إلى كود الخادم المخصص لأنه يتم تغيير العقد إلى عقد لا يستدعي تلقائيًا .listen()
لذلك يسمح لـ next.js بتزيينه بشكل أكبر قبل إنشاء مثيل له.
كنت أواجه الكثير من المتاعب عند استخدام المثال with-sentry
، لذلك فتحت العلاقات العامة لمثال أكثر بساطة. ليس بها كل الأجراس والصفارات ، لكنها كانت تعمل معي.
جرب هذا بالعرف _document.js
:
import React from "react";
import Document, {
Html,
Head,
Main,
NextScript,
} from "next/document";
import { NodeClient } from "@sentry/node";
const { default: getConfig } = require("next/config");
const { publicRuntimeConfig: { sentryDSN } } = getConfig();
let sentry = null;
if (sentryDSN) {
sentry = new NodeClient({ dsn: sentryDSN });
}
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
if (ctx.err && sentry) sentry.captureException(ctx.err);
return { ...initialProps };
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
وهذا في مخصص _app.js
:
import * as Sentry from "@sentry/browser";
const { default: getConfig } = require("next/config");
const { publicRuntimeConfig: { sentryDSN } } = getConfig();
if (sentryDSN) {
Sentry.init({ dsn: sentryDSN });
}
يساعدني.
Tbh أنا في حيرة من أمري بشأن الأماكن الصحيحة للقبض على الأخطاء لـ next.js في الوقت الحالي. هناك _app.tsx و _error.tsx و _document.tsx ، وهناك بعض التعليقات التي تشير إلى أنه يجب ضبط بعض الأشياء في _error.tsx (مثل: https://github.com/zeit/next.js/pull/5727/files # r235981700) ولكن الأمثلة الحالية تستخدم إما _app.tsx أو _app و _document.
لقد جربت كلا الاتجاهين الآن ويبدو أن بعض الأخطاء التي تحدث أثناء SSR لم يتم اكتشافها بالنسبة لي. أي الأماكن هي الآن هي الأماكن الصحيحة للتحقق من وجود أخطاء؟ يبدو أن الأمر الأكثر منطقية بالنسبة لي هو التحقق من مكون componentDidCatch لـ _app و getInitialProps للخطأ حيث يتم تقديم هذا الخطأ في حالات الأخطاء. أنا مرتبك قليلاً بشأن الجزء الكامل process.on
في _document
هل يمكن لشخص لديه معرفة أكثر عمقًا أن يحل هذا السؤال؟
abraxxas process.on
في _document.js
يكتشف الأخطاء التي تحدث على الخادم. كخلاصة ،
_document.js
_ جانب الخادم فقط_ ويستخدم لتغيير ترميز المستند المعروض من جانب الخادم الأولي._app.js
_ جانب العميل فقط_ ويستخدم لتهيئة الصفحات.لذلك ، عندما يحدث خطأ على الخادم ، يجب أن يؤدي إلى إرسال خطأ إلى Sentry عبر process.on
ثم يقوم العميل بعرض صفحة الخطأ الافتراضية أو _error.js
.
نأمل أن يساعد هذا: https://leerob.io/blog/configuring-sentry-for-nextjs-apps/
_app.js ليس من جانب العميل فقط ، ولكن componentDidCatch
timneutkens حسنًا ، هذا تم تحديث المستندات منذ آخر مرة بحثت فيها. هل يمكن أن تشرح كيف أن _app.js
ليس من جانب العميل فقط بمزيد من التفصيل؟
timneutkens ، هل يمكنك أن تشرح أين ولماذا
timneutkens حسنًا ، هذا تم تحديث المستندات منذ آخر مرة بحثت فيها. هل يمكن أن تشرح كيف أن
_app.js
ليس من جانب العميل فقط بمزيد من التفصيل؟
مرحبا ليروب!
لقد قمت للتو بنشر سؤال حول طلب الدمج الخاص بمثالك:
https://github.com/zeit/next.js/pull/7360#issuecomment -514318899
إضافة إلى هذا السؤال ... حاولت أيضًا إلقاء خطأ في العرض () على جانب الخادم (لقد بدأت الحالة مع liftErrorInRender: صحيح ، لذا فإن التصيير الأول ، أي جانب الخادم ، سيؤدي إلى خطأ بالفعل) ، و لم يتم التقاط هذا الخطأ أيضًا بواسطة Sentry.
هل اختبرت ذلك في تطبيقك ، وهل يتم تسجيل الأخطاء من جانب الخادم حقًا؟ أنا أستخدم التالي 9.
إذا كان الأمر كذلك بالفعل ، ولم يتم تسجيل سوى أخطاء جانب العميل ، فلن يكون هناك أيضًا سبب لتجاوز ملف _document.js.
شكرا مقدما على أي مساعدة!
timneutkens حسنًا ، هذا تم تحديث المستندات منذ آخر مرة بحثت فيها. هل يمكن أن تشرح كيف أن
_app.js
ليس من جانب العميل فقط بمزيد من التفصيل؟
للإجابة على سؤالك ، _app هو المكان الذي يتم فيه تعريف مكون التطبيق لتهيئة الصفحات. سنقوم بتجاوزه في حالات مثل الحاجة إلى تخطيط مستمر بين تغييرات الصفحة (تستخدم جميع الصفحات نفس التطبيق _app) ، أو للاستفادة من الإعادة. لذلك ، حتى التصيير الأول ، الذي يحدث على جانب الخادم ، سيعرض محتوى _app (ليس جانب العميل فقط).
إضافة إلى هذا السؤال ... حاولت أيضًا إلقاء خطأ في العرض () على جانب الخادم (لقد بدأت الحالة مع liftErrorInRender: صحيح ، لذا فإن التصيير الأول ، أي جانب الخادم ، سيؤدي إلى خطأ بالفعل) ، و لم يتم التقاط هذا الخطأ أيضًا بواسطة Sentry.
هل تمكنت بأي طريقة أخرى من إظهار هذا الخطأ في الحراسة؟ حاولت التقاطه في getInitialProps من الخطأ _ ولكن هذا أيضًا لا يظهر شيئًا في الحراسة. لم أجد حاليًا طريقة موثوقة واحدة لالتقاط الأخطاء على الخادم ، بعضها (غالبًا إذا كانت متصلة بفشل واجهة برمجة التطبيقات) تظهر ولكني لم أتمكن من الحصول على خطأ بسيط من صفحة الخطأ لتظهر في الحراسة
إضافة إلى هذا السؤال ... حاولت أيضًا إلقاء خطأ في العرض () على جانب الخادم (لقد بدأت الحالة مع liftErrorInRender: صحيح ، لذا فإن التصيير الأول ، أي جانب الخادم ، سيؤدي إلى خطأ بالفعل) ، و لم يتم التقاط هذا الخطأ أيضًا بواسطة Sentry.
هل تمكنت بأي طريقة أخرى من إظهار هذا الخطأ في الحراسة؟ حاولت التقاطه في getInitialProps من الخطأ _ ولكن هذا أيضًا لا يظهر شيئًا في الحراسة. لم أجد حاليًا طريقة موثوقة واحدة لالتقاط الأخطاء على الخادم ، بعضها (غالبًا إذا كانت متصلة بفشل واجهة برمجة التطبيقات) تظهر ولكني لم أتمكن من الحصول على خطأ بسيط من صفحة الخطأ لتظهر في الحراسة
للأسف لا. الحل الذي أعتقد أنني سأقوم بتنفيذه هو استخدام المثال (مطروحًا منه ملف _document.js المتجاوز) كقالب لالتقاط الأخطاء التي تحدث من جانب العميل ، نظرًا لأن تلك هي الأخطاء التي لا أملك التحكم فيها والطريقة التي يمكنني بها تعرف عنه ، ما لم يبلغ المستخدمون بذلك. على جانب الخادم ، أعتقد أنني سأعيد توجيه أي سطر سجل مباشرة إلى ملف السجل. هذا بالتأكيد ليس أفضل حل لأنني كنت أرغب في الحصول على جميع الأخطاء في نفس المكان ، ولكن عند القيام بذلك بهذه الطريقة ، سيكون لدي على الأقل معلومات حول أي خطأ قد يحدث في التطبيق.
ما رأيك في ذلك؟ شكرا!
إضافة إلى هذا السؤال ... حاولت أيضًا إلقاء خطأ في العرض () على جانب الخادم (لقد بدأت الحالة مع liftErrorInRender: صحيح ، لذا فإن التصيير الأول ، أي جانب الخادم ، سيؤدي إلى خطأ بالفعل) ، و لم يتم التقاط هذا الخطأ أيضًا بواسطة Sentry.
هل تمكنت بأي طريقة أخرى من إظهار هذا الخطأ في الحراسة؟ حاولت التقاطه في getInitialProps من الخطأ _ ولكن هذا أيضًا لا يظهر شيئًا في الحراسة. لم أجد حاليًا طريقة موثوقة واحدة لالتقاط الأخطاء على الخادم ، بعضها (غالبًا إذا كانت متصلة بفشل واجهة برمجة التطبيقات) تظهر ولكني لم أتمكن من الحصول على خطأ بسيط من صفحة الخطأ لتظهر في الحراسة
للأسف لا. الحل الذي أعتقد أنني سأقوم بتنفيذه هو استخدام المثال (مطروحًا منه ملف _document.js المتجاوز) كقالب لالتقاط الأخطاء التي تحدث من جانب العميل ، نظرًا لأن تلك هي الأخطاء التي لا أملك التحكم فيها والطريقة التي يمكنني بها تعرف عنه ، ما لم يبلغ المستخدمون بذلك. على جانب الخادم ، أعتقد أنني سأعيد توجيه أي سطر سجل مباشرة إلى ملف السجل. هذا بالتأكيد ليس أفضل حل لأنني كنت أرغب في الحصول على جميع الأخطاء في نفس المكان ، ولكن عند القيام بذلك بهذه الطريقة ، سيكون لدي على الأقل معلومات حول أي خطأ قد يحدث في التطبيق.
ما رأيك في ذلك؟ شكرا!
هذا هو بالضبط ما نقوم به الآن ، إنه أمر صعب بعض الشيء ولكن أفضل ما يمكن أن نتوصل إليه. ولكن نظرًا لأن بعض الأخطاء من جانب الخادم تظهر في الحارس بالنسبة لنا ، يجب أن يكون هناك شيء ما يحدث إما مع الحارس أو next.js على ما أعتقد. لقد حاولت باستخدام المثال البسيط والأكثر تعقيدًا وكلاهما يتصرفان بنفس الطريقة ، لذا فأنا على الأقل واثق إلى حد ما من أن هذا السلوك لا يتعلق بإعدادنا
قد يكون الأشخاص في هذا الموضوع مهتمين بـ https://github.com/zeit/next.js/pull/8684 والأخطاء ذات الصلة. يحتوي على 12 اختبارًا مختلفًا للاستثناءات التي لم تتم معالجتها والتي يمكنك اللعب بها لفهم الاستثناءات التي يعالجها Next.js نيابةً عنك وما لا يعالجها.
أي أخبار بخصوص هذا الموضوع؟
الحل الخاص بي هو استخدام redux
حفظ خطأ البيانات في جلب العقدة في state
ثم في componentDidMount
من _app.js
افعل شيئًا (تنبيه للمستخدم أو خطأ في النشر مطلوب إلى الخلفية).
الكود موجود في الخطأ التالي - antd-scaffold_server .
========> دولة
import {
SERVER_ERROR,
CLEAR_SERVER_ERROR
} from '../../constants/ActionTypes';
const initialState = {
errorType: []
};
const serverError = (state = initialState, { type, payload }) => {
switch (type) {
case SERVER_ERROR: {
const { errorType } = state;
errorType.includes(payload) ? null : errorType.push(payload);
return {
...state,
errorType
};
}
case CLEAR_SERVER_ERROR: {
return initialState;
}
default:
return state;
}
};
export default serverError;
=======> عمل
import {
SERVER_ERROR
} from '../../constants/ActionTypes';
export default () => next => action => {
if (!process.browser && action.type.includes('FAIL')) {
next({
type: SERVER_ERROR,
payload: action.type
});
}
return next(action);
};
=======> _app.js
...
componentDidMount() {
const { store: { getState, dispatch } } = this.props;
const { errorType } = getState().serverError;
if (errorType.length > 0) {
Promise.all(
errorType.map(type => message.error(`Node Error, Code:${type}`))
);
dispatch(clearServerError());
}
}
...
بفضل https://github.com/zeit/next.js/issues/1852#issuecomment -353671222 حصلت على مثال للعمل مع الإبلاغ عن أخطاء Rollbar من جانب الخادم .
فلدي الحب _ unortodox_ الحلول
function installErrorHandler(app) { const _renderErrorToHTML = app.renderErrorToHTML.bind(app) const errorHandler = rollbar.errorHandler() app.renderErrorToHTML = (err, req, res, pathname, query) => { if (err) { errorHandler(err, req, res, () => {}) } return _renderErrorToHTML(err, req, res, pathname, query) } return app } // ¯\_(ツ)_/¯
لا يمكن تطبيق هذه الطريقة على خطأ 404 لأن وسيطة الخطأ ستكون فارغة عند الخطأ 404.
لقد قمت بحل هذا لعميل عقدة Elastic APM (https://www.npmjs.com/package/elastic-apm-node)
لأي شخص مهتم:
في next.config.js
:
webpack: (config, { isServer, webpack }) => {
if (!isServer) {
config.node = {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
};
// ignore apm (might use in nextjs code but dont want it in client bundles)
config.plugins.push(
new webpack.IgnorePlugin(/^(elastic-apm-node)$/),
);
}
return config;
}
ثم في _error.js
render func ، يمكنك استدعاء خطأ التقاط يدويًا:
function Error({ statusCode, message, err }) {
const serverSide = typeof window === 'undefined';
// only run this on server side as APM only works on server
if (serverSide) {
// my apm instance (imports elastic-apm-node and returns captureError)
const { captureError } = require('../src/apm');
if (err) {
captureError(err);
} else {
captureError(`Message: ${message}, Status Code: ${statusCode}`);
}
}
}
مرحبا جميعا! لقد أطلقنا للتو مكتبة NPM لهندسة النمط السريع في Next.js دون إضافة خادم Express. قد يكون من المفيد التعامل مع أخطاء الخادم الخاص بك التحديات! تحقق من ذلك إذا كنت مهتمًا. https://github.com/oslabs-beta/connext-js
نجح أي شخص في اصطياد (ومعالجة) الاستثناءات التي تحدث في getServerSideProps
؟
نجح أي شخص في اصطياد (ومعالجة) الاستثناءات التي تحدث في
getServerSideProps
؟
من غير الواضح ، كنت تعتقد أن إطار العمل سيوفر طريقة اصطلاحية لتسجيل الأخطاء لكل من العميل والخادم 🤷♂️
نجح أي شخص في اصطياد (ومعالجة) الاستثناءات التي تحدث في
getServerSideProps
؟
تضمين التغريدة
نعم ، لقد نجح شيء كهذا بالنسبة لي:
أنشئ أولاً برمجية وسيطة للتعامل مع تقارير الأعطال. لقد قمت بلف Sentry
داخل فئة CrashReporter
لأن إرجاع Sentry
لن يعمل (على سبيل المثال ، req.getCrashReporter = () => Sentry
).
// crash-reporter.js
const Sentry = require("@sentry/node");
class CrashReporter {
constructor(){
Sentry.init({ dsn: process.env.SENTRY_DSN });
}
captureException(ex){
return Sentry.captureException(ex);
}
}
function crashReporterMiddleware(req, res, next) {
req.getCrashReporter = () => new CrashReporter();
next();
}
module.exports = crashReporterMiddleware;
بعد ذلك ، بالطبع ، قم بتحميل البرامج الوسيطة في تطبيقك قبل تعيين معالج الطلب Next.js:
// server.js
const crashReporterMiddleware = require("./middleware/crash-reporter")
...
app.use(crashReporterMiddleware);
...
setHandler((req, res) => {
return handle(req, res);
});
ثم أينما كنت تتصل بـ getServerSideProps
:
// _error.js
export async function getServerSideProps({req, res, err}) {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
const crashReporter = req.getCrashReporter();
const eventId = crashReporter.captureException(err);
req.session.eventId = eventId;
return {
props: { statusCode, eventId }
}
}
التعليق الأكثر فائدة
فلدي الحب _ unortodox_ الحلول