'Sentry with SSR

  • We have an application on Reactjs
  • We have an SSR that builds the app on webpack, renders this application and returns HTML
  • Then on the client-side we hydrate the app
  • So the app is run on both server and client sides.

Problem:

We'd like to use sentry in react, so that it can be used on both client and server sides, because an error may occur in either place

What we've tried:

There are 2 modules @sentry/browser and @sentry/node. We tried to make a module that would do:

export default isClientSide ? SentryBrowser : SentryNode

So if it's client, then use SentryBrowser. If server - SentryNode

But @sentry/node can't be run on webpack since it can't resolve node dependencies like fs, path etc.

Question: How can we use a single Sentry interface on both client and server sides for React like @sentry/nextjs works on both sides?



Solution 1:[1]

Short answer - you can't.

Client-side is wrapped in special HOC, called in most cases Error Boundary. React passes up an error to the root component of the project and catches it and reports it to the URL. This is a browser, which is client's "server", can do requests on ethernet and so on.

If you run NextJS server, not html export (extremely important condition!), under the hood it is uses some NodeJS libraries (Express, for example). This server has nothing in common with Webpack or JS compilation and is used as middleware. As you can see, it is just a wrapper upon some route or functionality. If you got an error on server, it is reported by NodeJS, not Webpack. So the flag somewhere in React or Webpack plugins will not help you.

One more time - client and server are different environments, browser and NodeJS server. The errors are reported by servers, not bundlers. Webpack will not help you here.

Solution 2:[2]

Our solution was to pass in an errorHandler prop to the app. When rendering on the server we'd pass in @sentry/node's captureException, and on the client we'd pass in the @sentry/browser's one. Seemed to work just fine.

const App = ({errorHandler}) => {
  ..
  return (<ErrorBoundary errorHandler={errorHandler}>
    ..
  </ErrorBoundary>);

Then on server:

import { captureException as serverCaptureEx } from '@sentry/node';

hydrate(..., <App errorHandler={serverCaptureEx} />)

and on client:

import { captureException as clientCaptureEx } from '@sentry/browser';

render(..., <App errorHandler={clientCaptureEx} />)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Eugene Mikhushkin
Solution 2 McTrafik