Next.js: рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд▓реЙрдЧ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдХреИрд╕реЗ рдкрдХрдбрд╝реЗрдВ рдФрд░ рдХреИрд╕реЗ рд╕рдВрднрд╛рд▓реЗрдВ?

рдХреЛ рдирд┐рд░реНрдорд┐рдд 2 рдордИ 2017  ┬╖  74рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: vercel/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 рдлрд╝рд╛рдЗрд▓ рдХреЗ рднреАрддрд░ рдореБрдЭреЗ рд╕рдВрддрд░реА рдХреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рддрд░реАрдХрд╛ рдЪрд╛рд╣рд┐рдПред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рджреЛ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИрдВ ( raven рдиреЛрдб рдХреЗ рд▓рд┐рдП рдФрд░ raven-js рдкреЛрд░ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ)ред рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ рдЙрди рджреЛрдиреЛрдВ рдХреЛ рдЖрдпрд╛рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рдХреНрдпреЛрдВрдХрд┐ raven SSR рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдм рд╡реЗрдмрдкреИрдХ рдмрдВрдбрд▓ рдмрдирд╛рддрд╛ рд╣реИ рддреЛ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕рд╛рде рд╣реА raven-js XMLHTTPRequest рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдХрд╛рд░рдг рднреА рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рдХреНрдпрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рдореБрдЭреЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рдЕрдЧрд▓реА.рдЬреЗрдПрд╕ рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рд╕реВрдЪрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?

story feature request

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

_рдЕрдиреЛрд░реНрдЯреЛрдбреЙрдХреНрд╕_рд╕рдорд╛рдзрд╛рдиреЛрдВ рд╕реЗ рдкреНрдпрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП

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
}
// ┬п\_(уГД)_/┬п

рд╕рднреА 74 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдореЗрдВ рд▓реЙрдЧрд┐рдВрдЧ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп рдХрд░ рд░рд╣реЗ рд╣реИрдВ:
https://gist.github.com/jgautheron/044b88307d934d486f59ae87c5a5a5a0

рдпрд╣ рдореВрд▓ рд░реВрдк рд╕реЗ рд╕рд░реНрд╡рд░ рдХреЛ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рднреЗрдЬрддрд╛ рд╣реИ, рдЬреЛ рдЕрдВрдд рдореЗрдВ stdout рдореБрджреНрд░рд┐рдд рд╣реЛрддреА рд╣реИрдВ рдФрд░ рд╣рдорд╛рд░реЗ Docker рд▓реЙрдЧрд┐рдВрдЧ рдбреНрд░рд╛рдЗрд╡рд░ рджреНрд╡рд╛рд░рд╛ рдкрдХрдбрд╝реА рдЬрд╛рддреА рд╣реИрдВред
рд╣рдордиреЗ react-guard рд╕рд╛рде SSR рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкрдХрдбрд╝рд╛ рд╣реИ рдФрд░ рдХреЛрд░ рдиреЗрдХреНрд╕реНрдЯ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред

рдореБрдЭреЗ рднреА рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИред рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдп рд╣реИ: рдХреНрдпрд╛ рдЕрдЧрд▓реЗ рдХреЗ 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.
})

@arunoda @rauchg рдХреНрдпрд╛ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЬреЛ рдмрджрд▓рд╛рд╡ рддреБрд░рдВрдд рдКрдкрд░ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдХрд┐рдпрд╛ рд╣реИ рд╡рд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛? рдЕрдЧрд░ рдРрд╕рд╛ рд╣реИ, рддреЛ рдкреАрдЖрд░ рд╕рдмрдорд┐рдЯ рдХрд░рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛрдЧреА

рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдлреЗрдВрдХрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣рдордд рд╣реИрдВ рддрд╛рдХрд┐ рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рдЦреЗрд▓ рд╕рдХреЗрдВред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ renderToHTML рднреА рдлрд┐рд░ рд╕реЗ рдлреЗрдВрдХрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ ...

рдореИрдВ рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рднреА рд╣реВрдВ рдЬрд╣рд╛рдВ рд╣рдо рд╕рд░реНрд╡рд░ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рджреЛрдиреЛрдВ рддрд░рдл рд╕реЗ рд╕рдВрддрд░реА рдЬреИрд╕реА рд╕реЗрд╡рд╛ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рднреЗрдЬрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ рдРрд╕реА рд╕реЗрд╡рд╛рдУрдВ/рдЙрдкрдХрд░рдгреЛрдВ рдХреА рд╕рдмрд╕реЗ рдореВрд▓реНрдпрд╡рд╛рди рд╡рд┐рд╢реЗрд╖рддрд╛ рдЙрди рдореБрджреНрджреЛрдВ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдирд╛ рд╣реИ рдЬреЛ рд╕рдмрд╕реЗ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╣реИрдВ, рдЬреЛ рдореЗрд░реЗ рдЕрдиреБрднрд╡ рдореЗрдВ рдЬрдВрдЧрд▓реА (рдпрд╛рдиреА рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб) рдореЗрдВ рдЕрдирдЬрд╛рди рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рд╕рдВрдмрдВрдзрд┐рдд рдЕрдВрдХ #2334 рдореЗрдВ рдЬреЛрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, Next.js рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рд╣реИрдВрдбрд▓рд░ рдЗрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЕрдкрдиреЗ рдкрд╛рд╕ рд░рдЦрддреЗ рд╣реИрдВ, рдРрд╕реЗ рдЕрдиреНрдп рдЯреВрд▓ рдХреЗ рд╕рдВрддрд░реА рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рд╕рдВрднрд╛рд╡рд┐рдд рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред

рдЬрд┐рд╕ рдЪреАрдЬ рдиреЗ рд╣рдореЗрдВ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдХрдард┐рди рдХрд╛рдЯ рджрд┐рдпрд╛ рд╣реИ рд╡рд╣ рдпрд╣ рд╣реИ: рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдкрд░ рд░рд┐рдПрдХреНрдЯ рд░реЗрдВрдбрд░рд┐рдВрдЧ рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рди рдЖрдпрд╛ рд╣реБрдЖ рдЕрдкрд╡рд╛рдж рд╣реЛрдиреЗ рдкрд░ рдПрдХ рдареАрдХ рд╕реЗ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд░реЗрдВрдбрд░ рдХрд┐рдП рдЧрдП рдкреЗрдЬ рдХреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдкреЗрдЬ рдХреЗ рд░реВрдк рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдЗрд╕реЗ рдпрд╛ рддреЛ рдПрдХ рдорд╣рд╛рди рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдирд┐рд░рд╛рд╢рд╛рдЬрдирдХ рдбреЗрд╡рд▓рдкрд░ рдЕрдиреБрднрд╡ рднреА, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣рд┐рд╕реНрд╕реЗ рдкрд░ рдкрд╣рд▓реЗ рд╕реЗ рдкреНрд░рд╕реНрддреБрдд рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреА рд╕реЗрд╡рд╛ рдХреЗ рд▓рд╛рднреЛрдВ рдХреЛ рдмрд░реНрдмрд╛рдж рдХрд░ рджреЗрддрд╛ рд╣реИред

рдпрд╣рд╛рдБ рдПрдХ рдирдореВрдирд╛ рдкреГрд╖реНрда рд╣реИ рдЬреЛ рд╕рдорд╕реНрдпрд╛ рдХреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реИ:

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>;

рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб-рд░реЗрдВрдбрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдЕрд╡рд╛рдВрдЫрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдлреНрд▓реИрд╢ рдмрдирдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдкреВрд░реЗ рдкреГрд╖реНрда рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдкрд░ рдЦрддрд░рдирд╛рдХ "рдПрдХ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рддреНрд░реБрдЯрд┐ рд╣реБрдИ рд╣реИ" рд╕рдВрджреЗрд╢ рдЕрдзрд┐рдХрд╛рдВрд╢ рдмреНрд░рд╛рдЙрдЬрд╝рд░реЛрдВ рдкрд░ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рдП , рд╕рдВрддрд░реА (рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рд╕реЗрд╡рд╛/рдЙрдкрдХрд░рдг)

рдпрд╣ "рддреНрд░реБрдЯрд┐ рдирд┐рдЧрд▓рдиреЗ" рдорд╛рдирдХ рдСрдирд░рд░ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдХрд┐рд╕реА рднреА рдЙрддреНрддреЛрд▓рди рдХреЛ рд░реЛрдХрддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдЕрдзрд┐рдХрд╛рдВрд╢ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐ рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рдЯреВрд▓ рд╣реБрдХ (рдпрд╛ рдЕрдзрд┐рдХ рдЖрдзреБрдирд┐рдХ, рд▓реЗрдХрд┐рди рд╡реНрдпрд╛рдкрдХ рдирд╣реАрдВ, рдЧреИрд░-рдЕрд╕реНрд╡реАрдХреГрддрд┐ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ , рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдХреА

рд╕рдВрднрд╛рд╡рд┐рдд рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рд╕рдорд╛рдзрд╛рди

рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдореИрдВ рдмрддрд╛ рд╕рдХрддрд╛ рд╣реВрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░реА-рд░рд┐рдПрдХреНрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐ Next.js рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ/index.js рдореЗрдВ try / catch рдмреНрд▓реЙрдХ рдореЗрдВ рдирд┐рдЧрд▓ рд▓реА рдЬрд╛рддреА рд╣реИ рдЬрд╣рд╛рдВ Component рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ ErrorComponent (рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд▓рд╛рдЗрди 67-72 ) рдХреЗ рдореВрд▓реНрдп рдкрд░ рдлрд┐рд░ рд╕реЗ рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдкреНрд░рд┐рдп Next.js рд▓реЗрдЦрдХ рдФрд░ рдЕрдиреБрд░рдХреНрд╖рдХ, рдЬреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЙрд╕рдХреЗ рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдЪрд╛рд░реЛрдВ рдореЗрдВ рд╕реЗ рдХреНрдпрд╛ рд╕реНрд╡реАрдХрд╛рд░реНрдп/рд╕рдВрднрд╡ рд╣реЛрдЧрд╛:

  • рдЗрд╕ рддрд░рд╣ рдХреА рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд▓рд╛рдЗрдВрдЯ/index.js рдореЗрдВ рдЙрд╕ catch рдмреНрд▓реЙрдХ рдореЗрдВ рдПрдХ рд╣реБрдХ рдкреЗрд╢ рдХрд░реЗрдВ?
  • рддреНрд░реБрдЯрд┐ рдХреЛ рдПрдХ рдЖрддрдВрдХ/рдСрдирд╣реИрдВрдбрд▓ рд░рд┐рдЬреЗрдХреНрд╢рди рд╣реИрдВрдбрд▓рд░ рдХреЛ рдкреНрд░реЗрд╖рд┐рдд рдХрд░реЗрдВ, рдпрджрд┐ рдХреЛрдИ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ?
  • рддреНрд░реБрдЯрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдирд┐рдХрд╛рд▓рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рджрд╛рди рдХрд░реЗрдВ?
  • рддреНрд░реБрдЯрд┐ рдШрдЯрдХ рдкреНрд░рджрд░реНрд╢рд┐рдд рди рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рджрд╛рди рдХрд░реЗрдВ?
  • рдПрдХ рдХрд╕реНрдЯрдо рддреНрд░реБрдЯрд┐ рдШрдЯрдХ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рджрд╛рди рдХрд░реЗрдВ?

рдЗрд╕ рддрд░рд╣ рдХреА рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд▓рд╛рдЗрдВрдЯ/рдЗрдВрдбреЗрдХреНрд╕.рдЬреЗрдПрд╕ рдореЗрдВ рдЙрд╕ рдХреИрдЪ рдмреНрд▓реЙрдХ рдореЗрдВ рдПрдХ рд╣реБрдХ рдкреЗрд╢ рдХрд░реЗрдВ?
рддреНрд░реБрдЯрд┐ рдХреЛ рдПрдХ рдЖрддрдВрдХ/рдСрдирд╣реИрдВрдбрд▓ рд░рд┐рдЬреЗрдХреНрд╢рди рд╣реИрдВрдбрд▓рд░ рдХреЛ рдкреНрд░реЗрд╖рд┐рдд рдХрд░реЗрдВ, рдпрджрд┐ рдХреЛрдИ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ?

рдпрд╣ рдРрд╕реА рдЪреАрдЬ рд╣реИ рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣рдордиреЗ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдмрд╛рдд рдХреА рд╣реИред рдФрд░ рд╣рдо рдЬрд▓реНрдж рд╣реА рд╕рдВрдмреЛрдзрд┐рдд рдХрд░реЗрдВрдЧреЗред

рдореИрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Sentry.io рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЬреЛ рд╕рдорд╛рдзрд╛рди рд╣рдо рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рд╡рд╣ рд╣реИ:

1- рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд░реЗрд╡реЗрди-рдиреЛрдб рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ
2- рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рд░реИрд╡реЗрдВрдЬ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ (рд╣рдордиреЗ рдЗрд╕реЗ _document рдкрд░ рдмрдирд╛рдпрд╛ рд╣реИред

рдЗрди рджреЛ рдЪрд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рджреЛрдиреЛрдВ рдкрд░ рдХрд┐рд╕реА рднреА рдЕрдирдЪрд╛рд╣реЗ рдЕрдкрд╡рд╛рдж рдХреЛ рдкрдХрдбрд╝рддреЗ рд╣реИрдВред

3- рдПрдХ _error рдкреЗрдЬ рдмрдирд╛рдПрдВред рдиреЗрдХреНрд╕реНрдЯрдЬ рдПрдХ рдмрд╛рд░ рдЙрддреНрдкрдиреНрди рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдХреЛрдИ рднреА рддреНрд░реБрдЯрд┐ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрднрд╛рд▓рддреА рд╣реИ (рдЪрд╛рд╣реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдпрд╛ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдХреЛрдИ рднреА рд╣реЛ) рдЙрд╕ рдкреГрд╖реНрда рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред _error рдкреГрд╖реНрда рдХреА getInitialProps рдкрджреНрдзрддрд┐ рдореЗрдВ рд╣рдо рд╕рдВрддрд░реА рдХреЛ рддреНрд░реБрдЯрд┐ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддреЗ рд╣реИрдВред

рдЕрдЧрд░ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ const Raven = require('raven-js'); рдпрд╛ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб const Raven = require('raven'); рдореЗрдВ рд╣реИрдВ рддреЛ рдпрд╣ рддрдп рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рд░реЗрд╡реЗрди-рдиреЛрдб рдпрд╛ рд░реЗрд╡реЗрдирдЬ рдХреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЖрдпрд╛рдд рдХрд░рдХреЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред
рдиреЛрдЯ рд╣рдо webpack рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рд╣реИ рдмрдВрдбрд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 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;
  },
};

@ acanimal

2- рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рд░реИрд╡реЗрдВрдЬ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ (рд╣рдордиреЗ рдЗрд╕реЗ _document.

рдХреНрдпрд╛ рдЖрдк рдореБрдЭреЗ рджрд┐рдЦрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдкрдиреЗ рдЕрдкрдиреЗ _document.js рдкрд░ рд░реЗрд╡реЗрди-рдЬреЗрдПрд╕ рдХреЛ рдХреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛? рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЬрдм рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ рддреЛ рд╕рдВрддрд░реА рдкрд░ рдХреБрдЫ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред

рдХреНрдпрд╛ рдореБрдЭреЗ рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ _error.js рдкреГрд╖реНрда рдкрд░ рд╕рдВрддрд░реА рдХреЛ рднреЗрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?

// _document constructor
constructor(props) {
    super(props);
    Raven
      .config('...')
      .install();
}

Next.js рдЕрднреА рднреА рд╕рд░реНрд╡рд░ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ console.error рдкрд░ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдЖрдк рдЗрд╕реЗ рд╢рд╛рдВрдд рдкрд░ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

рд╕рдВрддрд░реА рдХреЗ рд╕рд╛рде, рдЖрдк рдЗрд╕ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ 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 рдЙрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдХреЗ рдЖрд╕рдкрд╛рд╕ рднреЗрдЬ рд╕рдХреЗ, рддрд╛рдХрд┐ рд╣рдо рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рд╕рдВрддрд░реА/рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдПрдХреАрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХреЗрдВред

@tusgavomelo рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рджреЗрд░ рд╕реЗ рдЙрддреНрддрд░ рдХреЗ рд▓рд┐рдПред

рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдкрдбреЗрдЯ рд╣реИред рд╣рдорд╛рд░реЗ рдРрдк рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд░реЗрд╡реЗрди рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╝рд┐рдореНрдореЗрджрд╛рд░ рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рд╛рдЗрд▓ рд╣реИ рдпрджрд┐ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдпрд╛ рд╕рд░реНрд╡рд░ рдХреА рддрд░рдл рд╣реИрдВред

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;
};

рдпрд╣ рдХреЛрдб рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб (рдЬрдм рдХреЛрдИ рдЕрдиреБрд░реЛрдз рдЖрддрд╛ рд╣реИ) рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рджреЛрдиреЛрдВ рдЪрд▓рд╛рддрд╛ рд╣реИред рд╣рдордиреЗ рдЬреЛ рдХрд┐рдпрд╛ рд╣реИ рд╡рд╣ raven рдкреИрдХреЗрдЬ рдХреЛ рдмрдВрдбрд▓ рдХрд░рдиреЗ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рд╡реЗрдмрдкреИрдХ ( next.config.js рдлрд╝рд╛рдЗрд▓) рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реИред

@acanimal рдХреНрдпрд╛ рдЖрдк рд╢рд╛рдпрдж рдПрдХ рдХрд╛рдордХрд╛рдЬреА рдЙрджрд╛рд╣рд░рдг рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореБрдЭреЗ рдкреВрд░рд╛ рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рдирд╣реАрдВ рдорд┐рд▓ рд░рд╣рд╛ рд╣реИ? рдпрд╛ рд╢рд╛рдпрдж рдЖрдк рдЕрдкрдирд╛ _error.js рдкреЛрд╕реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

рдореИрдВ рдЕрдкрдиреЗ _error.js RavenInstance.captureException(err) рдЬреИрд╕рд╛ рдХреБрдЫ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЛ рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рдХрд┐ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реБрдИрдВ рдФрд░ рд╕рд╛рде рд╣реА рдХрд╣рд╛рдВ?

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 рдХреЛ рдЧрд▓рдд рдкрд░ рд╕реЗрдЯ рдХрд░рдирд╛ред

рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рд╡рд┐рд╡рд░рдг stderr рд╕реНрдЯреНрд░реАрдо рдкрд░ рднреА рдЙрдкрд▓рдмреНрдз рд╣реИред
process.stderr.write = error => yourErrorLog(error);

_рдЕрдиреЛрд░реНрдЯреЛрдбреЙрдХреНрд╕_рд╕рдорд╛рдзрд╛рдиреЛрдВ рд╕реЗ рдкреНрдпрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП

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
}
// ┬п\_(уГД)_/┬п

рдХрд╕реНрдЯрдо рд╡реЗрдмрдкреИрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди w/o рдиреЛрдб рдФрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд░реЗрд╡реЗрди рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ рдХрд╛ рдХреЙрдореНрдкреИрдХреНрдЯ рд╕рдВрд╕реНрдХрд░рдгред @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 (рдкрд┐рдЫрд▓реА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рд╕реБрдЭрд╛рдП рдЧрдП рд╡реЗрдмрдкреИрдХ рдХреЗ рд╕рд╛рде рдЕрдирджреЗрдЦрд╛ рдХрд░реЗрдВ) рдФрд░ raven-js рджреЛрдиреЛрдВ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ, рдлрд┐рд░ рдЖрдЗрд╕реЛрдореЛрд░реНрдлрд┐рдХ рд░реЗрд╡реЗрди рдХреЛ рддрддреНрдХрд╛рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╣рд╛рдпрдХ рдмрдирд╛рдПрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП 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;

рдпрд╣рд╛рдВ рд░реЛрд▓рдмрд╛рд░ рд╕реЛрд░реНрд╕рдореИрдк рд╡реЗрдкрдмреИрдХ рдкреНрд▓рдЧрдЗрди рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рдкреАрдЖрд░ рд╣реИ https://github.com/thredup/rollbar-sourcemap-webpack-plugin/pull/56 Next.js рд╕рдкреЛрд░реНрдЯ рдХреЗ рд╕рд╛рде :)

@tusgavomelo , рдХреНрдпрд╛ рдЖрдк рд╕реНрдЯреНрд░реАрдо рдкрд░ рдореМрдЬреВрдж рддреНрд░реБрдЯрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВ?
"process.stderr.write = error => yourErrorLog (рддреНрд░реБрдЯрд┐);"

рдиреЛрдб рдХрдВрд╕реЛрд▓ рдореЗрдВ рддреНрд░реБрдЯрд┐ рд▓реЙрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдХреЛрдб рдХреА рдпрд╣ рдкрдВрдХреНрддрд┐ рдХрд╣рд╛рдВ рд▓рд┐рдЦрдиреА рдЪрд╛рд╣рд┐рдП?

рд╡рд╣ рдХреЗрд╡рд▓ рдЧреНрд░рд╛рд╣рдХ рдкрдХреНрд╖ рд╣реИред
Rollbar.error('some error')

https://docs.rollbar.com/docs/javascript

@ рдЯреАрдХреА 99 рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ @sentry/browser рд▓рд┐рдП рд╕рдорд╛рди рд╕рдорд╛рдзрд╛рди рд╣реИ? рд╢рд╛рдпрдж рд╕рдВрддрд░реА рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдЕрджреНрдпрддрди рдХрд░реЗрдВ?

@sheerun рдореИрдВ рдЕрдм рддрдХ raven рдФрд░ raven-js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рд╢рд╛рдпрдж рдкрджрд╛рд╡рдирдд рд╣реЛ рдЬрд╛рдПрдВрдЧреЗ рдХреНрдпреЛрдВрдХрд┐ рд╕рднреА рдирдИ рд╕реБрд╡рд┐рдзрд╛рдПрдВ рдЕрдм @sentry/node рдФрд░ @sentry/browser рдЬреЛрдбрд╝ рджреА рдЧрдИ рд╣реИрдВред рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдЗрди рдирдП рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред рдЕрдЧрд░ рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдХрд╛рдордХрд╛рдЬреА рдЙрджрд╛рд╣рд░рдг рд╣реИ рддреЛ рдореИрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдКрдВрдЧрд╛ред

рд╡рд┐рде-рд╕реЗрдВрдЯреНрд░реА рдЙрджрд╛рд╣рд░рдг рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

@timneutkens рдореИрдВ рджреЗрдЦрддрд╛ рд╣реВрдВ рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрддрд░реА рдХреЛ рдРрдк рдХреЗ рдЕрдВрджрд░ рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬрд╣рд╛рдВ рд╕рд░реНрд╡рд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдореЗрдВ рдмрд╣реБрдд рджреЗрд░ рд╣реЛ рдЪреБрдХреА рд╣реИред рдЙрдЪрд┐рдд рд╕рдорд╛рдзрд╛рди рд╢рд╛рдпрдж рдХрд╣реАрдВ @sentry/node рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛

@sheerun рдореИрдВ рдЙрд╕реА рдореБрджреНрджреЗ рдХреЛ рдорд╛рд░ рд░рд╣рд╛ рд╣реВрдВред @sentry/node рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рддреБрдЪреНрдЫ рдирд╣реАрдВ рд╣реИред рдЗрд╕ рд╕рдВрддрд░реА рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд░реАрдбрдореА рдПрдХ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рд╣реИ рдЬрд┐рд╕ рдкрд░ рдореИрдВ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рд╣рдорд╛рд░реЗ рдХрд╕реНрдЯрдо Express.js рд╕рд░реНрд╡рд░ рдореЗрдВ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рд╡рд╛рд▓реА рдкрд╣рд▓реА рддреНрд░реБрдЯрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕рдВрддрд░реА рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдорд┐рдбрд▓рд╡реЗрдпрд░ рддреНрд░реБрдЯрд┐ рдбрд╛рд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдиреЗрдХреНрд╕реНрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдареАрдХ рдмрд╛рдж рд╕рдВрддрд░реА рдХреЗ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЙрд╕ рдмрд┐рдВрджреБ рд╕реЗ рддреНрд░реБрдЯрд┐ рдкрд╣рд▓реЗ рд╣реА рдирд┐рдЧрд▓ рд▓реА рдЧрдИ рд╣реИ рдФрд░ рд╕рдВрддрд░реА рдЗрд╕реЗ рдирд╣реАрдВ рджреЗрдЦрддрд╛ рд╣реИред

рдореИрдВ @sentry/browser рдХрд╛ рдЙрдкрдпреЛрдЧ getInitialProps рдХреЗ _error.js рдореЗрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рджреЛрдиреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ @sentry/browser рдореЗрдВ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд╕рдкреЛрд░реНрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдпрд╛ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд╕реЗрдВрдЯреНрд░реА рдореЗрдВ рдЗрд╡реЗрдВрдЯ рдорд┐рд▓ рд░рд╣реЗ рд╣реИрдВред

рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореИрдВ рдХрд╕реНрдЯрдо рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рдХреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ Sentry.init() рдорд╛рдзреНрдпрдо рд╕реЗ @sentry/node Sentry.init() рдорд╛рдзреНрдпрдо рд╕реЗ рднреА рдХреЙрд▓ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рд╢рд╛рдпрдж рдпрд╣ рдХреБрдЫ рд╡реИрд╢реНрд╡рд┐рдХ рд╕реНрдерд┐рддрд┐ рд╕реЗрдЯ рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬреЛ рдПрд╕рдПрд╕рдЖрд░ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИред

рдпрд╣рд╛рдБ рдЙрд╕ рд╕реЗрдЯрдЕрдк рдХрд╛ рд╕рд╛рд░ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдореИрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ: https://gist.github.com/mcdougal/7bf001417c3dc4b579da224b12776691

рджрд┐рд▓рдЪрд╕реНрдк!

рдпрд╣рд╛рдБ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреА рд╡реИрд╢реНрд╡рд┐рдХ рд╕реНрдерд┐рддрд┐ рдЪрд▓ рд░рд╣реА рд╣реИ (рдЬреЛ рдереЛрдбрд╝рд╛ рдбрд░рд╛рд╡рдирд╛ рд╣реИ, рдФрд░ рд╢рд╛рдпрдж рднрдВрдЧреБрд░ рдФрд░ рдЕрд╡рд╛рдВрдЫрдиреАрдп рд╣реИ)ред _error.js рдореЗрдВ рдЕрдкрдиреЗ рдкрд░рд┐рд╡рд░реНрддрди рд▓рд╛рдЧреВ рдХрд░рдирд╛:

  • __рдмрд┐рдирд╛ __ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдореЗрдВ рд╕рдВрддрд░реА рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛:

    • рдЬрдм рд╡рд┐рдХрд╛рд╕ рдореЛрдб рдпрд╛ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдЪрд▓ рд░рд╣рд╛ рд╣реЛ (рдпрд╛рдиреА рдореЗрд░реЗ рдРрдк рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд╕рд╛рде), рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рд╕рдВрддрд░реА рдХреЛ рдХреБрдЫ рднреА рд╕реВрдЪрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд╕рд░реНрд╡рд░ рд▓реЙрдЧ рдореЗрдВ рдХреБрдЫ ReferenceError: XMLHttpRequest is not defined рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ

  • __рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж__ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдореЗрдВ рд╕рдВрддрд░реА:

    • рдореЗрд░реЗ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рдЕрдкрд╡рд╛рджреЛрдВ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдорд┐рд▓рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд╕реЗрдВрдЯреНрд░реА рдореЗрдВ рдПрдХ рдЕрдЬреАрдм Error: Sentry syntheticException рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ

рдпрд╣ рд╕рдордЭрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕рдорд╛рдзрд╛рди рдХреНрдпрд╛ рд╣реИред рдиреЗрдХреНрд╕реНрдЯ рдХреЗ рдбреЙрдХреНрд╕ рдЕрдм рдПрдХ рдХрд╕реНрдЯрдо <App> рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддреЗ рд╣реИрдВ, рдФрд░ рдпрд╣реА "рд╕реЗрдВрдЯреНрд░реА рдХреЗ рд╕рд╛рде" рдЙрджрд╛рд╣рд░рдг рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХреЗрд╡рд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдкрд╣рд▓реА рдмрд╛рд░ рдРрдк рд░реЗрдВрдбрд░ рд╣реЛрдиреЗ рддрдХ рддреНрд░реБрдЯрд┐ рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдирд╣реАрдВ рд╣реЛрдЧреАред рдЕрдЧрд▓рд╛ рд░рд╛рд╕реНрддрд╛ рдкрд╣рд▓реЗ рд╡рд┐рдлрд▓ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдкреЗрдЬ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╕рдордпред рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╕рдВрдпреЛрдЧ рд╕реЗ рдпрд╣ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реЛ рдЬрдм рдРрдк рдкрд╣рд▓реА рдмрд╛рд░ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛ, рд▓реЗрдХрд┐рди рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдпрд╣ рдкреВрд░реНрдг рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИред

рд╕рдВрддрд░реА рдЙрджрд╛рд╣рд░рдг рдореЗрд░реЗ рд▓рд┐рдП @timneutkens рдХреЗ рд▓рд┐рдП рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЪрд▓рд╛рдирд╛ рдФрд░ рдореЗрд░реЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреАрдПрд╕рдПрди рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ 400 рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрддрд╛ рд╣реИ рдФрд░ рд╕рдВрддрд░реА (рдПрдкреАрдЖрдИ рдХреЗ рд╕рдВрд╕реНрдХрд░рдг 7) рдХреЛ рдХреБрдЫ рднреА рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рд╣реИред

{"error":"Bad data reconstructing object (JSONDecodeError, Expecting value: line 1 column 1 (char 0))"}

@mcdougal рдореЗрд░реЗ рдХрд╛рдо рдирд╣реАрдВ рдЖрдпрд╛ред рд╡реИрд╢реНрд╡рд┐рдХ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд╕реЗрдЯрдЕрдк рд╣реЛрдирд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рдерд╛ рдЬреЛ рдХрд┐рд╕реА рднреА рддрд░рд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рддрдХ рдмреБрд▓рдмреБрд▓реЗ рд╣реЛ, рд▓реЗрдХрд┐рди рдЙрд╕ рд╣реИрдХ рдХреЗ рд╕рд╛рде рднреА рдореБрдЭреЗ 301 рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдПрдВ рдорд┐рд▓реЗрдВрдЧреАред

рдореИрдВ рдирд╣реАрдВ рджреЗрдЦрддрд╛ рдХрд┐ рдореЗрд░реЗ рд╕рдВрддрд░реА рд╕реНрд╡рдпрдВ-рд╣реЛрд╕реНрдЯ рдХрд┐рдП рдЧрдП рд╕реЗрдЯрдЕрдк рдореЗрдВ рдЧрд▓рдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреИрд╕реЗ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХрдИ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИрдВ рдФрд░ рдпрд╣ рдХрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдЪрд▓ рд░рд╣рд╛ рд╣реИред

рдореИрдВ @sentry/browser рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрд╕реА рддрд░рд╣ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬреИрд╕реЗ рдХрд┐ рд╕рдВрддрд░реА рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЗрд╕рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдХреА рдЬрд╛рддреА рд╣реИ, рдФрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рд░реНрд╡рд░ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рджреЛрдиреЛрдВ рд╕реЗ рдореЗрд░реА рд╕рдВрддрд░реА рдХреЛ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рднреЗрдЬ рд░рд╣рд╛ рд╣реИред рдореЗрд░реЗ рдкрд╛рд╕ рдХреЛрдИ рд╡рд┐рд╢реЗрд╖ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдирд╣реАрдВ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рдорд╛рди рдХреЛрдб рд╣реИред

@ рдЬреМрдиреА рдХреНрдпрд╛ рдЖрдк рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рд╣реИрдВ рдХрд┐ рдпрд╣ рд╕рд░реНрд╡рд░ рд╕реЗ рднреЗрдЬ рд░рд╣рд╛ рд╣реИ? рдЖрдкрдиреЗ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд┐рдпрд╛? рдЙрджрд╛рд╣рд░рдг рдХрд╛ рд░реАрдбрдореА рдпрд╣ рднреА рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рд░реНрд╡рд░ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред

@timrogers рд╣рд╛рдБ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореЗрд░рд╛ рдмреБрд░рд╛ рд╣реИ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рд░реНрд╡рд░ рд╕реЗ рдПрдХ рдкрд░реАрдХреНрд╖рдг рддреНрд░реБрдЯрд┐ рдЖ рд░рд╣реА рдереА рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдЯреНрд░рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ :(

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдВрддрд░реА рдХреЗ рд╕рд╛рде рд╡рд░реНрддрдорд╛рди рдЙрджрд╛рд╣рд░рдг getInitialProps рдореЗрдВ рдлреЗрдВрдХрдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдирд╣реАрдВ рдкрдХрдбрд╝рддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдкреЗрдбрд╝ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВ .. рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрдзрд┐рдХрд╛рдВрд╢ рддреНрд░реБрдЯрд┐рдпрд╛рдВ getInitialProps рд╕реЗ рд╣реИрдВред

@sheerun рдХреНрдпрд╛ рдЖрдк рдКрдкрд░ рджрд┐рдП рдЧрдП рдореИрдХрдбреЙрдЧрд▓ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЛ рдЖрдЬрдорд╛ рд╕рдХрддреЗ рд╣реИрдВ? рдпрд╣ рд╕рд╣реА рдирд╣реАрдВ рд╣реИ (рдЕрдЬреАрдм рд╕рд┐рдВрдереЗрдЯрд┐рдХ рд╕рдВрддрд░реА рддреНрд░реБрдЯрд┐рдпрд╛рдВ) рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рдореЗрдВ рд╕рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВ рдФрд░ рдореИрдВ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рд╕рдЪ рдирд╣реАрдВ рд╣реИред рдЕрдЧрд░ рдпрд╣ рд╕рдЪ рд╣реИ, рддреЛ рд╕рдВрднрд╡рддрдГ рд╕рдВрддрд░реА рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЗрд╕рдХреЗ рд╕рд╛рде рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ Next.js рдЗрд╕реЗ рдмреЗрд╣рддрд░ рддрд░реАрдХреЗ рд╕реЗ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рд▓рд╛рд╣ рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛ (рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рдЗрд╕реЗ рд╕рд░реНрд╡рд░.рдЬреЗрдПрд╕ рд╕рдВрддрд░реА рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдирд╣реАрдВ рдЬрд╛рддрд╛ рд╣реИ?)

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдереЛрдбрд╝реЗ рджреЛ рдкреНрд░рдореБрдЦ рдореБрджреНрджреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

  1. рд╢рд╛рдпрдж рдЗрд╕рд▓рд┐рдП рдХрд┐ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рдХреЛрдб рдХреЛ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рд░реАрдЬреЗрдирд░реЗрдЯрд░ рдХреЛрдб рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрддреНрдкрд╛рджрди рдореЗрдВ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд╕реНрдЯреИрдХрдЯреНрд░реЗрд╕ рдХреЛ рдЕрдХреНрд╕рд░ рдЖрдВрддрд░рд┐рдХ/рдкреНрд░рдХреНрд░рд┐рдпрд╛/next_tick.js рдкрд░ рдЫреЛрдЯрд╛ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рддреНрд░реБрдЯрд┐ рдХрд╛ рдХреЛрдИ рдХрд╛рд░рдг рдмрд┐рд▓реНрдХреБрд▓ рднреА рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред
  2. рдЕрдЧрд▓реЗ рдЕрдиреБрд░реЛрдз рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдлреЗрдВрдХрдиреЗ рдкрд░ рддреНрд░реБрдЯрд┐ рдкреНрд░рдмрдВрдзрди рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХреЛрдб рдореЗрдВ)

рдЕрд╕рд▓ рдореЗрдВ рдЖрдЧреЗ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдмрд╛рдж рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдХрд╕реНрдЯрдо рддреНрд░реБрдЯрд┐ рдХреЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХрдкреНрд░реЙрдкреНрд╕ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдлрд╛рдпрд░рд┐рдВрдЧ рднреА рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬрдм рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдХрд╕реНрдЯрдо _app рдХреЗ getInitialProps рдХреЗ рдЕрдВрджрд░ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ ..

рд╣рд╛рдБ, рдХреБрдЫ рджрд┐рдиреЛрдВ рдХреЗ рдЕрдкрдиреЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рд╕рд╛рде рджреМрдбрд╝рдиреЗ рдХреЗ рдмрд╛рдж рдореБрдЭреЗ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдХреБрдЫ рдЕрдЬреАрдм рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реЛ рд░рд╣рд╛ рд╣реИред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЬрд┐рди рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рд╡реЗ рд╣реИрдВ:

  1. рд╕реАрдПрд╕рдЖрд░ рдХреЗ рд▓рд┐рдП @sentry/browser рдФрд░ рдПрд╕рдПрд╕рдЖрд░ рдХреЗ рд▓рд┐рдП @sentry/node рдЖрдпрд╛рдд рдХрд░рдирд╛
  2. рд╕реАрдПрд╕рдЖрд░ рдФрд░ рдПрд╕рдПрд╕рдЖрд░ рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдореЗрд╢рд╛ рдЯреНрд░рд┐рдЧрд░ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрдЧрд╣ рдЦреЛрдЬрдирд╛

рдореИрдВ #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);

рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдиреЗрдХреНрд╕реНрдЯ рдХреЗ рдбрд╛рдпрдирд╛рдорд┐рдХ рдЗрдВрдкреЛрд░реНрдЯ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рд▓реЗрдХрд┐рди рдореИрдВ рдЕрднреА рддрдХ рдЙрдирд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реВрдВред рдореБрдЭреЗ рдпрд╣ рднреА рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рд░ рдмрд╛рд░ рддреНрд░реБрдЯрд┐ рдкреНрд░рдмрдВрдзрди рдХреЛрдб рдЯреНрд░рд┐рдЧрд░ рд╣реЛрдиреЗ рдкрд░ require рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдЕрд╕рд░ рдкрдбрд╝рддрд╛ рд╣реИред рдЕрдЧрд░ рдореИрдВ рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рддрд╛ рд╣реВрдВ рддреЛ рдореИрдВ рдЕрдкрдбреЗрдЯ рдХрд░реВрдВрдЧрд╛ред

рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрд╕рдорд╕реНрдпрд╛ #2 , рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдВрднрд╛рд╡рдирд╛рдПрдВ рд╣реИрдВ:

  1. _app.componentDidCatch , рдЬреЛ SSR рдХреЗ рд▓рд┐рдП рд╕рдХреНрд░рд┐рдп рдирд╣реАрдВ рд╣реИ
  2. _error.getInitialProps , рдЬрд┐рд╕рдореЗрдВ рдмрд╣реБрдд рд╕реА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ
  3. ...рдХреБрдЫ рдФрд░? рдХреНрдпрд╛ рд╣рдо рдиреЗрдХреНрд╕реНрдЯ рд╕рд░реНрд╡рд░ рд╣реИрдВрдбрд▓рд░ рдлрдВрдХреНрд╢рди рдореЗрдВ SSR рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

рдореЗрд░реА рдЖрдВрдд рдХреА рднрд╛рд╡рдирд╛ рдпрд╣ рд╣реИ рдХрд┐ рдиреЗрдХреНрд╕реНрдЯ рд╕реЗ рдкрд╣рд▓реЗ рд╕реЗрдВрдЯреНрд░реА рдХреЗ рдПрд░рд░ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдХреЗ рд╕рд░реНрд╡рд░ рдкрд░ рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЗрд╕реЗ рдЕрднреА рддрдХ рдирд╣реАрдВ рджрд┐рдпрд╛ рд╣реИред

рдлрд┐рд▓рд╣рд╛рд▓, рдРрд╕рд╛ рдХрд░рдиреЗ рдореЗрдВ рдЖрдкрдХреА рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП рдЕрдЧрд▓рд╛ рдХреЛрдИ рд╣реБрдХ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЕрдЧрд░ рд╣рдордиреЗ рдкрд╛рдпрд╛ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ

рдПрдХ рдЬреЛрдЦрд┐рдо рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдЕрдЧрд▓рд╛ рдмрд╣реБрдд рдЬрд▓реНрджреА рдкрдХрдбрд╝рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ред

@mcdougal рдЖрд╣ &#!% рдореИрдВ рдмрд╣реБрдд рдЦреБрд╢ рдерд╛ рдЬрдм рдЖрдкрдХрд╛ рдХрд╛рдордХрд╛рдЬ рд╣рдореЗрдВ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рдВрддрд░реА рдХреНрд▓рд╛рдЗрдВрдЯ/рд╕рд░реНрд╡рд░ рдХрд╡рд░реЗрдЬ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛ рд╕рдХрддрд╛ рдерд╛ред

рдореЗрд░реА рдкреВрд░реА рдЕрдЬреНрдЮрд╛рдирддрд╛ рдХреЛ рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣рдореЗрдВ рдЗрд╕рдХреЗ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд╕рд╢рд░реНрдд рд░реВрдк рд╕реЗ рдЕрдХреНрд╖рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╕ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдиреЛрдбрдЬ рд╕рдВрддрд░реА рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдкрд╣рд▓рд╛ рдмрди рдЬрд╛рдП? next.config.js рдореЗрдВ рдХреБрдЫ рдзреНрд╡рдЬ "disableErrorHandler" рдХрд╣рд▓рд╛рддреЗ рд╣реИрдВ?

@Enalmada рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдЖрдк рдЕрдЧрд▓рд╛ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдЕрдХреНрд╖рдо рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд╣ рд╣реЛрдЧрд╛ рдЬреЛ рдПрдХ рдЕрдЪреНрдЫрд╛ рддреНрд░реБрдЯрд┐ рдкреГрд╖реНрда рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИред рдЖрдк рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдЕрдиреНрдп рдорд┐рдбрд▓рд╡реЗрдпрд░ рдбрд╛рд▓рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЗрд╕реЗ рдЖрдЬрдорд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред

рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рдЙрд╕ рдирд┐рд╢реНрдЪрд┐рдд рдХреЗ рд╕рд╛рде, рдореБрдЭреЗ рдЕрднреА рднреА рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐ рдкреНрд░рдмрдВрдзрди рдХрд╛рд░реНрдпреЛрдВ рдХреА рддрд░рд╣ рдорд╣рд╕реВрд╕ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рд╕рд╛рде рд╣реА рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ :(

рдпрд╣ рдкреВрд░рд╛ рдореБрджреНрджрд╛ рд╢рд░реНрдо рдХреА рдмрд╛рдд рд╣реИ рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдЕрдЧрд▓рд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд╡рд░реЛрдзрдХ рд╣реИред

FYI рдХрд░реЗрдВ рдореИрдВ рд╣рд░ рдЬрдЧрд╣ @sentry/node рдЖрдпрд╛рдд рдХрд░рддрд╛ рд╣реВрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛ next.config.js рдореЗрдВ рдбрд╛рд▓рддрд╛ рд╣реВрдВ:

        if (!isServer) {
          config.resolve.alias['@sentry/node$'] = '@sentry/browser'
        }

рдЬреЛ @mcdougal . рдХреЗ eval рд╕реЗ рдмреЗрд╣рддрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ

рдХрд╕реНрдЯрдо _app рдШрдЯрдХ рдФрд░ рддреНрд░реБрдЯрд┐ рдкреНрд░рдмрдВрдзрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореЗрд░реЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдиреЛрдЯреНрд╕ рдпрд╣рд╛рдВ рджрд┐рдП рдЧрдП рд╣реИрдВ:

  1. _app.js рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рднреА рдкреГрд╖реНрдареЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ _error.js рдпрд╛ 404 рдЬреИрд╕реЗ рдкреГрд╖реНрда рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЬрдм ctx.err рдЗрд╕реЗ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред
  2. рдРрдк рдХреЗ getInitialProps рдореЗрдВ Component.getInitialProps рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ _error.js getInitialProps рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХреЗрдЧрд╛ ( 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
  }
}

рдЕрдм рддрдХ рдореБрдЭреЗ рдЕрдЧрд▓реА.рдЬреЗрдПрд╕ рдореЗрдВ рдПрдХ рдмрд╣реБрдд рд╣реА рдирд╛рдЬреБрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рддреНрд░реБрдЯрд┐ рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рдареАрдХ рд╕реЗ рд╕реЗрдЯ рдЕрдк рдорд┐рд▓ рд░рд╣реА рд╣реИ :(

рдзрдиреНрдпрд╡рд╛рдж @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 }
    }

рд╕рд╛рде рдореЗрдВ @sheerun рд╕реЗ рдЕрдЧрд▓рд╛ . рд╕рд░реНрд╡рд░ рдореЗрдВ рд╕рдВрддрд░реА рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдирд╛ рднреА if (!isServer) { config.resolve.alias['@sentry/node$'] = '@sentry/browser' }
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд░реНрд╡рд░ рдХреА рддрд░рдл рдпрд╣ рдХреЗрд╡рд▓ рдкрд╣рд▓реА рддреНрд░реБрдЯрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╕рд░реНрд╡рд░ рдХреЗ рдкреБрдирд░рд╛рд░рдВрдн рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рд╣реЛрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдмрд╛рдж рдореЗрдВ рд╕рд░реНрд╡рд░ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рдореЗрд░реЗ рдкрд╛рд╕ рд▓реЙрдЧ рдореЗрдВ рдХреЛрдИ рд╕рд┐рдВрдереЗрдЯрд┐рдХ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВред

рдлрд┐рд░ рднреА рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдлреА рд╣реИрдХреА рд▓рдЧрддрд╛ рд╣реИ рдФрд░ рдЪреВрдВрдХрд┐ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЗрд╡рд▓ рдкрд╣рд▓реА рдмрд╛рд░ рдХрд╛рдо рдХрд░ рд░рд╣реА рд╣реИ, рдпрд╣ рдЕрднреА рднреА рдЕрдиреБрдкрдпреЛрдЧреА рд╣реИред

рдореИрдВрдиреЗ рдЗрд╕ рднрд╛рдЧ рдХреЛ рд╕рдВрддрд░реА рдЙрджрд╛рд╣рд░рдг рд╕реЗ рднреА рдЬреЛрдбрд╝рд╛ рд╣реИ

    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 рдкрд░ abraxxas 2:53 pm рдкрд░ [email protected] рд▓рд┐рдЦрд╛ рд╣реИ:

рдХреНрдпрд╛ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдХреЛрдИ рдЕрдкрдбреЗрдЯ рд╣реИ? рдореИрдВрдиреЗ рдЕрдм рддрдХ рдЬреЛ рдХреЛрд╢рд┐рд╢ рдХреА рд╡рд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИ: I
рд╣рдорд╛рд░реЗ рд╕рднреА рдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЛрдб рдХреЛ _app.js . рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛

`
рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ (рддрд░реНрдХ: рдХреЛрдИ рднреА) {
рд╕реБрдкрд░ (рддрд░реНрдХ)
рд╕рдВрддрд░реА.рдЗрдирд┐рдЯ({
рдбреАрдПрд╕рдПрди: 'рдмреНрд▓рд╛рд╣',
рдкрд░реНрдпрд╛рд╡рд░рдг: 'рд╕реНрдерд╛рдиреАрдп',
})
рд╕рдВрддрд░реА.рдХреЙрдиреНрдлрд╝рд┐рдЧрд░рд╕реНрдХреЛрдк (рджрд╛рдпрд░рд╛ => {
рд╕реНрдХреЛрдк.рд╕реЗрдЯрдЯреИрдЧ ('рдПрд░рд░рдСрд░рд┐рдЬрд┐рди', рдЖрдИрд╕рд░реНрд╡рд░? 'рдПрд╕рдПрд╕рдЖрд░': 'рдХреНрд▓рд╛рдЗрдВрдЯ')
})
}

рд╕реНрдереИрддрд┐рдХ async getInitialProps ({рдШрдЯрдХ, рд░рд╛рдЙрдЯрд░, ctx}: рдХреЛрдИ рднреА) {
рдЪрд▓реЛ рдкреЗрдЬрдкреНрд░реЙрдкреНрд╕ = {}

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 }

}

`

@sheerun . рд╕реЗ next.config.js рдЬреЛрдбрд╝ рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░
https://github.com/sheerun рдФрд░ рд╕рд░реНрд╡рд░ рдореЗрдВ рд╕рдВрддрд░реА рдкреНрд░рд╛рд░рдВрдн рдХрд░рдирд╛ред рдЬреЗрдПрд╕ рднреА рдЕрдЧрд░
(!isServer) { config.resolve.alias['@sentry/node$'] = '@sentry/browser' }
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд░реНрд╡рд░ рдХреА рддрд░рдл
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рдкрд╣рд▓реА рддреНрд░реБрдЯрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдкреБрдирд░рд╛рд░рдВрдн рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рд╣реЛрддрд╛ рд╣реИ
рд╕рд░реНрд╡рд░ред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдмрд╛рдж рдореЗрдВ рд╕рд░реНрд╡рд░ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд╕рд╛рде рд╣реА
рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрд░реЗ рдкрд╛рд╕ рд▓реЙрдЧ рдореЗрдВ рдХреЛрдИ рд╕рд┐рдВрдереЗрдЯрд┐рдХ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВред

рдлрд┐рд░ рднреА рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдлреА рд╣реИрдХреА рд▓рдЧрддрд╛ рд╣реИ рдФрд░ рдЪреВрдВрдХрд┐ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдЯреНрд░реИрдХрд┐рдВрдЧ рд╣реИ
рдХреЗрд╡рд▓ рдкрд╣рд▓реА рдмрд╛рд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ рдпрд╣ рдЕрднреА рднреА рдЕрдиреБрдкрдпреЛрдЧреА рд╣реИред

-
рдЖрдк рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ, рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
https://github.com/zeit/next.js/issues/1852#issuecomment-440668980 , рдпрд╛ рдореНрдпреВрдЯ рдХрд░реЗрдВ
рд╕реВрддреНрд░
https://github.com/notifications/unsubscribe-auth/AAR2DeIhoOj6PdWRA2VqiEZyrO5Jui8vks5uxVrHgaJpZM4NOQlp
.

рдореИрдВрдиреЗ рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╛рд╣рд░ рд▓реЗ рдЬрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдФрд░ рдЕрднреА рднреА рд╡рд╣реА рд╡реНрдпрд╡рд╣рд╛рд░ред @sheerun рдХреНрдпрд╛ рдЖрдк рд╢рд╛рдпрдж рдЕрдкрдиреЗ рд╕реЗрдЯрдЕрдк рдХрд╛ рдиреНрдпреВрдирддрдо рд╕рд╛рд░ рдкреЛрд╕реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдореИрдВрдиреЗ рдЗрд╕реЗ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рд╕реНрдирд┐рдкреЗрдЯ рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рдФрд░ рдореИрдВ рдЗрд╕реЗ рдХрд╛рдо рдкрд░ рдирд╣реАрдВ рд▓рд╛ рд╕рдХрддрд╛ред рдЬреЛ рдХреБрдЫ рдореИрдВ рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рдерд╛ рдЙрд╕рдХреЗ рд▓рд┐рдП рдкреВрд░реА рдмрд╛рдд рдЕрддреНрдпрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд▓рдЧрддреА рд╣реИ :( рдХреНрдпрд╛ рдЖрдк рд╕рд░реНрд╡рд░ рдкрд░ рд╕рдВрддрд░реА рд╢реБрд░реВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдпрд╛ рдХреЗрд╡рд▓ рдХрдХреНрд╖рд╛ рдХреЗ рдмрд╛рд╣рд░ _app.js рдореЗрдВ рд╣реИрдВ?

рдореИрдВ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕рдВрддрд░реА рдЙрджрд╛рд╣рд░рдг рдЕрдкрдбреЗрдЯ рдХрд░реВрдВрдЧрд╛ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдбрд░ рд╣реИ рдХрд┐ рдЗрд╕реЗ "рдмрд╣реБрдд рдЬрдЯрд┐рд▓" рдХреЗ рд░реВрдк рдореЗрдВ рдЦрд╛рд░рд┐рдЬ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЬрдм рдореБрдЭреЗ рд╕рдордп рдорд┐рд▓реЗрдЧрд╛ рддреЛ рдореИрдВ рдХреБрдЫ рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ ..

@sheerun рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рднреА рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реЛрдЧрд╛ред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╡рд┐рд▓рдп рд╣реЛ рдЬрд╛рдПрдЧрд╛ рдпрджрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдиреНрдпреВрдирддрдо рдЬрдЯрд┐рд▓рддрд╛ рд╣реИ рдЬреЛ рд╕рдВрддрд░реА ssr рдХреЛ SyntheticErrors рдХреЗ рдмрд┐рдирд╛ рдХрд╛рдо рдХрд░рдиреЗ рдпрд╛ рдХреЗрд╡рд▓ рдкрд╣рд▓реА рд╕рд░реНрд╡рд░ рддреНрд░реБрдЯрд┐ рдХреЛ рд░рд┐рдХреЙрд░реНрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдлрд┐рд░ рд╣рдо рдЗрд╕реЗ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рддрд░реАрдХреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд╣рд╛рдВ рд╕реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдиреЗрдХреНрд╕реНрдЯрдЬ рдХреЛрд░ рд╕реБрдзрд╛рд░ рдпрд╛ рд╕рдВрддрд░реА рдЖрдЗрд╕реЛрдореЛрд░реНрдлрд┐рдХ рд╕рдорд░реНрдерди рдкрд░ рдЬреЛрд░ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣рд╛рдБ рдпрд╣ рдЬрд╛рддрд╛ рд╣реИ .. https://github.com/zeit/next.js/pull/5727

рддреЛ рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рдЬрдЯрд┐рд▓ рдХрд╛рдордХрд╛рдЬреА рдЙрджрд╛рд╣рд░рдг рд╣реИ, рддреЛ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕реБрдзрд╛рд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЧрд▓реЗ рдХрджрдо рдХреНрдпрд╛ рд╣реИрдВ:

  • рдЦреБрд▓реЗ рд╕рдВрддрд░реА рдореБрджреНрджреЛрдВ рдкрд░ рддреМрд▓рдирд╛ (рдХреЛрдИ рдЧреБрдо рд╣реИ?):
    https://github.com/getsentry/sentry-javascript/issues/1762#issuecomment -442778751
    https://github.com/getsentry/sentry-javascript/issues/1622
    https://github.com/getsentry/sentry-javascript/issues/951
  • @sheerun рдЖрдк рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддреЗ рд╣реИрдВ next.js рд╕рд░реНрд╡рд░ рдФрд░ рдРрдк рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧрдЗрдиреНрд╕ рдмрдирд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдХреНрдпрд╛ рдХреЛрдИ рдлреАрдЪрд░ рдЯрд┐рдХрдЯ рдЙрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╣реАрдВ рдХреЗрдВрджреНрд░рд┐рдд рд╣реИ?
  • nextjs рдЯреАрдо рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рдорджрдж рдХрд░ рд╕рдХрддреА рд╣реИ:
    https://github.com/zeit/next.js/issues/1852#issuecomment -337573921
    https://github.com/zeit/next.js/issues/1852#issuecomment -427124032

next.js рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдХреА рдЬрд░реВрд░рдд рд╣реЛрддреА рд╣реИ, рд╡рд╣ рд╣реИ next.config.js рдореЗрдВ рдХрд╕реНрдЯрдо рдорд┐рдбрд▓рд╡реЗрдпрд░ рдЬреЛрдбрд╝рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдФрд░ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ (рдЖрдЗрд╕реЛрдореЛрд░реНрдлрд┐рдХ) рдкреНрд▓рдЧрдЗрди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП next.browser.js рдЬреИрд╕рд╛ рдХреБрдЫ (next.config.js рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡реЗрдмрдкреИрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рджреВрд╕рд░реЛрдВ рдХреЗ рдмреАрдЪ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЕрдиреНрдп рдЪреАрдЬреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛрдб рдореЗрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдкрд░рд┐рдкрддреНрд░ рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛ рдХрд╛рд░рдг рд╣реЛрдЧрд╛)ред

next.browser.js рдХреЗ рд▓рд┐рдП next.js рдРрдк рдпрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдШрдЯрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдбреЗрдХреЛрд░реЗрдЯрд░ рдЬреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рдореИрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдПрдХ рдкреНрд▓рдЧрдЗрди рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрддрд░реА рдПрдХреАрдХрд░рдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддрд╛ рдерд╛ред

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЯрд┐рдХрдЯ рд╣реИ рдпрд╛ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ @timneutkens рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдЧрд▓реЗ рд╕рд░реНрд╡рд░ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреИрдХреЗрдЬреЛрдВ рдореЗрдВ

module.exports = {
  server: server => {
    server.use(Sentry.Handlers.errorHandler())
  }
}

рдореИрдВрдиреЗ рдРрд╕реЗ рдПрдкреАрдЖрдИ рдХреЗ рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЛ #6922 . рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ

рдпрд╣ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХреЛрдб рдореЗрдВ рдбреЗрдХреЛрд░реЗрдЯрд░ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЕрдиреБрдмрдВрдз рдХреЛ рдПрдХ рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ .listen() рдХреЙрд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ next.js рдХреЛ рддрддреНрдХрд╛рд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЗрд╕реЗ рдФрд░ рд╕рдЬрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ

рдореБрдЭреЗ with-sentry рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдмрд╣реБрдд рдкрд░реЗрд╢рд╛рдиреА рд╣реЛ рд░рд╣реА рдереА, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдПрдХ рдФрд░ рдЕрдзрд┐рдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдкреАрдЖрд░ рдЦреЛрд▓рд╛ред рдЗрд╕рдореЗрдВ рд╕рднреА рдШрдВрдЯрд┐рдпрд╛рдБ рдФрд░ рд╕реАрдЯреА рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред

https://github.com/zeit/next.js/pull/7119

рдЗрд╕реЗ рдХрд╕реНрдЯрдо _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 });
}

рдЗрд╕рд╕реЗ рдореБрдЭреЗ рдорджрдж рдорд┐рд▓рддреА рд╣реИред

рдЯреАрдмреАрдПрдЪ рдореИрдВ рдмрд╣реБрдд рдЙрд▓рдЭрди рдореЗрдВ рд╣реВрдВ рдХрд┐ рдЕрдЧрд▓реЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╕реНрдерд╛рди рдХреМрди рд╕реЗ рд╣реИрдВред рдЬреЗрдПрд╕ рдЕрднреА рд╣реИрдВред _app.tsx, _error.tsx рдФрд░ _document.tsx рд╣реИрдВ, рдХреБрдЫ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ рдХрд╣ рд░рд╣реА рд╣реИрдВ рдХрд┐ рдХреБрдЫ рд╕рд╛рдорд╛рди _error.tsx рдореЗрдВ рдкрдХрдбрд╝реЗ рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдП (рдЬреИрд╕реЗ: https://github.com/zeit/next.js/pull/5727/files #r235981700) рд▓реЗрдХрд┐рди рд╡рд░реНрддрдорд╛рди рдЙрджрд╛рд╣рд░рдг рдпрд╛ рддреЛ _app.tsx рдпрд╛ _app рдФрд░ _document рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

рдореИрдВрдиреЗ рдЕрдм рджреЛрдиреЛрдВ рддрд░реАрдХреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдФрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ ssr рдХреЗ рджреМрд░рд╛рди рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдХреБрдЫ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдореЗрд░реЗ рд▓рд┐рдП рдкрдХрдбрд╝ рдореЗрдВ рдирд╣реАрдВ рдЖ рд░рд╣реА рд╣реИрдВред рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХреЗ рд▓рд┐рдП рдЕрдм рдХреМрди рд╕реЗ рд╕реНрдерд╛рди рд╕рд╣реА рд╣реИрдВ? рдореЗрд░реЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рддрд╛рд░реНрдХрд┐рдХ рдПрдХ _app рдХреЗ рдШрдЯрдХрдбрд┐рдбрдХреИрдЪ рдФрд░ _error рдХреЗ getInitialProps рдореЗрдВ рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдкрд░реЛрд╕рд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рдореИрдВ _рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рд╕рдВрдкреВрд░реНрдг process.on рднрд╛рдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рднреНрд░рдорд┐рдд рд╣реВрдБ

рдХреНрдпрд╛ рдХреЛрдИ рдФрд░ рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЬреНрдЮрд╛рди рд░рдЦрдиреЗ рд╡рд╛рд▓рд╛ рдХреГрдкрдпрд╛ рдЗрд╕ рдкреНрд░рд╢реНрди рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИ?

@abraxxas process.on рдореЗрдВ _document.js рд╕рд░реНрд╡рд░ рдкрд░ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝ рд░рд╣рд╛ рд╣реИред рдкреБрдирд░реНрдХрдерди рдХреЗ рд░реВрдк рдореЗрдВ,

  • _document.js рдХреЗрд╡рд▓ _рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб_ рд╣реИ рдФрд░ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдорд╛рд░реНрдХрдЕрдк рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  • _app.js рдХреЗрд╡рд▓ _client-side_ рд╣реИ рдФрд░ рдкреГрд╖реНрдареЛрдВ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдЗрд╕рд▓рд┐рдП, рдЬрдм рд╕рд░реНрд╡рд░ рдкрд░ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ рддреЛ рдЙрд╕реЗ 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

рдЙрд╕ рдкреНрд░рд╢реНрди рдХреЛ рдЬреЛрдбрд╝рдирд╛ ... рдореИрдВрдиреЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд░реЗрдВрдбрд░() рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрдиреЗ рдХреА рднреА рдХреЛрд╢рд┐рд╢ рдХреА (рдореИрдВрдиреЗ рд░рд╛рдЬреНрдп рдХреЛ raiseErrorInRender рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд┐рдпрд╛: рд╕рдЪ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкрд╣рд▓рд╛ рд░реЗрдВрдбрд░, рдЬреЛ рд╕рд░реНрд╡рд░ рдкрдХреНрд╖реАрдп рд╣реИ, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛), рдФрд░ рд╡рд╣ рддреНрд░реБрдЯрд┐ рднреА рд╕рдВрддрд░реА рджреНрд╡рд╛рд░рд╛ рдХрдмреНрдЬрд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдХреНрдпрд╛ рд╡реЗ рд╕рд░реНрд╡рд░ рдкрдХреНрд╖реАрдп рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреИрдкреНрдЪрд░ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИрдВ? рдореИрдВ рдЕрдЧрд▓рд╛ 9 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдпрджрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдРрд╕рд╛ рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ, рддреЛ _document.js рдлрд╝рд╛рдЗрд▓ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдХрд╛рд░рдг рдирд╣реАрдВ рд╣реЛрдЧрд╛ред

рдХрд┐рд╕реА рднреА рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП рдЕрдЧреНрд░рд┐рдо рд░реВрдк рд╕реЗ рдзрдиреНрдпрд╡рд╛рдж!

@timneutkens рдареАрдХ рд╣реИ, рдпрд╣ рдореЗрд░реЗ рджрд┐рдорд╛рдЧ рдХреЛ рдереЛрдбрд╝рд╛ рд╕рд╛ рдЕрдкрдбреЗрдЯ рдХрд┐рдП рдЧрдП рд╣реИрдВ ред рдХреНрдпрд╛ рдЖрдк рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреИрд╕реЗ _app.js рдХреЗрд╡рд▓ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдирд╣реАрдВ рд╣реИ?

рдЖрдкрдХреЗ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрддреЗ рд╣реБрдП, _app рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рдкреГрд╖реНрдареЛрдВ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдРрдк рдШрдЯрдХ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╣рдо рдЗрд╕реЗ рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░реЗрдВрдЧреЗ рдЬреИрд╕реЗ рдкреГрд╖реНрда рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рд╕реНрдерд╛рдпреА рд▓реЗрдЖрдЙрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ (рд╕рднреА рдкреГрд╖реНрда рд╕рдорд╛рди _app рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ), рдпрд╛ рд░реЗрдбрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рддреЛ, рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рдкрд╣рд▓рд╛ рд░реЗрдВрдбрд░ рднреА _app рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдЧрд╛ (рдпрд╣ рдХреЗрд╡рд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдирд╣реАрдВ рд╣реИ)ред

рдЙрд╕ рдкреНрд░рд╢реНрди рдХреЛ рдЬреЛрдбрд╝рдирд╛ ... рдореИрдВрдиреЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд░реЗрдВрдбрд░() рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрдиреЗ рдХреА рднреА рдХреЛрд╢рд┐рд╢ рдХреА (рдореИрдВрдиреЗ рд░рд╛рдЬреНрдп рдХреЛ raiseErrorInRender рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд┐рдпрд╛: рд╕рдЪ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкрд╣рд▓рд╛ рд░реЗрдВрдбрд░, рдЬреЛ рд╕рд░реНрд╡рд░ рдкрдХреНрд╖реАрдп рд╣реИ, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛), рдФрд░ рд╡рд╣ рддреНрд░реБрдЯрд┐ рднреА рд╕рдВрддрд░реА рджреНрд╡рд╛рд░рд╛ рдХрдмреНрдЬрд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЙрд╕ рддреНрд░реБрдЯрд┐ рдХреЛ рд╕рдВрддрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рдЕрдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рд╣реИ? рдореИрдВрдиреЗ рдЗрд╕реЗ _error рдХреЗ getInitialProps рдореЗрдВ рдХреИрдкреНрдЪрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдВрддрд░реА рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдореБрдЭреЗ рд╕рд░реНрд╡рд░ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХрд╛ рдПрдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рддрд░реАрдХрд╛ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ, рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ (рдЬреНрдпрд╛рджрд╛рддрд░ рдЕрдЧрд░ рд╡реЗ рдПрдкреАрдЖрдИ рд╡рд┐рдлрд▓рддрд╛рдУрдВ рд╕реЗ рдЬреБрдбрд╝реЗ рд╣реИрдВ) рддреЛ рд╡реЗ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕рдВрддрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рддреНрд░реБрдЯрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рдирд╣реАрдВ рд╣реБрдЖ рд╣реВрдВред

рдЙрд╕ рдкреНрд░рд╢реНрди рдХреЛ рдЬреЛрдбрд╝рдирд╛ ... рдореИрдВрдиреЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд░реЗрдВрдбрд░() рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрдиреЗ рдХреА рднреА рдХреЛрд╢рд┐рд╢ рдХреА (рдореИрдВрдиреЗ рд░рд╛рдЬреНрдп рдХреЛ raiseErrorInRender рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд┐рдпрд╛: рд╕рдЪ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкрд╣рд▓рд╛ рд░реЗрдВрдбрд░, рдЬреЛ рд╕рд░реНрд╡рд░ рдкрдХреНрд╖реАрдп рд╣реИ, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛), рдФрд░ рд╡рд╣ рддреНрд░реБрдЯрд┐ рднреА рд╕рдВрддрд░реА рджреНрд╡рд╛рд░рд╛ рдХрдмреНрдЬрд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЙрд╕ рддреНрд░реБрдЯрд┐ рдХреЛ рд╕рдВрддрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рдЕрдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рд╣реИ? рдореИрдВрдиреЗ рдЗрд╕реЗ _error рдХреЗ getInitialProps рдореЗрдВ рдХреИрдкреНрдЪрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдВрддрд░реА рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдореБрдЭреЗ рд╕рд░реНрд╡рд░ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХрд╛ рдПрдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рддрд░реАрдХрд╛ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ, рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ (рдЬреНрдпрд╛рджрд╛рддрд░ рдЕрдЧрд░ рд╡реЗ рдПрдкреАрдЖрдИ рд╡рд┐рдлрд▓рддрд╛рдУрдВ рд╕реЗ рдЬреБрдбрд╝реЗ рд╣реИрдВ) рддреЛ рд╡реЗ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕рдВрддрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рддреНрд░реБрдЯрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рдирд╣реАрдВ рд╣реБрдЖ рд╣реВрдВред

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдирд╣реАрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдЬрд┐рд╕ рд╕рдорд╛рдзрд╛рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ, рд╡рд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрджрд╛рд╣рд░рдг (рдУрд╡рд░рд░рд╛рдЗрдб _document.js рдлрд╝рд╛рдЗрд▓ рдХреЛ рдШрдЯрд╛рдХрд░) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╡рд╣реА рд╣реИрдВ рдЬрд┐рди рдкрд░ рдореЗрд░рд╛ рдХреЛрдИ рдирд┐рдпрдВрддреНрд░рдг рдФрд░ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдиреЗрдВ, рдЬрдм рддрдХ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореБрдЭреЗ рд░рд┐рдкреЛрд░реНрдЯ рди рдХрд░реЗрдВред рд╕рд░реНрд╡рд░ рдХреА рддрд░рдл, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдХрд┐рд╕реА рднреА рд▓реЙрдЧ рд▓рд╛рдЗрди рдХреЛ рд╕реАрдзреЗ рд▓реЙрдЧ рдлрд╝рд╛рдЗрд▓ рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░ рджреВрдВрдЧрд╛ред рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдПрдХ рд╣реА рд╕реНрдерд╛рди рдкрд░ рд╕рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд░рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдХрд░рдиреЗ рд╕реЗ рдореБрдЭреЗ рдХрдо рд╕реЗ рдХрдо рдХрд┐рд╕реА рднреА рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрдЧреА рдЬреЛ рдЖрд╡реЗрджрди рдкрд░ рд╣реЛ рд╕рдХрддреА рд╣реИред

рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рдЦрд╝рдпрд╛рд▓ рд╣реИ? рдзрдиреНрдпрд╡рд╛рдж!

рдЙрд╕ рдкреНрд░рд╢реНрди рдХреЛ рдЬреЛрдбрд╝рдирд╛ ... рдореИрдВрдиреЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд░реЗрдВрдбрд░() рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрдиреЗ рдХреА рднреА рдХреЛрд╢рд┐рд╢ рдХреА (рдореИрдВрдиреЗ рд░рд╛рдЬреНрдп рдХреЛ raiseErrorInRender рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд┐рдпрд╛: рд╕рдЪ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкрд╣рд▓рд╛ рд░реЗрдВрдбрд░, рдЬреЛ рд╕рд░реНрд╡рд░ рдкрдХреНрд╖реАрдп рд╣реИ, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛), рдФрд░ рд╡рд╣ рддреНрд░реБрдЯрд┐ рднреА рд╕рдВрддрд░реА рджреНрд╡рд╛рд░рд╛ рдХрдмреНрдЬрд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЙрд╕ рддреНрд░реБрдЯрд┐ рдХреЛ рд╕рдВрддрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рдЕрдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рд╣реИ? рдореИрдВрдиреЗ рдЗрд╕реЗ _error рдХреЗ getInitialProps рдореЗрдВ рдХреИрдкреНрдЪрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдВрддрд░реА рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдореБрдЭреЗ рд╕рд░реНрд╡рд░ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХрд╛ рдПрдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рддрд░реАрдХрд╛ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ, рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ (рдЬреНрдпрд╛рджрд╛рддрд░ рдЕрдЧрд░ рд╡реЗ рдПрдкреАрдЖрдИ рд╡рд┐рдлрд▓рддрд╛рдУрдВ рд╕реЗ рдЬреБрдбрд╝реЗ рд╣реИрдВ) рддреЛ рд╡реЗ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕рдВрддрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рддреНрд░реБрдЯрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рдирд╣реАрдВ рд╣реБрдЖ рд╣реВрдВред

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдирд╣реАрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдЬрд┐рд╕ рд╕рдорд╛рдзрд╛рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ, рд╡рд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрджрд╛рд╣рд░рдг (рдУрд╡рд░рд░рд╛рдЗрдб _document.js рдлрд╝рд╛рдЗрд▓ рдХреЛ рдШрдЯрд╛рдХрд░) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╡рд╣реА рд╣реИрдВ рдЬрд┐рди рдкрд░ рдореЗрд░рд╛ рдХреЛрдИ рдирд┐рдпрдВрддреНрд░рдг рдФрд░ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдиреЗрдВ, рдЬрдм рддрдХ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореБрдЭреЗ рд░рд┐рдкреЛрд░реНрдЯ рди рдХрд░реЗрдВред рд╕рд░реНрд╡рд░ рдХреА рддрд░рдл, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдХрд┐рд╕реА рднреА рд▓реЙрдЧ рд▓рд╛рдЗрди рдХреЛ рд╕реАрдзреЗ рд▓реЙрдЧ рдлрд╝рд╛рдЗрд▓ рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░ рджреВрдВрдЧрд╛ред рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдПрдХ рд╣реА рд╕реНрдерд╛рди рдкрд░ рд╕рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд░рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдХрд░рдиреЗ рд╕реЗ рдореБрдЭреЗ рдХрдо рд╕реЗ рдХрдо рдХрд┐рд╕реА рднреА рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрдЧреА рдЬреЛ рдЖрд╡реЗрджрди рдкрд░ рд╣реЛ рд╕рдХрддреА рд╣реИред

рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рдЦрд╝рдпрд╛рд▓ рд╣реИ? рдзрдиреНрдпрд╡рд╛рдж!

рдареАрдХ рдпрд╣реА рд╣рдо рдЕрднреА рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдпрд╣ рдереЛрдбрд╝рд╛ рдЕрдЯрдкрдЯрд╛ рд╣реИ рд▓реЗрдХрд┐рди рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣рдо рд╕рд╛рдордиреЗ рдЖ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рдХреБрдЫ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕рдВрддрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдВрддрд░реА рдпрд╛ рдЕрдЧрд▓реЗ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдЪрд▓ рд░рд╣рд╛ рд╣реЛрдЧрд╛ред рдореИрдВрдиреЗ рд╕рд░рд▓ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рджреЛрдиреЛрдВ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рдФрд░ рд╡реЗ рджреЛрдиреЛрдВ рд╕рдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдХрдо рд╕реЗ рдХрдо рдХреБрдЫ рд╣рдж рддрдХ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣рдорд╛рд░реЗ рд╕реЗрдЯрдЕрдк рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИ

рдЗрд╕ рдереНрд░реЗрдб рдХреЗ рд▓реЛрдЧреЛрдВ рдХреА рджрд┐рд▓рдЪрд╕реНрдкреА https://github.com/zeit/next.js/pull/8684 рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рдмрдЧреНрд╕ рдореЗрдВ рд╣реЛ рд╕рдХрддреА рд╣реИред рдЗрд╕рдореЗрдВ рд╣реИрдВрдбрд▓ рди рдХрд┐рдП рдЧрдП рдЕрдкрд╡рд╛рджреЛрдВ рдХреЗ 12 рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рдЖрдк рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдЦреЗрд▓ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ Next.js рдЖрдкрдХреЗ рд▓рд┐рдП рдХреМрди рд╕реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИ рдФрд░ рдХреНрдпрд╛ рдирд╣реАрдВред

рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЦрдмрд░?

рдореЗрд░реЗ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реИ redux рдиреЛрдб рдмрдЪрд╛рдиреЗ рдореЗрдВ рдбреЗрдЯрд╛ рддреНрд░реБрдЯрд┐ рд▓рд╛рдиреЗ state рддреЛ рдлрд┐рд░ рдореЗрдВ componentDidMount рдХреЗ _app.js рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдпрд╛ рдкреЛрд╕реНрдЯ рддреНрд░реБрдЯрд┐ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХреБрдЫ (рдЪреЗрддрд╛рд╡рдиреА рдмреИрдХрдПрдВрдб рдХреЗ рд▓рд┐рдП)ред
рдХреЛрдб рд╡рд╣рд╛рдБ рд╣реИ next-antd-scaffold_server-error ред

========> рд░рд╛рдЬреНрдп

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());
    }
  }
...

_рдЕрдиреЛрд░реНрдЯреЛрдбреЙрдХреНрд╕_рд╕рдорд╛рдзрд╛рдиреЛрдВ рд╕реЗ рдкреНрдпрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП

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 рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рд╢реВрдиреНрдп рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рд╣реИред

рдореИрдВрдиреЗ рдЗрд╕реЗ рдЗрд▓рд╛рд╕реНрдЯрд┐рдХ рдПрдкреАрдПрдо рдиреЛрдб рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП рд╣рд▓ рдХрд┐рдпрд╛ (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 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}`);
    }
  }

}

рд╕рднреА рдХреЛ рдкреНрд░рдгрд╛рдо! рд╣рдордиреЗ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рдХреЛ рдЬреЛрдбрд╝реЗ рдмрд┐рдирд╛ рдиреЗрдХреНрд╕реНрдЯ.рдЬреЗрдПрд╕ рдореЗрдВ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕реНрдЯрд╛рдЗрд▓ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдирдкреАрдПрдо рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд▓реЙрдиреНрдЪ рдХреА рд╣реИред рдпрд╣ рдЖрдкрдХреЗ рд╕рд░реНрд╡рд░ рддреНрд░реБрдЯрд┐ рдкреНрд░рдмрдВрдзрди рдЪреБрдиреМрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣рд╛рдпрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ! рдпрджрд┐ рдЖрдк рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рддреЛ рдЗрд╕реЗ рджреЗрдЦреЗрдВред https://github.com/oslabs-beta/connext-js

рдХрд┐рд╕реА рдХреЛ рднреА getServerSideProps рдореЗрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ (рдФрд░ рд╕рдВрднрд╛рд▓рдиреЗ) рдореЗрдВ рд╕рдлрд▓рддрд╛ рдорд┐рд▓реА рд╣реИ?

рдХрд┐рд╕реА рдХреЛ рднреА getServerSideProps рдореЗрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ (рдФрд░ рд╕рдВрднрд╛рд▓рдиреЗ) рдореЗрдВ рд╕рдлрд▓рддрд╛ рдорд┐рд▓реА рд╣реИ?

рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ, рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдврд╛рдВрдЪрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рджреЛрдиреЛрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд▓реЙрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдореБрд╣рд╛рд╡рд░реЗрджрд╛рд░ рддрд░реАрдХрд╛ рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ тАНтЩВя╕П

рдХрд┐рд╕реА рдХреЛ рднреА getServerSideProps рдореЗрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ (рдФрд░ рд╕рдВрднрд╛рд▓рдиреЗ) рдореЗрдВ рд╕рдлрд▓рддрд╛ рдорд┐рд▓реА рд╣реИ?

@stephankaag

рд╣рд╛рдБ, рдРрд╕рд╛ рдХреБрдЫ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

рдХреНрд░реИрд╢ рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рдПрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдмрдирд╛рдПрдВред рдореИрдВрдиреЗ 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 }
  }
}
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

knipferrc picture knipferrc  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

YarivGilad picture YarivGilad  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

irrigator picture irrigator  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

swrdfish picture swrdfish  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

ghost picture ghost  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ