问题 :global() css-module 选择器在 NextJS 中不是纯的

Issue with :global() css-module selectors not being pure in NextJS

所以我正在将一个应用程序从 CRA 迁移到 NextJS,我遇到了一些组件和页面的 .module.scss 文件错误:

Syntax error: Selector ":global(.label-primary)" is not pure (pure selectors must contain at least one local class or id)

我在所有 :global 和 :local css-模块选择器上都遇到了这个错误。根据我搜索的内容,我可以通过将选择器包装在 class 中并同时编辑 jsx 来解决此问题。但这不会破坏它的目的吗? 这在应用程序的 CRA 版本而不是 NextJS 上如何工作?

编辑: 我对此的一种解决方案是将 :global() 选择器移动到 _app.js 中导入的全局 css 文件,但我的问题是我们有什么办法可以使用这些样式就像他们现在一样 ( :global(...) )?

不,除了覆盖 webpack 配置本身之外,目前还没有任何解决方案。它在 CRA 工作,因为他们可能有 mode: local, while Next.js has pure.


我还没有尝试覆盖 css-loader webpack 配置,所以我只是建议一个解决方法。因为,你正在使用 SCSS,你可以像这样包装你的 pseudo-global [1] 样式:

.root :global {
  .foo {
    color: red;
  }
}

现在将您的 component/page 包裹在 div 中,并在该元素上将 class 设置为 styles.root。然后,在所有的子元素上你可以直接设置 className="foo".

import styles from "../styles/index.module.scss";

const IndexPage = () => (
  <div className={styles.root}>
    <div className="foo">This text should be red!</div>
  </div>
);

export default IndexPage;

注意,此方法后需要考虑特异性问题,而且不能直接对动画起作用,需要将keyframes分开,然后全局化。

Demo Sandbox


[1]:此方法不会使样式真正成为全局样式,因为样式仍然在范围内。 class foo 仅在某些父级 styles.root 为 class 时才有效。仅当您不打算从其他组件使用 :global(.selector) 并且使用它们只是因为您想在没有样式对象的情况下使用 JS 操作 class 名称时,这是更可取的。

如果您希望它们真正成为全球性的,请在 useEffect 挂钩中将 styles.root 添加到 document.documentElement,如下所示:

import { useEffect } from "react";
import styles from "../styles/index.module.scss";

const IndexPage = () => {
  useEffect(() => {
    document.documentElement.classList.add(styles.root);
    return () => {
      document.documentElement.classList.remove(styles.root);
    };
  }, []);

  return (
    <div className="foo">
      This text should be red, even if you put it in another component until the
      page is same. If you want it across pages inject it in _app or _document.
    </div>
  );
};

export default IndexPage;

Demo Sandbox

PS:在_app_document中将class注入html完全相同使用 global stylesheet,因为您可能有多页应用程序,那么只有特定页面上的组件的 CSS 会被请求,因为已完成自动 CSS 代码拆分通过 Next.js。如果情况并非如此,并且您的所有页面都共享相同的 CSS,则无需将事情复杂化,只需使用在 _app.

中导入样式的常规方法即可