Search code examples
javascriptreactjssource-maps

How to display JS error from source map in DOM


I'm trying to debug my app created with create-react-app for the Google bot.

TL:DR: I need to add my error to the DOM so it's visible in the Google bot rendering. The problem is how do I get the same accurate (via source maps) file/line/column numbers that React displays in dev to be displayed in a DOM node.

On Google documentation for debugging rendering, they provide a snippet using a global window.addEventlistener('error') to add the error to the DOM so it's visible in the rendered screenshot that Google bot generates.

However, when I try this on development, I'm getting this as the first line of the stack trace : at Home.render (http://localhost:3000/static/js/main.chunk.js:17125:34)

So it's giving me the right function, but the source file and line/column numbers are wrong.

I'm able to see the correct error via the development error display that I assume is something from create-react-app enter image description here

Notice that it gives the error in src/containers/Home/Home.js on line 70 compared to the DOM pre output.

Is there a way to get the same accurate result in my DOM pre output ?


Solution

  • I think it can be done via AST (maybe as a babel plugin), you can explore it with AST explore.

    If writing AST is too much, maybe redbox-react could help. It's a react component that accepts an error and displaying it in human friendly format on the screen.

    import RedBox from 'redbox-react'
    
    const e = new Error('boom')
    const box = <RedBox error={e} />
    

    An edit from the OP

    Here is the actual code I ended up using to get the rendering of the errors in the Google bot rendering in the index.js file

    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    import RedBox from 'redbox-react'
    
    var errors = []
    
    window.addEventListener('error', function(e) {
    
        errors.push(e)
    
        const displayErrors = (
          <ul>
            {errors.map(e => {
              return <li key={e.message}><RedBox error={e.error} /></li>
            })}
          </ul>
        )
    
        const app = errors.length > 0 ? displayErrors : <App />
    
        ReactDOM.render(app, document.getElementById('root'));
    
    });