Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next.js build error: Window is not defined #228

Closed
mikeriley131 opened this issue Nov 2, 2023 · 33 comments
Closed

Next.js build error: Window is not defined #228

mikeriley131 opened this issue Nov 2, 2023 · 33 comments

Comments

@mikeriley131
Copy link

mikeriley131 commented Nov 2, 2023

isomorphic-dompurify version - 1.9.0
Node version - 18.18.0
Next.js version - 13.5.4
React version - 18.2.0

I am importing my company's React component library that makes use of Isomorphic DOMPurify.
No issues when using it in a client-side app.
However, when running yarn build in my Next.js project I am getting ReferenceError: window is not defined and the path in the logs points to the following line of code: var ti=window.DOMPurify||(window.DOMPurify=Vl().default||Vl());

Am I doing something incorrectly?

Here's a repo for the Next.js app - https://github.com/mikeriley131/next-idp-test
And here's a repo for the component library - https://github.com/mikeriley131/pyrographic-react-component-library

The component library is "npm link"ed to the next app.

When I add the Button component from the library to the Next.js app, it throws the following error:

Server Error
Error: window is not defined

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source
../pyrographic-react-component-library/dist/components/Button/index.js (509:9) @ window

  507 | }(Ce)), Ce.exports;
  508 | }
> 509 | var fn = window.DOMPurify || (window.DOMPurify = ht().default || ht());
      |       ^
  510 | function pn(re) {
  511 | const { className: xe, ...z } = re;
  512 | return /* @__PURE__ */ rn("button", { className: `${xe} ${ln.button}`, ...z, children:
@kkomelin
Copy link
Owner

kkomelin commented Nov 4, 2023

@mikeriley131 Wow, that's a new one. Thanks for reporting. I need to play with it a little bit.

I think it's because Next is experimenting with the server-client rendering and changing related things quite often.

Did you try it with Next 14?

@mikeriley131
Copy link
Author

Not yet. I'll give that a try and report back.

@bjarn
Copy link

bjarn commented Nov 6, 2023

I'm on a Next.js 14 project here, all up to date, this error is indeed happening still on 14.

@kkomelin
Copy link
Owner

kkomelin commented Nov 6, 2023

Thanks guys. I have no idea how to fix that and why Next treats the browser field in the package.json as a server entry point https://github.com/kkomelin/isomorphic-dompurify/blob/master/package.json#L30

@nx-phinehas-sersah
Copy link

Having similar issues. Uncaught ReferenceError: window is not defined at (webpack-internal:///(middleware)/../../node_modules/isomorphic-dompurify/browser.js:1)

@kkomelin
Copy link
Owner

kkomelin commented Nov 7, 2023

Can someone report this issue to Next.js developers? Interested to know what they think.

@mikeriley131
Copy link
Author

@kkomelin
Copy link
Owner

kkomelin commented Dec 12, 2023

As @BohdanYavorskyi suggested here I'm going to try adding "use client" at the top of browser.js to fix the issue.

kkomelin added a commit that referenced this issue Dec 12, 2023
@kkomelin
Copy link
Owner

I've released a new version with a fix for this bug. Please check it out and let me know if it works for you https://github.com/kkomelin/isomorphic-dompurify/releases/tag/v1.12.0

@kkomelin kkomelin self-assigned this Dec 12, 2023
@kkomelin kkomelin added the bug Something isn't working label Dec 12, 2023
@kkomelin kkomelin removed their assignment Dec 12, 2023
@alexmilde
Copy link

alexmilde commented Dec 12, 2023

Hey. Thanks for your work!
I came across this issue with a svelte kit and cloudflare pages stack.

v.1.12 did not fix the issue for me, but don't stress yourself about it :)

@kkomelin
Copy link
Owner

Thanks @alexmilde for your feedback. I didn't know that it's an issue for Svelte Kit as well.

@BohdanYavorskyi
Copy link
Contributor

@kkomelin hey, do you have any ideas how this can be fixed? This issues blocks the upgrade on one of my projects :)

@kkomelin
Copy link
Owner

@BohdanYavorskyi No, I don't, unfortunately. Next's innovations kind of turn things upside down.

@BohdanYavorskyi
Copy link
Contributor

BohdanYavorskyi commented Dec 18, 2023

@kkomelin check this link, I guess same should be done for SSR support vercel/next.js#46893

But looks like you have the same in the package :(

Perhaps this can be rewritten differently?

image

@kkomelin
Copy link
Owner

kkomelin commented Dec 18, 2023

@kkomelin check this link, I guess same should be done for SSR support vercel/next.js#46893

@BohdanYavorskyi what exactly should I look at by the link you sent? Can you give me a link to the particular comment you meant?

Perhaps this can be rewritten differently?

Please go ahead and provide a pull-request.

@silasabbott
Copy link

silasabbott commented Dec 19, 2023

I came across this issue with v1.12.0 using SvelteKit deployed on Vercel Edge Functions (Vercel's custom runtime built on V8)

This only happens in Vercel Edge Functions for me—deploying locally or to Vercel Serverless Functions (which uses Node as a runtime) works perfectly. Not quite the original issue but probably related.

Error points to this line in browser.js as mentioned, so it does seem like browser.js is being used as an entrypoint incorrectly.

module.exports = window.DOMPurify || (window.DOMPurify = require('dompurify').default || require('dompurify'));
@kkomelin
Copy link
Owner

Error points to this line in browser.js as mentioned, so it does seem like browser.js is being used as an entrypoint incorrectly.

Thanks @silasabbott. I agree with your conclusion. Please comment and vote for this issue vercel/next.js#58142

@kkomelin
Copy link
Owner

For now, I'm going to rollback my attempt to fix this issue through this repo because it didn't work.

@kkomelin kkomelin removed the bug Something isn't working label Dec 20, 2023
@BohdanYavorskyi
Copy link
Contributor

BohdanYavorskyi commented Dec 20, 2023

@kkomelin hi, please replace this condition

const isClientSide = typeof process === 'undefined';

with proper one

const isClientSide = typeof window !== 'undefined';

I tried to debug the old variant and got this on nextjs server :)

image

@BohdanYavorskyi
Copy link
Contributor

@kkomelin can confirm it's working with the condition I sent (saw canvas module issues though (can be setup on webpack fallback level))

@kkomelin
Copy link
Owner

@BohdanYavorskyi

with proper one

Are you sure that no one can define window as well as Vercel defined process?

@BohdanYavorskyi
Copy link
Contributor

BohdanYavorskyi commented Dec 21, 2023

Are you sure that no one can define window as well as Vercel defined process?

yes, all libraries check client-side with the condition above. Besides dompurify has other checks inside. So even when you do window = {} it won't be working

And I could make it work locally with just this condition

@BohdanYavorskyi
Copy link
Contributor

@kkomelin can you release a new version ASAP? I can check it in old pages router and newest app router

@kkomelin
Copy link
Owner

kkomelin commented Dec 21, 2023

@BohdanYavorskyi I understand it's probably a cultural difference but I don't like your language like "proper one" or "can you release ASAP?". It's not my job and you're not my client to expect that. It's OpenSource. I asked you for a pull request, you didn't provide it but asked me to do it asap.

Anyway, I'm still not convinced that const isClientSide = typeof window !== 'undefined'; is the best way forward.

What if I set window = {} on the server? Will isClientSide be still false?

Above we discussed the fact that Vercel mistakenly uses browser field value of package.json on the server. In what way will your suggested solution fix that issue?

@BohdanYavorskyi
Copy link
Contributor

@BohdanYavorskyi I understand it's probably a cultural difference but I don't like your language like "proper one" or "can you release ASAP?". It's not my job and you're not my client to expect that. It's OpenSource. I asked you for a pull request, you didn't provide it but asked me to do it asap.

Anyway, I'm still not convinced that const isClientSide = typeof window !== 'undefined'; is the best way forward.

What if I set window = {} on the server, will isClientSide be still false?

Above we discussed the fact that Vercel mistakenly uses browser field value of package.json on the server. In what way will your suggested solution fix that issue?

agree with the first sentence. My bad

about second part

nothing prevent us to set process = {} on server as well

the check I mentioned as proper one is used by all libs which check if it is SSR/CSR.

You can even see it in dompurify

image

So I guess it should work fine without issues

@kkomelin
Copy link
Owner

@BohdanYavorskyi

nothing prevent us to set process = {} on server as well

Which some frameworks actually do, but it doesn't mean it's 100% correct.

the check I mentioned as proper one is used by all libs which check if it is SSR/CSR.

Could you please provide examples?

You can even see it in dompurify

Some more checks from Dompurify code on top of that condition:

if (!window || !window.document || window.document.nodeType !== 9) {
    // Not running in a browser, provide a factory function
    // so that you can pass your own Window

Source: https://github.com/cure53/DOMPurify/blob/d7498e0546c0f67cf95437ae430ff2035582a689/src/purify.js#L90

So I guess it should work fine without issues

Guessing is not enough when you're at risk of breaking many sites.

@BohdanYavorskyi
Copy link
Contributor

BohdanYavorskyi commented Dec 21, 2023

Some more checks from Dompurify code on top of that condition

exactly this part fails, because the check in the isomorphic package returns you false and this part is loaded which means the window is not defined on SSR

Examples with SSR/CSR check

image

image
image

image
image

@BohdanYavorskyi
Copy link
Contributor

@kkomelin should I open a PR? How can we proceed further?

@BohdanYavorskyi
Copy link
Contributor

@kkomelin should I open a PR? How can we proceed further?

the PR is up #239

@kkomelin
Copy link
Owner

Thanks @BohdanYavorskyi . I will take a look at your PR.
If you need it urgently, you may point out to your fork like this https://stackoverflow.com/a/50734317/1762849

@kkomelin
Copy link
Owner

kkomelin commented Dec 23, 2023

Happy to announce that we've just released 2.0.0 where we switched from typeof process === 'undefined' to typeof window !== 'undefined' for detecting the client.

It won't fix the issue related to misusing the package.json browser field by some hosting providers but should help with some server-side rendering issues in some frameworks.

Please test and let me know about the results.

@kkomelin
Copy link
Owner

According to the error description, I can say that Next is trying to use the browser entry point from package.json on server, which is incorrect, so it should be fixed on their side. Subscribe to this issue to get updated when it's fixed vercel/next.js#58142
And I'm closing this issue for now.

@kkomelin kkomelin closed this as not planned Won't fix, can't repro, duplicate, stale Dec 23, 2023
@mikeriley131
Copy link
Author

Finally had a chance to upgrade and test.

Still getting "window is not defined" error in the Next.js logs, however it no longer prevents the page from rendering.

⨯ [node_modules/@ux/balance-react/dist/index.es.js](mailto:node_modules/@ux/balance-react/dist/index.es.js) (5061:9) @ window
⨯ ReferenceError: window is not defined
    at __webpack_require__ (/Users/d2gn8/Projects/test-nextjs-app/.next/server/webpack-runtime.js:33:42)
    at eval (./app/page.js:11:75)
    at (ssr)/./app/page.js (/Users/d2gn8/Projects/test-nextjs-app/.next/server/app/page.js:173:1)
    at __webpack_require__ (/Users/d2gn8/Projects/test-nextjs-app/.next/server/webpack-runtime.js:33:42)
    at JSON.parse (<anonymous>)
null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
7 participants