简体   繁体   中英

Use single StylesContext when importing component from custom MUI-based library

I have an application (let's call it frontend ) importing a custom library of React components ( design-system ) that's Material UI based.

In the frontend app, I have a ShadowDOM-contained component (using react-shadow ) that I want to import a Button component from design-system to. I wrapped the whole tree inside ShadowDOM with StylesProvider that I passed a custom instance of jss to (with different injectionPoint, so the styles from inside that tree are attached not at the head of the document, but inside the ShadowDOM.

The issue I have is, that frontend uses its own copy of StylesProvider from @material-ui/styles package (I have no need to install the whole @material-ui/core as all components should be imported from design-system instead) and design-system uses its own copy of StylesProvider from @material-ui/core , resulting in a situation, where the Button is being wrapped with another StylesProvider by MUI because it doesn't detect any styles context available (and it doesn't, because MUI creates the context in global scope of StylesProvider.js file - so there are two different contexts that do the same), resulting in Button having access to default JSS instance where the insertionPoint is pointing to document head.

显示应用程序、反应组件和上下文之间关系的图表

What I'd like to achieve is, have MUI not create another styles context for every single component imported from design-system but use the one I defined in frontend - without passing it as a prop manually to every component imported. I considered adding @material-ui/styles on top of @material-ui/core to design-system and adding it to webpack's "externals" (so, theoretically, only one StylesProvider.js would be used and in turn - one context), but I was hoping there's a better solution.

TLDR:

Just adding @material-ui/styles to externals in design-system 's webpack config was enough (even if you don't add it explicitly as dependency, @material-ui/core depends on it and will use it anyway, so it works).

Long answer:

My setup is such that the "main" entrypoint in package.json of design-system points to dist/index.js (so, already bundled/minified version of the library). Without adding @material-ui/styles to "externals" in webpack config, it was bundled along the whole library, so at this point, whatever I did there would always be two copies of StylesProvider.js:

显示包含两个 @material-ui/styles 副本的图表

One solution is to mark @material-ui/styles as external - this way, it won't be bundled in dist/index.js and instead, expected to be available during runtime (and it is):

显示@material-ui/styles 如何从前端加载运行时的图表

Besides the aforementioned solution, there's also another one that worked - pointing "main" entry in package.json to "src/index.ts" instead. It made the frontend webpack treat it as a part of frontend code, instead of separate library:

在此处输入图像描述

As a bonus, it ended up with the final bundle being smaller (as common dependencies weren't duplicated). One minus of this approach was, however, that each frontend build had to also rebuild design-system , which increased the total build time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM