React 17中App组件className丢失问题求助
问题描述
我用React 17编写了一个App组件用于页面渲染,App组件引入App.module.scss中的styles.uiStage作为div的className。项目启动后,该div的className丢失,但style标签中存在ui-stage样式,且所有子组件的className均可正常渲染。相关代码及rollup配置文件如下,请问问题原因是什么?
App.tsx
import React from 'react'; import styles from './App.module.scss'; type AppProps = { templateString: string; } const App: React.FC<AppProps> = ({ templateString = '' }) => { return <div className={styles.uiStage}> 123 </div>; }; export default App;
App.module.scss
.ui-stage { background-color: red; position: fixed; top: 0; left: 0; right: 0; bottom: 0; }
index.ts
const root = document.getElementById('root'); ReactDOM.render(<App />, root);
rollup.config.js
import serve from "rollup-plugin-serve"; import livereload from "rollup-plugin-livereload"; import babel from '@rollup/plugin-babel'; import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import replace from '@rollup/plugin-replace'; import image from '@rollup/plugin-image'; import postcss from 'rollup-plugin-postcss'; const extensions = [".js", ".jsx", ".ts", ".tsx"]; export default { input: "src/index.ts", output: [ { file: "dist/iife/bundle.js", format: "iife", // for local dev sourcemap: true, }, { file: "dist/esm/bundle.js", format: 'esm', // for esm sourcemap: true, } ], plugins: [ image(), postcss({ autoModules: true, extensions: [".css", ".scss"], }), nodeResolve({ extensions, }), replace({ preventAssignment: true, 'process.env.NODE_ENV': JSON.stringify( 'development' ) }), commonjs(), babel({ babelHelpers: 'bundled', extensions }), serve({ open: true, verbose: true, contentBase: ["", "public"], host: "localhost", port: 3000, }), livereload({ watch: "dist" }), ] };
问题原因及解决办法
核心原因
问题出在rollup-plugin-postcss的模块转换逻辑上:
- 你SCSS里的类名是
ui-stage(短横线命名),组件里用的是styles.uiStage(小驼峰),虽然插件autoModules: true默认会把短横线转驼峰,但主App组件的样式模块没有被正确映射,导致styles.uiStage的值为undefined,所以div上没渲染出className。 - 子组件正常是因为它们的样式模块处理顺序或逻辑没触发这个冲突。
解决办法
- 明确配置postcss模块规则:替换
autoModules为modules选项,强制开启驼峰转换:
postcss({ modules: { camelCase: true, // 强制将短横线类名转为驼峰 generateScopedName: '[name]__[local]--[hash:base64:5]' // 可选,自定义作用域类名格式 }, extensions: [".css", ".scss"], })
- 直接使用短横线属性名:把组件里的
styles.uiStage改成styles['ui-stage'],跳过驼峰转换步骤:
return <div className={styles['ui-stage']}> 123 </div>;
- 调整插件执行顺序:确保
postcss插件在babel、commonjs之前执行,避免样式模块解析延迟导致的映射丢失。
内容的提问来源于stack exchange,提问作者ChenLee
相关产品推荐
相关产品推荐

