Material-ui: 生产版本-类名冲突

创建于 2017-09-15  ·  62评论  ·  资料来源: mui-org/material-ui


某些组件的css类名定义已重复-在我的情况下,它是为MuiIconButtonMuiModal复制的(我想从调试中得知)-检查当前行为

  • [x]我搜索了此存储库的问题,并认为这不是重复的。

预期行为

类名不应在组件之间重复。

当前行为

我的按钮样式:
classnames_conflict
该类已重复。
样式定义:
classnames_conflit_2

它正在开发模式下工作:
我的按钮样式:
development_class

并找到了定义:
mui-icon-button-dev

和从模式:
mui-modal-dev

重现步骤(针对错误)

我可以尝试为重现该问题的环境做准备,但现在我只想在这里报告它。

语境


我正在尝试在生产环境中发布我的应用程序。

您的环境

| 技术| 版本|
| -------------- | --------- |
| Material-UI | 1.0.0-beta.10 |
| 反应| 15.6.1 |
| 浏览器| 任何|
| webpack | ^ 3.3.0 |

我需要一些提示,可能是问题所在。 我在任何地方都没有使用withStyles解决方案-我使用样式化组件进行样式覆盖。

bug 🐛

最有用的评论

我遇到了冲突的类名,并在createGenerateClassName选项中添加了前缀,从而解决了该问题。

这里使用了很棒的全面文档

所有62条评论

我已经看到了解决此问题的一些问题。 它始终链接到重复的className生成器实例。 没有复制品,我无能为力。

我暂时无法解决此问题。 让我知道您是否有复制示例。

@oliviertassinari我能够重现该问题。 这里是的WebPack斌- https://www.webpackbin.com/bins/-KuO6ia3h-JDpBOJncZ3

就我而言,我有2个应用程序根目录,分别独立安装到2个不同的div。 两者都使用包裹了JssProvider的相同材料UI ThemeProvider insertionPoint从_jss_覆盖

generate_classnames_counter

基于createGenerateClassName函数,您可以使用counter具有唯一的类名

export default function createGenerateClassName(): generateClassName {
  let ruleCounter = 0;

  return (rule: Rule, sheet?: StyleSheet): string => {
    ruleCounter += 1;
    warning(
      ruleCounter < 1e10,
      [
        'Material-UI: you might have a memory leak.',
        'The ruleCounter is not supposed to grow that much.',
      ].join(''),
    );

    if (process.env.NODE_ENV === 'production') {
      return `c${ruleCounter}`;
    }

    if (sheet && sheet.options.meta) {
      return `${sheet.options.meta}-${rule.key}-${ruleCounter}`;
    }

    return `${rule.key}-${ruleCounter}`;
  };
}

我的屏幕快照证实,由于某种原因,计数器已重复。

我需要帮助。 我不知道我现在在做什么错。

@darkowic您需要在不同的反应树之间共享jss实例。 这样的变化应该对您有利。

@oliviertassinari我想我正在使用自定义ThemeProvider

  <JssProvider registry={context.sheetsRegistry} jss={context.jss}>
    <MuiThemeProvider
      theme={context.theme}
      sheetManage={context.sheetsManager}
      {...props}
    />
  </JssProvider>

我用这个包装我的每一个反应树。

这个问题应该被解决。

当然,让我们总结一下到目前为止的知识。 一旦使用多个反应渲染树,就会出现此问题。 jss提供程序将创建两个类名生成器,每棵树一个。 因此,我们最终遇到了类名冲突。
@kof我们是否应该将JssProvider从react-jss扩展为接受类名生成器?

客户端应用程序的替代方法:您可以创建自己的createGenerateClassName并将ruleCounter移动到包装函数之外

import warning from 'warning';

// Returns a function which generates unique class names based on counters.
// When new generator function is created, rule counter is reset.
// We need to reset the rule counter for SSR for each request.
//
// It's an improved version of
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js
//
// Copied from material-ui due to issue https://github.com/callemall/material-ui/issues/8223

// This counter is moved outside from `createGenerateClassName` to solve the issue
let ruleCounter = 0;

export default function createGenerateClassName() {
  return (rule, sheet) => {
    ruleCounter += 1;
    warning(
      ruleCounter < 1e10,
      [
        'Material-UI: you might have a memory leak.',
        'The ruleCounter is not supposed to grow that much.'
      ].join('')
    );

    if (process.env.NODE_ENV === 'production') {
      return `c${ruleCounter}`;
    }

    if (sheet && sheet.options.meta) {
      return `${sheet.options.meta}-${rule.key}-${ruleCounter}`;
    }

    return `${rule.key}-${ruleCounter}`;
  };
}

不错,我们在服务器上有这样一个用例,我已经计划在文档中使用大胆​​的提示,请参阅#5

但是现在您实际上找到了支持2个并行运行的提供程序的充分理由。

我们需要研究是否存在强烈需要多个并行JssProviders的用例。 如果有的话,我们需要考虑一些支持它的事情。

@kof您刚刚在客户端发现了多个并行JssProviders的用例。 而且我认为所提出的解决方案很容易实现:)。

将ruleCounter移动到包装器函数之外

这意味着在服务器上,ruleCounter将永远不会重置。 我们不能那样做。

在服务器端,JssProviders绝对需要支持对反应树的并发异步呈现(非常需要)。 但是当前的实现使其已经受支持:)

@darkowic提出了一种无法访问基础堆栈的解决方法。 我们的确是。 我们可以通过这种额外的灵活性来做得更好:接受类名生成器实例。

同样,对相同端点的请求应始终以相同的类名响应。

@kof我们应该从react-jss扩展JssProvider来接受类名生成器吗?

  1. 是的,一种可能的方法是允许JssProvider接受这样的类名生成器:

import {createGenerateClassName} from 'react-jss'

const generateClassName = createGenerateClassName()

<JssProvider generateClassName={generateClassName}>
  <App1 />
</JssProvider>

<JssProvider generateClassName={generateClassName}>
  <App2 />
</JssProvider>

  1. 另一个可能的选择是提供一些前缀,例如应用程序名称。 如果我们假设我们没有不可预测的应用程序数量,那么这可能会起作用。

<JssProvider classNamePrefix="app-1">
  <App1 />
</JssProvider>

<JssProvider classNamePrefix="app-2">
  <App2 />
</JssProvider>

优点1:

  • 用户不需要提供前缀

优点2:

  • 用户可以在DOM类名称中包含一些有意义的内容,以在开发过程中识别应用程序
  • 用户对前缀有更多控制权。
  • 具有不冲突的前缀相对容易。 您只需要几个子树,命名就已经足够容易了,或者您可以为这些名称添加自己的数字前缀,并在每次请求时重置它们。

实际上,同时拥有两个道具classNamePrefixgenerateClassName是有意义的。 首先是调试,其次是类名的自动唯一性。

我已经通过https://github.com/facebookincubator/create-react-app/issues/3173 (以及链接的简化测试用例)遇到了这个问题。

就我而言,一个依赖于UI的应用程序中。 在开发中,这很好用,但是在生产中,由于类名冲突而导致布局被破坏。

我不确定这是否符合“多重反应渲染树”的要求,并在createGenerateClassName()之前移动var ruleCounter = 0; createGenerateClassName() _did not_解决此问题,但是注释了以下内容,_did_工作:

https://github.com/callemall/material-ui/blob/2361339fd6df9bfbb85ed2ee4da9d42ee6fee71c/src/styles/createGenerateClassName.js#L26 -L28

抱歉,我在打开#7855时无法提供更多信息。
注释基本上涵盖了我在运行生产版本时遇到的问题。

解决这个问题的方法?

创建了一个应该在react-jss https://github.com/cssinjs/react-jss/pull/155中修复的PR

因此,让我们总结一下。

  • @darkowic的问题的根本原因在这里描述: https@kof的PR:cssinjs / react-jss#将得到解决。 155,并且将添加新的警告以防止将来出现这种情况:#8341。

  • @tlvince的问题症状相同,但根本原因不同。 您正在使用单个反应渲染树。 可以将其链接到已安装的重复Material-UI版本。 检查您的警告,如果您能确切了解发生了什么,请打开另一个问题。

  • @Robophil的问题太含糊,无法采取措施。

我遇到了冲突的类名,并在createGenerateClassName选项中添加了前缀,从而解决了该问题。

这里使用了很棒的全面文档

@oliviertassinari感谢您的总结!

在单个反应渲染树中,此问题很可能是由构建中的不同Material-ui版本引起的。 确保检查您的依赖树并检查正在使用的Material-ui版本。

yarn list | grep material-ui

我的webpack配置如下

module.exports = {
    entry: {
        FirstComp: path.join(paths.JS, '/components/FirstComponent/MyFirstComp.js'),
        SecondComp: path.join(paths.JS, '/components/SecondComponent/MySecondComp.js'),
    },
}

我有这两个组件,以及使用splitChunks选项构建的公共组件。
我使用JSSProvider将默认导出的组件包装在MyFirstComp和MySecondComp中。
我应该如何在通用组件周围使用JSSProvider?

@Sewdn我也认为这可能是由不同的Material-ui版本引起的。 昨天,当我开始迁移到钩子和makeStyles从@ material-ui / styles从3.0.0-alpha.1创建的
我也在使用3.6.0的“ @ material-ui / core”

突然,我的应用程序类和material-ui类都以jss1开始,并开始并行计数。 那会混合一切。 我的jss5标头也使用了MuiListItem的jss5样式。

在遵循此解决方案后, @ iamhosseindhvhttps://github.com/mui-org/material-ui/issues/8223#issuecomment -412349569 MUI组件的类以ac为前缀,从而解决了问题。

@christiaanwesterbeek您是否正确使用了安装步骤? 我们使用依赖注入。 install()调用需要在所有高阶组件导入之前运行。

@oliviertassinari恐怕我不知道您指的是哪一步。 另外,我也不知道install()是什么部分以及需要在哪里调用。 我很高兴了解更多有关它的信息,但是我需要知道它的记录位置。

@christiaanwesterbeek我指的是https://material-ui.com/css-in-js/basics/#migration -for -material-ui-core-users。

@oliviertassinari似乎应该在每个组件的文件中调用install() 也许我们需要更清晰的描述。

也许我错了,安装无法解决冲突。
To switch from the default style implementation to this newest version, you need to execute the following code before importing any Material-UI's components:

import { install } from '@material-ui/styles';

install();

@oliviertassinari如何安装before importing any Material-UI's components
导入始终由babel和tsc静态处理

@zheeeng ES模块导入被提升到模块顶部,并按照定义的顺序同步解析。 我们在Material-UI文档中也遇到了同样的问题。 解决方案是将所有内容打包到bootstrap.js模块中,然后先导入:
https://github.com/mui-org/material-ui/blob/cb30b43e9c6cd49f9b16536a125456f5ea3a85c5/docs/src/modules/components/bootstrap.js#L1 -L13
如果问题仍然存在,请继续讨论其他问题。

@oliviertassinari我将导入顺序从

// entry index.js
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import CssBaseline from '@material-ui/core/CssBaseline'
import { install } from '@material-ui/styles'

import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { install } from '@material-ui/styles'
import CssBaseline from '@material-ui/core/CssBaseline'

该代码报告错误Cannot read property 'text' of undefined 。 通过检查主题对象,它为空。
如果我切换回导入顺序,则此部分工作正常。

const useStyles = makeStyles(
  (theme: Theme) => ({
    root: {
      flexShrink: 0,
      color: theme.palette.text.secondary,
    },
  }),
)

当我用<StylesProvider>包装整个应用程序时,也会发生同样的问题

zh

代码报告错误Cannot read property 'text' of undefined 。 通过检查主题对象,它为空。

我有同样的问题。 通过将“ @ material-ui / core”升级到3.6.0或将@ material-ui / styles升级到3.0.0-alpha.1,可以解决此问题。 我忘记了最好两个都做。

但是,传递给makeStyles的函数将接收的确切主题不是我使用createMuiTheme创建的主题。 相反,它具有默认主题。 我最终要做的是不依赖任何会通过的主题。 相反,我在需要样式的每个文件中导入了主题。

@christiaanwesterbeek我安装了@material-ui/[email protected]@material-ui/styles/.0.0-alpha.2 ,但仍然有此问题。

这似乎与当前问题(8223)无关。 但是无论如何这里都去了。 只是导入主题,而不依赖于将其传递给传递给makeStyles的函数。 这样就完成了。

有人可以确认v3.7.0(https://github.com/mui-org/material-ui/releases/tag/v3.7.0)是否仍然需要安装步骤吗?

@christiaanwesterbeek是的,这是必需的。 我们将删除Material-UI v4中的安装步骤。

@oliviertassinari嘿,我在最新的v3.9.0中遇到此问题,并且我没有使用@ material-ui / styles,我仍然在使用core withStyles core我有两个问题。

  1. 我应该现在迁移到mui / styes还是等待v4发行。 (大型应用)
  2. 使用此解决方法https://github.com/mui-org/material-ui/issues/8223#issuecomment -331081785是处理此问题的正确方法吗? 它最终在构建过程中确实运行良好,但似乎无法理解为什么它首先发生。

谢谢

我在最新的v3.9.0中遇到了这个问题

@ w3nda这太笼统了,有百万种不同的原因导致此问题发生。

我应该现在迁移到mui / styes还是等待v4发行。 (大型应用)

我们可能会还原类名哈希逻辑。 尽管它极大地提高了服务器的性能,但在客户端上却付出了可观的代价。 也许我们会提供一个标记来启用它。 因此,我认为最好的选择是解决核心问题。 您是否尝试过此页面https://material-ui.com/guides/server-rendering/#troubleshooting

@oliviertassinari感谢您的快速响应,我真的不知道如何调试问题,您提到的链接与我无关,因为我将其作为静态站点使用。
我引用的评论对我有帮助,难道不应该说明我这个问题的起因吗?

@ w3nda静态网站具有相同的问题。 您需要生成HTML,因此它将使用服务器端渲染API。 如果索引计数器在两个页面之间泄漏,则类名将不正确。 好吧,我认为较慢的类名生成器与调试此类问题(以及调试频率)的痛苦相比是一个不错的折衷。 因此,是的,您可以升级到@material-ui/styles ,这是一个简单的逃生舱口。

我只是有一个类似的问题,这是一个旧的Material-ui导入,位于我们的一个库中。 它在开发模式下运行良好,但在生产中被破坏了。 我很确定这以前是可行的,即使这种情况显然是我们的错,我也不知道是否可以在这种情况下发出警告。
我更新了版本以使其在项目之间匹配,并且一切正常。

嗨,我只是在网站上使用单一输入,按钮和表单的材料,而在此评论之后我不得不使用<JssProvider /> https://github.com/mui-org/material-ui/issues / 8223#issuecomment -331412432

需要这个jss提供者很烦人,是否有我们可以做的另一种修复不会增加最终构建大小的修复程序?

@kopax您将使用JssProvider做什么?

@oliviertassinari ,您好,在production访问其他路线之前(我们使用react-router):

image

访问路线后在production或在development

image

表单(奇怪的盒子阴影)会发生类似的情况,我们需要访问另一页才能获得正确的CSS,这仅在生产中发生:

image

如果我们添加JssProvider则两个问题都已解决。 (固定:我们有相同的CSS productiondevelopment

我不知道。 我无法提供所提供的信息。

一切都坏了。 我在生产中观察到错误的订单jssXX类,结果是样式错误。 刷新页面后发生。

找不到原因。

@oliviertassinari也许我们正在使用的[email protected]使用的那些版本号将帮助您告诉我们发生了什么:

        "@material-ui/core": "^1.4.0",
        "@material-ui/icons": "^1.0.0",
        "material-ui-chip-input": "1.0.0-beta.6 - 1.0.0-beta.8",

您能否确定Material-UI仅捆绑一次? 同时使用两个版本可以创建相同的错误行为。

好。 这是可能的。 我们正在使用建议版本为〜1.5的react-admin

我通过添加JssProvider解决了生产中的错误。 现在,我可以正常刷新页面了。

import React from "react";
import { Admin, Resource } from "react-admin";
import JssProvider from "react-jss/lib/JssProvider";

const App = () => (
  <JssProvider>
    <Admin dataProvider={dataProvider}>
      <Resource name="trip" list={RequestsList} className="resourceItem" />
    </Admin>
  </JssProvider>
);

export default App;

@andrewkslv这正是我们要避免的方法,我们宁愿在没有JssProvider情况下使用它,因为我们仅使用@ material-ui中的一个InputButton组件,相反,我们更喜欢将其余的ui用于react-admin。

我刚刚检查了@oliviertassinari ,但确实遇到了一些依赖关系问题。 我已修复它,但仍然出现以下npm ls @material-ui/core

├─┬ @bootstrap-styled/[email protected]
│ └── @material-ui/[email protected] 
├── @material-ui/[email protected] 
└─┬ [email protected]
  └── @material-ui/[email protected] 

完成后:

rm -rf node_modules/@bootstrap-styled/ra-ui/node_modules/@material-ui/
rm -rf node_modules/ra-ui-materialui/node_modules/@material-ui/
npm ls @material-ui/core
├─┬ @bootstrap-styled/[email protected]
│ └── UNMET DEPENDENCY @material-ui/[email protected] 
├── @material-ui/[email protected] 
└─┬ [email protected]
  └── UNMET DEPENDENCY @material-ui/[email protected] 

然后,现在它可以工作了(生产中没有CSS问题)。 我想这不是我想要的...

相关项目@ material-ui依赖项:

知道该怎么办吗?

@kopax如果没有我可以调试的东西很难说。 我很高兴听到它现在正在工作。

我注意到您在Material-UI中使用了样式化的组件。 如果您有时间,我想谈谈有关Gitter的集成。

可行的解决方案不是自然的。 这意味着它涉及无法使用npm运行的任务。 我不会使用它,我只是作为提示。

我们星期一有机会,我会加入mui gitter频道。

@kopax ,您设法找到解决方案了吗?

还没有。 并非没有提供者。 @oliviertassinari我很烦。

@andrewkslv您的解决方案确实对我有用。 我还使用react-admin和AWS Amplify。 每当我将我的react应用程序部署到S3存储桶时,样式都将被破坏,您的解决方案确实救了我。

这里同样的问题。 为什么添加JssProvider有帮助?

我在v4中添加了一个警告,以警告使用重复的样式实例时:#15422。

我不知道。 当他们在框架中实现新版本的材料ui时,我在react-admin提出了这个问题,但忽略了它。

https://github.com/marmelab/react-admin/pull/3102#issuecomment -484228320

在哪里可以找到有关生产版本-类名冲突的解决方案#8223?

谢谢,

@oliviertassinari即使我按照所有说明进行操作,也再次

https://stackoverflow.com/questions/58938080/jssprovider-not-generating-class-prefix-with-classnameprefix

我正在使用以下版本的软件包。

“ @ material-ui / core”:“ ^ 4.6.1”,
“ @ material-ui / icons”:“ ^ 4.5.1”,
“反应”:“ ^ 16.12.0”,
“ react-dom”:“ ^ 16.12.0”,
“ react-jss”:“ ^ 10.0.0”,
“反应脚本”:“ 3.2.0”

更新:问题已解决。 抱歉,没有彻底阅读文档。 文档的这一部分解决了我的问题。

https://material-ui.com/styles/api/#creategenerateclassname -options-class-name-generator

但是不知何故,对其他所有人都有效的JSSProvider解决方案却对我不起作用。 无论如何,谢谢:)

谢谢@KannugoPrithvi ,这是一个很好的解决方案! https://material-ui.com/styles/api/#creategenerateclassname -options-class-name-generator

此页面是否有帮助?
0 / 5 - 0 等级