使用 CSS Modules
CSS Modules 让我们能以模块化的方式编写 CSS 代码,并且可以在 JavaScript 文件中导入和使用这些样式。使用 CSS Modules 可以自动生成唯一的类名,隔离不同模块之间的样式,避免类名冲突。
Rsbuild 默认支持使用 CSS Modules,无需添加额外的配置。我们约定使用 [name].module.css 文件名来启用 CSS Modules。
以下样式文件会被视为 CSS Modules:
*.module.css*.module.less*.module.sass*.module.scss*.module.styl*.module.stylus
用法示例
- 编写样式:
button.module.css
.red {background: red;}
- 使用样式:
Button.tsx
import styles from './button.module.css';export default () => {return <button className={styles.red}>Button</button>;};
具名导入
如果你倾向于在 CSS Modules 中使用具名导入,可以通过 output.cssModules.namedExport 配置项来开启。
rsbuild.config.ts
export default {output: {cssModules: {namedExport: true,},},};
开启后,你可以通过具名导入来引用类名:
Button.tsx
import { red } from './button.module.css';export default () => {return <button className={red}>Button</button>;};
CSS Modules 识别规则
在默认情况下,只有 *.module.css 结尾的文件才被视为 CSS Modules 模块。
如果你想将其他 CSS 文件也当做 CSS Modules 模块进行处理,可以通过配置 output.cssModules.auto 来实现。
比如:
export default {output: {cssModules: {auto: (resource) => {return resource.includes('.module.') || resource.includes('shared/');},},},};
设置后,以下两个文件都会被视为 CSS Modules:
import styles1 from './foo.module.css';import styles2 from './shared/bar.css';
自定义类名
自定义 CSS Modules 生成的类名也是我们比较常用的功能,你可以使用 output.cssModules.localIdentName 来进行配置。
export default {output: {cssModules: {localIdentName: '[hash:base64:4]',},},};
如果你需要自定义 CSS Modules 的其他配置,可以通过 output.cssModules 进行设置。
类型声明
当你在 TypeScript 代码中引用 CSS Modules 时,TypeScript 可能会提示该模块缺少类型定义:
TS2307: Cannot find module './index.module.css' or its corresponding type declarations.
此时你需要为 CSS Modules 添加类型声明文件,请在项目中创建 src/env.d.ts 文件,并添加相应的类型声明。
- 方法一:如果项目里安装了
@rsbuild/core包,你可以直接引用@rsbuild/core提供的 预设类型:
/// <reference types="@rsbuild/core/types" />
- 方法二:手动添加需要的类型声明:
src/env.d.ts
declare module '*.module.css' {const classes: { readonly [key: string]: string };export default classes;}declare module '*.module.scss' {const classes: { readonly [key: string]: string };export default classes;}declare module '*.module.sass' {const classes: { readonly [key: string]: string };export default classes;}declare module '*.module.less' {const classes: { readonly [key: string]: string };export default classes;}declare module '*.module.styl' {const classes: { readonly [key: string]: string };export default classes;}declare module '*.module.stylus' {const classes: { readonly [key: string]: string };export default classes;}
- 方法三:如果你需要使用具名导入来引用类名,可以更松散的类型定义:
src/env.d.ts
declare module '*.module.css';declare module '*.module.scss';declare module '*.module.sass';declare module '*.module.less';declare module '*.module.styl';declare module '*.module.stylus';
添加类型声明后,如果依然存在类型错误,请尝试重启当前 IDE,或者调整 env.d.ts 所在的目录,使 TypeScript 能够正确识别类型定义。
类型生成
上述方法虽然可以解决 CSS Modules 在 TypeScript 中的类型问题,但是无法准确地提示出 CSS Modules 导出了哪些类名。
Rsbuild 支持为 CSS Modules 生成准确的类型声明,你只需要开启 @rsbuild/plugin-typed-css-modules,再执行构建命令,Rsbuild 就会为项目中所有的 CSS Modules 文件生成类型声明文件。
rsbuild.config.ts
import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules';export default {plugins: [pluginTypedCSSModules()],};
示例
例如,创建 src/index.ts 和 src/index.module.css 两个文件:
src/index.ts
import styles from './index.module.css';console.log(styles.pageHeader);
index.module.css
.page-header {color: black;}
构建后,Rsbuild 会自动生成 src/index.module.css.d.ts 类型声明文件:
src/index.module.css.d.ts
interface CssExports {'page-header': string;pageHeader: string;}declare const cssExports: CssExports;export default cssExports;
此时再打开 src/index.ts 文件,可以看到 styles 对象已经具备了准确的类型。
