create-react-app getCSSModuleLocalIdent在使用模块化CSS类名时,在querySelector中可能会导致意外行为,

cbwuti44  于 5个月前  发布在  React
关注(0)|答案(7)|浏览(71)

描述bug

querySelector中使用css-loader选项中的getLocalIdent: getCSSModuleLocalIdent可能会导致在使用模块化CSS类名时出现意外行为。

你是否尝试恢复依赖关系?

是的

你在用户指南中搜索了哪些术语?

getCSSModuleLocalIdent

环境

webpack

重现步骤

(请在这里写下你的步骤:)

  1. 在readme中使用完全相同的webpack配置。
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');

// In your webpack config:
// ...
module: {
  rules: [
    {
      test: /\.module\.css$/,
      use: [
        require.resolve('style-loader'),
        {
          loader: require.resolve('css-loader'),
          options: {
            importLoaders: 1,
            modules: {
              getLocalIdent: getCSSModuleLocalIdent,
            },
          },
        },
        {
          loader: require.resolve('postcss-loader'),
          options: postCSSLoaderOptions,
        },
      ],
    },
  ];
}
  1. 在app中编写以下代码。
import styles from '../someStyle.css'

document.querySelector('.' + styles.foo);

function Component() { 
  return <div className={styles.foo} />
}
  1. 希望运气好。在某些罕见的情况下,styles.foo可能包含字符+,而querySelector将抛出错误或返回null。

预期行为

getCSSModuleLocalIdent的返回值不包括+

实际行为

getCSSModuleLocalIdent的返回值可能包含+

可复现的演示

查看我的forks tychenjiajun@28d10e6
在测试用例中,如果输入的类名为'class1020',输出的类名将为file_class1020__V+98r。在querySelector中使用此类名会导致错误,参见https://codepen.io/chankcccc/pen/MWEmxpZ

brjng4g3

brjng4g31#

解:我们最近也遇到了这个问题。看起来可以通过使用$x^{CSS.escape()}$来解决:

$x^{

import styles from '../someStyle.css'

-document.querySelector('.' + styles.foo);
+document.querySelector('.' + CSS.escape(styles.foo));

 function Component() { 
   return <div className={styles.foo} />
 }

}=x^{(1+a)(1-b)x}$

2w3rbyxf

2w3rbyxf2#

我们最近也遇到了这个问题。看起来你可以通过使用 CSS.escape() 来解决:

import styles from '../someStyle.css'

-document.querySelector('.' + styles.foo);
+document.querySelector('.' + CSS.escape(styles.foo));

 function Component() { 
   return <div className={styles.foo} />
 }

好主意。我们的解决方案是复制原始的 getLocalIndent 方法,并将哈希类型从 base64 更改为 base62

function getLocalIdent(context, localIdentName, localName, options) {
    // Use the filename or folder name, based on some uses the index.js / index.module.(css|scss|sass) project style
    const fileNameOrFolder = /index\.module\.(css|scss|sass)$/.test(context.resourcePath) ? '[folder]' : '[name]';
    // Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique.
    const hash = loaderUtils.getHashDigest(path.posix.relative(context.rootContext, context.resourcePath) + localName, 'md5', 'base62', 5);
    // Use loaderUtils to find the file or folder name
    const className = loaderUtils.interpolateName(context, `${fileNameOrFolder}_${localName}__${hash}`, options);
    // Remove the .module that appears in every classname when based on the file and replace all "." with "_".
    return className.replace('.module_', '_').replace(/\./g, '_');
}
// css-loader config
modules: {
    getLocalIdent,
}

也许我应该为此提交一个 PR。

kyxcudwk

kyxcudwk3#

我最近也遇到了这个问题,生成的类有 / ,但浏览器没有正确地将它们应用到元素上。
与 @tychenjiajun 类似,我修改了 getLocalIdent 函数,但我没有使用 base62 ,而是根据 https://datatracker.ietf.org/doc/html/rfc4648#section-5 将 base64 的第62个和第63个字符替换为它们的 url-safe 对应字符。
这是我的代码:

// Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique.
      const hash = loaderUtils
        .getHashDigest(
          path.posix.relative(context.rootContext, context.resourcePath) +
            localName,
          "md5",
          "base64",
          5
        )
        // replace base64 characters with their url-safe counterparts
        // https://datatracker.ietf.org/doc/html/rfc4648#section-5
        .replace(/\+/g, "-")
        .replace(/\//g, "_");
5uzkadbs

5uzkadbs4#

我也遇到了这个问题。我的解决方案是在getHashDigest中将digestType参数的值从"base64"更改为"base64url"。base64url是在nodejs 14中引入的。由于我刚刚提出了关于css模块哈希冲突的#12013问题,我可以在那里解决这个问题。顺便问一下,为什么这个问题现在才出现呢?

6rvt4ljy

6rvt4ljy5#

好的,我不知道base64url存在。由于我的项目一直使用webpack 4,我不得不也使用react-scripts v4。注意到从4.0.1升级到4.0.2会导致计算不同的哈希值。

9rnv2umw

9rnv2umw7#

我也遇到了这个问题,使用 CSS.escape() 来解决,等待 cra 修复。

相关问题