CharlieMcVicker / mathjax-react

React Component Library for MathJax
33 stars 14 forks source link

ReferenceError: window is not defined #34

Open MartinLBarranco opened 2 years ago

MartinLBarranco commented 2 years ago

"This error happened while generating the page. Any console logs will be displayed in the terminal window." this is what nextjs spits when I simply do " import { MathComponent } from 'mathjax-react' ". It also lists me a lots of errors I can give you but I defenitly can't find a solution to this. If you need more info just ask me.

Thanks

CharlieMcVicker commented 2 years ago

Are you trying to do server-side rendering?

Also, I'd be happy to take a look at the errors to see if I can reproduce them. It would also help if you can tell me any more about the stack you are using.

Thanks!

milotoor commented 2 years ago

@CharlieMcVicker I just encountered this error too. I am also using NextJS and yes, it occurs during server-side rendering:

error - ReferenceError: window is not defined
    at Object.browserAdaptor (/path/to/project/node_modules/mathjax-full/js/adaptors/browserAdaptor.js:6:45)
    at Object.<anonymous> (/path/to/project/node_modules/mathjax-react/dist/index.js:61:30)
    at Module._compile (node:internal/modules/cjs/loader:1099:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:975:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:999:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.mathjax-react (/path/to/project/.next/server/pages/2-preflight-procedures/B-instruments.js:427:18)
    at __webpack_require__ (/path/to/project/.next/server/webpack-runtime.js:33:42)

It's being triggered by the browserAdaptor function, called from utils/convert.ts line 17. Perhaps this issue should be filed in mathjax-full instead? Actually it looks like @MartinLBarranco did file one there, too, but did not provide much in the way of actionable information. This is the offending line, which assumes that the window object will be in scope. Alas, this is untrue in node. Perhaps using globalThis instead could resolve the issue? That certainly ought to behave the same in supporting web browsers (and core-js provides a polyfill for those which do not).

CharlieMcVicker commented 2 years ago

Okay thanks for getting back to me.

Server-side rendering with MathJax might be a bit of a bear. I think I may have to fork the project for it, so that the bundle doesn’t get too large. It’s something I’ve spoken with MathJax maintainers about though.

At this point I’ve seen a lot of requests though, so I will make an attempt this week and get back to you.

In short, it will be a bit complicated because MathJax wants to be able to stick things in the DOM and mutate them, which is difficult during SSR because… there is no DOM. In addition, rendering will have to use synchronous calls so that HTML from MathJax can be produced the first time a component is rendered instead of using a useEffect hook.

Are you hoping to do an entirely server side rendered app, or are you hydrating and rendering new equations on the front end?

Milo Toor @.***> schrieb am Sa. 20. Aug. 2022 um 16:27:

@CharlieMcVicker https://github.com/CharlieMcVicker I just encountered this error too. I am also using NextJS and yes, it occurs during server-side rendering:

error - ReferenceError: window is not defined at Object.browserAdaptor (/path/to/project/node_modules/mathjax-full/js/adaptors/browserAdaptor.js:6:45) at Object. (/path/to/project/node_modules/mathjax-react/dist/index.js:61:30) at Module._compile (node:internal/modules/cjs/loader:1099:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10) at Module.load (node:internal/modules/cjs/loader:975:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Module.require (node:internal/modules/cjs/loader:999:19) at require (node:internal/modules/cjs/helpers:102:18) at Object.mathjax-react (/path/to/project/.next/server/pages/2-preflight-procedures/B-instruments.js:427:18) at __webpack_require__ (/path/to/project/.next/server/webpack-runtime.js:33:42)

It's being triggered by the browserAdaptor function, called from utils/convert.ts line 17 https://github.com/CharlieMcVicker/mathjax-react/blob/master/src/utils/convert.ts#L17. Perhaps this issue should be filed in mathjax-full instead? Actually it looks like @MartinLBarranco https://github.com/MartinLBarranco did file one there https://github.com/mathjax/MathJax-src/issues/840, too, but did not provide much in the way of actionable information. This is the offending line https://github.com/mathjax/MathJax-src/blob/master/ts/adaptors/browserAdaptor.ts#L47, which assumes that the window object will be in scope. Alas, this is untrue in node. Perhaps using globalThis instead could resolve the issue? That certainly ought to behave the same in supporting web browsers https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis#browser_compatibility (and core-js provides a polyfill https://github.com/zloirock/core-js#ecmascript-globalthis for those which do not).

— Reply to this email directly, view it on GitHub https://github.com/CharlieMcVicker/mathjax-react/issues/34#issuecomment-1221403091, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABK4UWE7JVL6EEDCIMBXMJLV2E5UPANCNFSM552WXABA . You are receiving this because you were mentioned.Message ID: @.***>

CharlieMcVicker commented 2 years ago

To be clear, polyfilling the window global won't fix things. We need to not be on the browserAdaptor codepath, but instead use the litedomAdaptor. The tricky bit with apps that use hydrate or whatever to create an interactive app on the frontend will then need to use the browserAdaptor. If either of you know a good way to use different code on the server and client with NextJS, I'd love your input. I've never used it before myself!

matildepark commented 2 years ago

@MartinLBarranco What I did was lazy-load the Math component when we need it, explicitly disabling server-side rendering.

In my case, I define my Math component:

import React from "react";
import { MathComponent } from "mathjax-react"

const Math = ({ block = false, children }) => {
    return <MathComponent display={block} tex={String.raw`${children}`} />;
};

export default Math;

And in another file I import it for use like this:

import dynamic from "next/dynamic";

// ...

const Math = dynamic(() => import("./markdown/Math"), {
  ssr: false
})
milotoor commented 2 years ago

@matildepark thanks! I was not familiar with next/dynamic