-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Custom CacheProvider does not pick up styles from bundled components #1386
Comments
Can you reproduce this when installing LibraryComponent? I mean - when not using npm link? I think the problem is that each project - a library and your app - has its own |
Yes, I can reproduce this when I'm installing the package instead of using link. Edit: After further testing, I can get this to work as expected in my test repo if I'm not using yarn link. I'm still seeing issues with other bundles but I'm guessing that's due to a different configuration issue causing the same duplicate context situation. |
@Andarist could we put the context into some global space to avoid this issue? I know is not going to be nice, but maybe just for dev builds we could put it into |
That has to be it. You can try to find the culprits and resolve your dependency ranges in such a way that u would have a single version of emotion@10 in your node_modules. If you are using webpack I would advise aliasing it (and other shared react libs and react itself) to resolved paths. I'm doing this it with something like this: const path = require('path')
const fs = require('fs')
function findPkgRoot(directory) {
const configPath = path.join(directory, 'package.json')
if (fs.existsSync(configPath)) {
return directory
}
return findPkgRoot(path.join(directory, '..'))
}
const dependencies = Object.keys(require(path.join(findPkgRoot(__dirname), 'package.json')).dependencies)
const forcedNodeModules = dependencies..reduce((acc, dep) => {
acc[dep] = findPkgRoot(require.resolve(dep))
return acc
}, {})
module.exports = {
// webpack config
// ...
resolve: {
// ...
alias: forcedNodeModules
}
}
IMHO that wouldn't solve the issue completely and could introduce some bizarre bugs into somebody's setup. We can't assume how people differentiate their dev & prod builds, so any attempt to fix the dev one might just hide the issue and cause breakage accidentally in prod. We could use this to produce a dev only warning though, that we have detected multiple instances of our package being loaded. Keep in mind that the problem here is not unique to emotion itself, anything that relies on same references can break - i.e. |
A warning would be great! |
There is nothing that we can do to fix this - it's just how things work in general (the issue is not exclusive to emotion). We could introduce some kind of a warning - which is tracked here #1470 , but we need to think about all pros and cons of this before implementing this. |
This works for JSS btw, so I'm not convinced this issue is how things work in general. I couldn't tell you what the solution is but they made it work. Basically I have some code in the shadow dom in which I am using components made in Material UI (which uses JSS behind the scenes) that are from an external package and I am able to specify the location where those styles should be inserted. Not only does it insert all styles that are created within the shadow dom but also the ones that are imported via the package. Unfortunately the solution that allows me to specify where to add the emotion styles that are created within the shadow dom does not also include the emotion styles that are imported via the package. import root from 'react-shadow';
import { jssPreset, StylesProvider as MuiStylesProvider, MuiThemeProvider } from '@material-ui/core/styles';
import { ThemeProvider as EmotionThemeProvider } from 'emotion-theming';
import { create } from 'jss';
import React, { useState } from 'react';
import { CacheProvider as EmotionCacheProvider } from '@emotion/core';
import createCache from '@emotion/cache';
import { Theme, Components } from 'design-library';
// Define custom location to insert JSS styles (instead of document head)
// From: https://stackoverflow.com/a/57221293/83916
// Define custom location to insert Emotion styles (instead of document head)
// From: https://emotion.sh/docs/cache-provider
const ShadowDomContainer = ({ children }) => {
const [jss, setJss] = useState(null);
const [emotionCache, setEmotionCache] = useState(null);
function createJssStyles(headRef) {
if (headRef && !jss) {
const createdJssWithRef = create({ ...jssPreset(), insertionPoint: headRef });
setJss(createdJssWithRef);
}
}
function setEmotionStyles(emotionRef) {
if (emotionRef && !emotionCache) {
const createdEmotionWithRef = createCache({
container: emotionRef,
});
setEmotionCache(createdEmotionWithRef);
}
}
function setShadowHeadRef(headRef) {
createJssStyles(headRef);
setEmotionStyles(headRef);
}
return (
<root.div>
<head ref={setShadowHeadRef} />
{jss && emotionCache && (
<MuiThemeProvider theme={Theme}>
<EmotionThemeProvider theme={Theme}>
<EmotionCacheProvider value={emotionCache}>
<MuiStylesProvider jss={jss}>
<Components.ScopedCssBaseline>{children}</Components.ScopedCssBaseline>
</MuiStylesProvider>
</EmotionCacheProvider>
</EmotionThemeProvider>
</MuiThemeProvider>
)}
</root.div>
);
};
export default ShadowDomContainer; |
The "double context" problem is literally the only way this can break. I would encourage you to check your node_modules for multiple |
@Andarist If that is the case, how would I solve the multiple packages issue? |
I wonder, could someone help me, i'm finding the same problem. I have a design system lib which uses Im consuming said design system from this repo: Im trying to have the |
@glomotion your problem is very different from the issue described here. You can use a hack like this: https://codesandbox.io/s/twilight-glade-0tr4l?file=/src/App.js . But remember that this is a hack and this won't work correctly with things like SSR. |
Oh that is perfect! In this case a Hack is fine, its really only needed to work around an issue with cypress component testing. Thank you @Andarist! |
Hi @Andarist. we stumbled on a very similar issue. Our problem was that we had different modules. Our component lib had commonjs and our frontend esm. |
Current behavior:
A custom
CacheProvider
does not pick up styles from components imported from bundled JS. Styles for these components are prefixed with the defaultcss
key and are injected into the document head, not the location specified in the cache.To reproduce:
Repo with example: https://github.com/ChrisMccollister-minted/emotion-cache-provider-test
Expected behavior:
For the code shown below, I would expect the styles used by
LibraryComponent
to be prefixed withbbb
and injected into the div holding thet2Ref
.Looking at the resulting document, I see that the styles for
LocalComponent
are correctly prefixed withaaa
and injected into the div holding thet1Ref
. The styles used byLibraryComponent
however, are prefixed with the defaultcss
prefix and injected into the document head, as if no customCacheProvider
was being used.If this is the intended behavior, then I would expect the docs to mention that
CacheProvider
does not work with bundled components.Environment information:
react
version:16.8.6
@emotion/core
version:10.0.10
@emotion/cache
version:10.0.9
The text was updated successfully, but these errors were encountered: