CSS class 名称中的破折号与 Gatsby v3 (css-loader v5)

Dashes in CSS class names with Gatsby v3 (css-loader v5)

在 Gatsby v2 中,您可以通过将以下代码添加到 gatsby-node.js 来启用此语法 className={styles["block__element--modifier"]}:

const process_rule = rule => {
  if (rule.oneOf) {
    return {
      ...rule,
      oneOf: rule.oneOf.map(process_rule),
    };
  }

  if (Array.isArray(rule.use)) {
    return {
      ...rule,
      use: rule.use.map(use => {
        const css_loader_regex = /\/css-loader\//;

        if (!css_loader_regex.test(use.loader)) {
          return use;
        }

        return {
          ...use,
          options: {
            ...use.options,
            camelCase: false,
          },
        };
      }),
    };
  }

  return rule;
};

exports.onCreateWebpackConfig = ({ getConfig, actions }) => {
  const config = getConfig();

  const new_config = {
    ...config,
    module: {
      ...config.module,
      rules: config.module.rules.map(process_rule),
    },
  };
  actions.replaceWebpackConfig(new_config);
};

但是 Gatsby v3 使用的 css-loader v5 不再接受选项中的 camelCase: false 字段。相反,它具有字段 exportLocalsConvention,可以取值 asIs,但是当启用 namedExport 时,编译器会抛出错误:

The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "camelCaseOnly" or "dashesOnly".

我试过:

options: {
  ...use.options,
  modules: {
    ...use.options.modules,
    auto: true,
    exportLocalsConvention: "asIs",
    exportOnlyLocals: false,
    namedExport: false,
  },
},

但这不会使 CSS class 名称在 JSX 中可访问并给出警告:

warn Attempted import error: 'block' is not exported from './styles.module.css' (imported as 'styles').

看起来 namedExport 必须设置为 true 才能在 JSX 中访问已编译的 class 名称,但是 css-loader 将只接受 camelCaseOnlydashesOnly 对于 exportLocalsConvention.

我不确定如何在 v3 中启用与 Gatsby v2 相同的功能。我希望能够继续使用 className={styles["block__element--modifier"]} 语法,因为它使识别 CSS class 变得容易,而且还能保持 CSS 和 JSX 之间的一致性(我也是我宁愿不必重写我的一堆代码)。

我正在导入类似 Gatsby v2 到 v3 迁移指南的样式:

import * as styles from "./styles.module.css"

我也尝试过以旧方式导入它们 (import styles from "./styles.module.css"),但不幸的是没有任何区别。

原来问题出在 css-loader 选项中的 esModule 字段。它是 enabled by default 和:

generates JS modules that use the ES modules syntax. There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.

据我了解,这会将 CSS class 名称转换为 JS 变量,它不能有连字符,因此它们被更改为驼峰式。

因此,要在 CSS class 名称中保留连字符并使用语法 className={styles["block__element--modifier"]),我们需要使用以下内容覆盖 css-loader 选项:

options: {
  ...use.options,
  esModule: false,
  modules: {
    exportLocalsConvention: "asIs",
    namedExport: false,
  },
},

然而,当我通过 gatsby-node.js 将这些选项直接传递给 webpack 配置时,我仍然 运行 遇到构建错误,但是我找到了使用 Gatsby 插件 gatsby-plugin-postcss 的解决方法(只有 129B 缩小了+ gzipped) 在 gatsby-config.js:

中使用这些选项
{
  resolve: "gatsby-plugin-postcss",
  options: {
    cssLoaderOptions: {
      esModule: false,
      modules: {
        exportLocalsConvention: "asIs",
        namedExport: false,
      },
    },
  },
},

这将产生警告:

warn You did not set any plugins, parser, or stringifier. Right now, PostCSS does nothing. Pick plugins for your case on https://www.postcss.parts/ and use them in postcss.config.js.

但这只是一个警告,不会引起任何其他问题!

使用此实现,您将需要使用 Gatsby v2 方法导入样式:

import styles from "./styles.module.css";

请记住,这会阻止 Gatbsy v3 / css-loader v5.

的默认 tree shaking 行为

事实证明,这实际上已包含在迁移指南中 here。但是,它并不表示要使用 exportLocalsConvention: "asIs",根据我的测试,这是必需的。