How to display JS error from source map in DOM
Asked Answered
I

1

7

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 ?

Impetrate answered 29/1, 2019 at 11:51 Comment(10)
Look like this.props.foo is undefined. Can you print it to console? Or start search problem from this.propsPorta
Maybe I need to clarify the question, I'm not trying to solve this particular error, this code is there to produce the error. What I'm trying to do is display the same error as in the debug iframe but render it to my DOM so I can see it when Google bot tries and fails to render my page.Impetrate
How about try{/*...*/}catch(e){ console.log(e.stack) }?Porta
I don't think it's something you can do in "browser land". I think you would need to create your own babel plugin using AST. not sure exactly how to do that but you can explore it via AST explorerSwetiana
I think the problem is that your js file is minified by webpack or something else and the google bot will print the error like other browser will do. Chrome uses the webpack sourcemap to show in the typescript file, which line is executing. Maybe use chrome to find out, where the error is, i think the google bot is a modified chromium fork, it will not interpret the things in a other way.Copp
@Sagivb.g Yes, AST seems to be what the debug of create-react-app must be using under the hood. However I wonder if there can't be an easier solution, a library maybe, that can take an error and source map and 'do the translation' @Copp Yes I understand the Google bot won't be able to do this, so I basically need to use my JS code to do the translation taking the error and source map file, then displaying this in the DOMImpetrate
@GeoffreyHug maybe redbox-react would help?Swetiana
@Sagivb.g This looks like what I'm looking for, sadly I can't install it because of some permissions issues, even though I'm running sudo :/ I found another SO question that seems to be the missing piece : #32642584Impetrate
Well apparently my permissions error is not related to redbox-react but to npm and WSLImpetrate
@Sagivb.g I managed to solve my npm problem and it's working with redbox-react! I can now see the detailed and accurate errors on the Google bot rendering :D Feel free to post an answer so I can accept itImpetrate
S
2

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

});
Swetiana answered 29/1, 2019 at 13:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.