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
@emotion/cache browser specific module breaks SSR #1246
Comments
The root cause of this is an optimisation done in the module bundler preconstruct that replaces |
Isnt it? Could you prepare a simple repository reproducing the issue with your setup? I could take a look then. |
Absolutely, here it is https://github.com/GU5TAF/emotion-cache-ssr-error Just |
I had the same problem, I wrote a quick monkey patch to get my build working. This script can be used post install or pre webpack. It basically unsets the "browser" mapping in the const fs = require('fs');
const { sync } = require('glob');
sync('./node_modules/@emotion/*/package.json').forEach(src => {
const package = JSON.parse(fs.readFileSync(src, 'utf-8'));
const browser = package.browser;
delete package.browser;
if (browser) {
package._browser = browser;
}
fs.writeFileSync(src, JSON.stringify(package, null, 2))
}); |
@GU5TAF it's the problem of your setup. I'm not sure how The problem (the require call) is coming from You can check out that this is not emotion-related by removing all emotion stuff from your demo - it still won't work. |
My apologies @Andarist, there was indeed a typo in my call to hydrate but apart from that I can assure you that setting the target to web and dropping emotion it'll work just fine. I created a new branch called working-example where I do just that so you can take it for a spin. |
But this is again caused by how your entry is structured. Your entry gets shipped to the browser and you include in it |
It can't work with emotion or it can't work in general? You're correct that |
The problem with the environment I was using is that it's not for the browser or for node, the script needs to be run ad-hoc via Google V8 JS engine. |
@rdadoune that sounds like a challenging environment to develop for 😅thanks for the monkey patch! @Andarist I agree that it would be even more optimal for the resultant bundle to run webpack twice, once to generate the html, storing only html files and then once more to create the browser bundle. However, this approach with a bundle that can run in both contexts isn't that uncommon and all it would take to support it completely is for emotion not to over optimize the browser bundle. The monkey patch @rdadoune provided us with fixes the issue, once run the current broken example in master just works. Surely this is desirable behaviour? I've applied it as a pre build step in a new branch called rdadoune if you're curious. |
I'm seeing the same error when using html-webpack-plugin with a custom template that does React SSR. Setting the webpack target to Conversely, and maybe this should be tracked as a separate issue - when doing SSR in node, with a mocked document object (JSDOM), @emotion/cache does not populate the cache with inserted rules, which prevents extraction of critical styles. This appears to be due to the isBrowser check resolving to true. Mocking document (and window) is necessary when using 3rd-party React components which assume they are running in a browser and access those browser globals. |
From what I know - most SSR solutions use different webpack settings for server and client builds and this is how this problem should ultimately be solved. If any particular SSR-solution doesn't differentiate this, it really should - so I would advise reporting this to those SSR-solutions as a thing they should handle. |
Thank you for this thread! This was actually a big problem for us! We wanted to use Emotion 10 together with ReactJS.NET for using React components inside Razor pages in ASP.NET. The problem here is we can't use target "node" because the V8 engine it is running can't understand it (no support for require etc). So we need to use By manually deleting all the So there are definately cases where a check should be made even if it is the browser specific module. Follow up findings: I could also make it work without the monkey patch by setting (in webpack.config.js): resolve: {
aliasFields: ["module"]
}, |
@johot great find, thanks for the follow up. |
@johot Thank you! I've spent more time than I'd like to admit on this. Not sure what it does, since the docs are not that clear about it, but for now I'm just happy it works! Thanks again! |
I am having a similar issue with
which I believe has a similar cause, since our compiled component library has the following checks throughout (from Emotion):
which leads the code down paths where things like |
@el-ethan it looks like your bundler is configured to consume browser files - so it's not a surprise that this breaks in SSR. In webpack when bundling for SSR you should configure |
I had the same problem with Gatsby in Theme UI docs. (Worked around it already.)
Is this still true? — Node 15 consumes esmodules, and the window will still be undefined there, and I think that even in previous version people and metaframeworks do configure bundlers to consume esm. |
Esm files !== browser files. The comment was referring to bundler using package.json#browser even though the target environment was node |
Oh, sorry. I missed that |
can you share the solution with an example ? |
@breno-sapucaia sorry, I wish I would have included an example of the workaround at the time, because I don't recall exactly what we did now, and I no longer have access to that code base. This example shows one thing we tried that worked, but we didn't like having to use that work around. Ultimately, we ended up going moving to styled-components for various reasons that I don't recall. Wish I could be of more help, but I'm afraid I never really came to a good understanding of the problem or a good solution. |
so how to fix it? Now in mui 5 with next i got this error |
emotion
version: 10.0.7react
version: 16.8.0Relevant code:
https://github.com/emotion-js/emotion/blob/master/packages/cache/src/index.js#L69
What you did:
Tried to SSR using static-site-generator-webpack-plugin.
What happened:
Problem description:
When @emotion/cache gets imported by webpack with
target: web
it fails due to the browser specific module not including the check fortypeof document !== 'undefined'
.As mentioned in #1113 this is a known issue and setting
target: node
is not an adequate solution.Suggested solution:
Drop the browser specific version of the module.
The text was updated successfully, but these errors were encountered: