You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS中如何避免className被哈希化,新增不随部署变更的固定类名?

解决方案

方案1:直接拼接固定类名(最易用,无额外配置)

直接在写className属性时,手动拼接自定义固定类名和CSS Modules导出的哈希类名即可实现你要的效果,代码示例如下:

// Button.jsx
import styles from './Button.module.css'

export default function Button() {
  return (
    // 用模板字符串拼接两类类名
    <div className={`ButtonTest ${styles.test}`}>
      按钮内容
    </div>
  )
}

渲染后的最终效果就和你预期的完全一致:<div class="ButtonTest Button_test__1iM5u">。
如果你的项目已经引入了classnames工具库处理多类名逻辑,写法会更简洁:

import cx from 'classnames'
import styles from './Button.module.css'

<div className={cx('ButtonTest', styles.test)}>按钮内容</div>

方案2:使用data属性做定位(更稳定,无类名冲突风险)

Google Tag Manager和Optimizely都支持属性选择器,你完全不需要修改类名逻辑,直接给元素添加自定义data属性做定位标识,完全不受CSS Modules哈希规则影响,也不会和业务样式类名产生冲突,是更推荐的第三方工具定位方案:

<div 
  className={styles.test}
  data-gtm-element="button-test"
>
  按钮内容
</div>

后续在GTM/Optimizely里直接用选择器[data-gtm-element="button-test"]即可定位到对应元素,无论部署多少次、类名哈希怎么变都不会失效。

方案3:全局配置CSS Modules保留原始类名(适合批量处理场景)

如果你不想逐个组件修改类名,可以修改NextJS配置自定义CSS Modules的类名生成规则,自动同时保留原始类名和哈希值,不需要手动加固定类名就能得到稳定的类名前缀:

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config) => {
    const rules = config.module.rules
      .find((rule) => typeof rule.oneOf === 'object')
      .oneOf.filter((rule) => Array.isArray(rule.use));

    rules.forEach((rule) => {
      rule.use.forEach((moduleLoader) => {
        if (
          moduleLoader.loader?.includes('css-loader') &&
          !moduleLoader.loader?.includes('postcss-loader')
        ) {
          moduleLoader.options.modules.localIdentName = '[local]_[hash:base64:5]';
        }
      });
    });

    return config;
  }
}

module.exports = nextConfig

注意:该方案会全局修改所有CSS Modules的类名生成规则,要注意避免不同组件的同名原始类名产生定位冲突,建议组件的CSS类名统一加上组件名前缀,比如Button_test而不是test。

内容的提问来源于stack exchange,提问作者Mygel Bergstresser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 13:36:08