样式

Rspeedy 支持多种方式来对你的应用程序进行样式设计,包括:

  • CSS Modules: 创建具有局部作用域的 CSS 类,以避免命名冲突并提高可维护性。

  • Global CSS: 使用全局 CSS,对于习惯传统 CSS 的人来说很熟悉,但可能生成更大的 CSS 文件并且随着应用程序的增长难以管理样式。

  • CSS pre-processors: 使用常见的 CSS 预处理器,如 sass 或者 less 通过变量、嵌套规则等特性扩展了 CSS。

  • PostCSS: 用于转换 CSS 的工具。

使用 CSS Modules

CSS Modules 允许以模块化的方式编写 CSS 代码,并且这些样式可以在 JavaScript 文件中被导入并使用。使用 CSS 模块可以自动生成唯一的类名,隔离不同模块之间的样式,并避免类名冲突。

TIP

如果想要使用非隔离的 CSS 样式,可以使用 Global CSS

Rspeedy 默认支持 CSS Modules,你不需要添加额外的配置。我们的约定是使用 [name].module.css 文件名来启用 CSS Modules。

示例

  1. 与正常样式一样编写 CSS 代码
button.module.css
.red {
  background: red;
}
  1. 像模块一样使用样式
Button.jsx
import styles from './button.module.css';

export function Button() {
  return (
    <view className={styles.red}>
      <text>Button</text>
    </view>
  );
}

或者使用 Named Imports:

Button.jsx
import { red } from './button.module.css';

export function Button() {
  return (
    <view className={red}>
      <text>Button</text>
    </view>
  );
}

配合 CSS Pre-Processor 使用

CSS Modules 也可以与 CSS 预处理器一起使用。只需按照 *.module.* 的模式命名样式文件即可。

E.g.: 下面这些文件都将会被认为是 CSS Modules

  • *.module.css
  • *.module.less
  • *.module.sass
  • *.module.scss

识别规则

默认情况下,只有以 *.module.{css,scss,less} 结尾的文件才会被识别为 CSS Modules。

如果你想将其他 CSS 文件也视为 CSS Modules,可以通过在 Rspeedy 中配置 output.cssModules.auto 来实现。

如下面的例子所示:

lynx.config.ts
import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  output: {
    cssModules: {
      auto(filename) {
        return filename.includes('.module.') || filename.includes('/shared/');
      },
    },
  },
});

给定此配置,以下 imports 将被识别为 CSS Modules:

import * as foo from './foo.module.css';
import * as bar from './shared/bar.css';

类型声明

当你在 TypeScript 代码中导入 CSS Modules 时,TypeScript 可能会提示该模块缺少类型定义:

TS2307: Cannot find module './index.module.css' or its corresponding type declarations.

要解决这个问题,你需要为 CSS 模块添加一个类型声明文件,请创建一个 src/rspeedy-env.d.ts 文件,并添加相应的类型声明。

/// <reference types="@lynx-js/rspeedy/client" />
TIP

create-rspeedy 会自动为你创建这个文件。

如果在添加类型声明后仍然存在类型错误,你可以尝试重启当前的 IDE,以确保 TypeScript 能正确识别类型定义。

生成 TS 类型定义

@lynx-js/rspeedy/client 将提供如下类型声明:

declare module '*.module.css' {
  type CSSModuleClasses = {
    readonly [key: string]: string;
  };
  const classes: CSSModuleClasses;
  export default classes;
}

它对于每个 CSS Modules 中含有的类名不够精确。

使用 Typed CSS Modules Plugin 将为所有 CSS Modules 生成具有精确类型声明的类型声明文件。

  1. 安装 @rsbuild/plugin-typed-css-modules
npm
yarn
pnpm
bun
npm add -D @rsbuild/plugin-typed-css-modules
  1. pluginTypedCSSModules 添加至 lynx.config.ts
lynx.config.ts
import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules';

import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  source: {
    entry: './src/index.tsx',
  },
  plugins: [pluginReactLynx(), pluginTypedCSSModules()],
});

在执行 rspeedy build 或者 rspeedy dev 后,将会自动生成详细的类型定义。

button.module.css.d.ts
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
  red: string;
}
export const cssExports: CssExports;
export default cssExports;

你还需要设置 "allowArbitraryExtensions": true 以及 "moduleResolution": "Bundler" 来让 TypeScript 正确工作。

tsconfig.json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "allowArbitraryExtensions": true
  }
}

使用 Global CSS

在某些情况下,你可能希望 CSS 样式与一些复杂的选择器一起使用,或者一些样式能够被所有 JSX 所使用。这在 Rspeedy 中被称为全局 CSS。

只需编写 CSS 代码,并从 JavaScript 文件中导入即可。

示例

  1. 像往常一样编写 CSS 文件
styles.css
.red {
  background: red;
}

.red > text {
  color: blue;
}
  1. 从 JSX 中引入 CSS 并指定类名
index.jsx
import './styles.css';

export default function App() {
  return (
    <view className="red">
      <text>Hello, Rspeedy!</text>
    </view>
  );
}

使用 CSS Pre-Processors

CSS 预处理器通过变量、嵌套规则等特性扩展了 CSS。

使用 sass

只需创建 .scss.sass 文件,并将它们导入到 JavaScript 中即可。

import './global.sass';
import styles from './button.module.scss';

export function App() {
  return (
    <view className={styles.red}>
      <text className="title">Hello, Sass</text>
    </view>
  );
}
  1. 安装 @rsbuild/plugin-sass
npm
yarn
pnpm
bun
npm install -D @rsbuild/plugin-sass
  1. pluginSass 添加至 lynx.config.ts
lynx.config.ts
import { pluginSass } from '@rsbuild/plugin-sass';

import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  source: {
    entry: './src/index.tsx',
  },
  plugins: [
    pluginSass({
      /** sass options */
    }),
  ],
});

pluginSass 中可以使用更多选项,请参阅 Sass 插件以了解用法。

使用 less

只需创建 .less 文件,并将它们导入到 JavaScript 中即可。

import './global.less';
import styles from './button.module.less';

export function App() {
  return (
    <view className={styles.red}>
      <text className="title">Hello, Less</text>
    </view>
  );
}
  1. 安装 @rsbuild/plugin-less
npm
yarn
pnpm
bun
npm install -D @rsbuild/plugin-less
  1. pluginLess 添加至 lynx.config.ts
lynx.config.ts
import { pluginLess } from '@rsbuild/plugin-less';

import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  source: {
    entry: './src/index.tsx',
  },
  plugins: [
    pluginLess({
      /** less options */
    }),
  ],
});

pluginLess 中可以使用更多选项,请参阅 Less 插件以了解用法。

使用 PostCSS

由 Rsbuild 提供支持的 Rspeedy 内置了 PostCSS 用于转换 CSS 代码。

Rsbuild 使用 postcss-load-config 从当前项目的根目录加载 PostCSS 配置文件,例如 postcss.config.js

export default {
  'postcss-px-to-viewport': {
    viewportWidth: 375,
  },
};
除非另有说明,本项目采用知识共享署名 4.0 国际许可协议进行许可,代码示例采用 Apache License 2.0 许可协议进行许可。