简体   繁体   English

从基于 MUI 的自定义库导入组件时使用单个 StylesContext

[英]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.我有一个应用程序(我们称之为frontend )导入基于 Material UI 的自定义 React 组件库( design-system )。

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.frontend应用程序中,我有一个包含 ShadowDOM 的组件(使用react-shadow ),我想将 Button 组件从design-system导入到该组件。 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.我使用 StylesProvider 将整个树包裹在 ShadowDOM 中,我将自定义的jss实例传递给(使用不同的 injectionPoint,因此该树内部的 styles 不是附加在文档的开头,而是附加在 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.我遇到的问题是, frontend使用来自@material-ui/styles package 的自己的 StylesProvider 副本(我不需要安装整个@material-ui/core ,因为所有组件都应该从design-system导入)和design-system使用自己的来自@material-ui/core的 StylesProvider 副本,从而导致 Button 被 MUI 与另一个 StylesProvider 包装,因为它没有检测到任何可用的 styles 上下文(它没有,因为 MUI 在 StylesProvider.js 文件的全局 scope 中创建上下文 - 所以有两个不同的上下文执行相同的操作),导致 Button 可以访问 insertPoint 指向文档头的默认 JSS 实例。

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

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.我想要实现的是,让 MUI 不为从design-system导入的每个组件创建另一个 styles 上下文,而是使用我在frontend定义的那个 - 而不将其作为道具手动传递给每个导入的组件。 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.我考虑在@material-ui/core之上添加@material-ui/stylesdesign-system并将其添加到 webpack 的“外部”(因此,理论上,只会使用一个 StylesProvider.js,而反过来 - 一个上下文) ,但我希望有更好的解决方案。

TLDR: 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).只需将@material-ui/styles添加到design-system的 webpack 配置中的 externals 就足够了(即使您没有将它显式添加为依赖项, @material-ui/core也依赖它并且无论如何都会使用它,所以它作品)。

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).我的设置是这样的,即design-system的 package.json 中的“主要”入口点指向dist/index.js (因此,已经捆绑/缩小版本的库)。 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:在 webpack 配置中没有将@material-ui/styles添加到“externals”中,它被捆绑在整个库中,所以在这一点上,无论我做什么,总会有两个 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标记为外部 - 这样,它不会捆绑在 dist/index.js 中,而是预计在运行时可用(并且确实如此):

显示@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.除了上述解决方案之外,还有另一个有效的解决方案 - 将 package.json 中的“主”条目指向“src/index.ts”。 It made the frontend webpack treat it as a part of frontend code, instead of separate library:它使frontend webpack 将其视为frontend代码的一部分,而不是单独的库:

在此处输入图像描述

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.然而,这种方法的一个缺点是,每个frontend构建还必须重新构建design-system ,这增加了总构建时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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