Rollup构建React组件库如何保留SCSS变量支持自定义覆盖
问题背景
你正在开发基于SCSS编写原子组件样式的轻量React组件库,项目结构特征如下:
- 每个组件配有独立样式表
- 所有组件样式统一引入全局
common.scss,文件内定义了颜色、渐变、边框等通用SCSS变量,变量已添加!default标识支持默认值覆盖 - 当前Rollup构建逻辑会直接预处理SCSS,将变量替换为静态属性值,最终生成的CSS直接绑定到对应组件,导致使用方无法自定义变量
- 预期目标:组件库自带变量默认值,使用方可创建自有
global.scss文件,引入组件库导出的common.scss后重写需要自定义的变量值
当前现有配置
rollup.config.js
import peerDepsExternal from "rollup-plugin-peer-deps-external"; import resolve from "@rollup/plugin-node-resolve"; import commonjs from "@rollup/plugin-commonjs"; import typescript from "rollup-plugin-typescript2"; import postcss from "rollup-plugin-postcss"; const packageJson = require("./package.json"); export default { input: "src/index.ts", output: [ { file: packageJson.main, format: "cjs", sourcemap: true, }, { file: packageJson.module, format: "esm", sourcemap: true, } ], plugins: [ peerDepsExternal(), resolve(), commonjs(), typescript({ useTsconfigDeclarationDir: true }), postcss({ extensions: ['.scss'] }) ] };
common.scss 变量片段
$primary-text: #3C3C3C !default; $secondary-text: #5C5C5C !default; $tertiary-text: #7C7C7C !default;
解决方案
一、Rollup配置调整
核心逻辑是不在构建阶段把SCSS完全编译为不可变的静态CSS,同时将源码中的SCSS变量文件单独导出给使用方,分三步调整:
- 修改postcss插件配置,拆分样式输出,默认提供编译完成的静态CSS供无定制需求的用户直接使用
- 单独导出
common.scss作为组件库公开入口,方便有定制需求的用户引入修改变量 - 调整package.json导出配置,明确SCSS文件的引入路径
具体修改步骤如下:
首先安装需要的依赖:
npm i -D rollup-plugin-copy
修改后的rollup.config.js配置:
import peerDepsExternal from "rollup-plugin-peer-deps-external"; import resolve from "@rollup/plugin-node-resolve"; import commonjs from "@rollup/plugin-commonjs"; import typescript from "rollup-plugin-typescript2"; import postcss from "rollup-plugin-postcss"; import copy from "rollup-plugin-copy"; const packageJson = require("./package.json"); export default { input: "src/index.ts", output: [ { file: packageJson.main, format: "cjs", sourcemap: true, }, { file: packageJson.module, format: "esm", sourcemap: true, } ], plugins: [ peerDepsExternal(), resolve(), commonjs(), typescript({ useTsconfigDeclarationDir: true }), postcss({ extensions: ['.scss'], extract: 'style/index.css', // 将所有组件样式抽离为独立CSS文件,默认使用变量初始值 inject: false, // 关闭自动注入样式,避免自定义场景下样式重复引入 modules: false, // 未使用CSS Module则保持false,使用的话按需配置规则 use: [ ['sass', { silenceDeprecations: ['legacy-js-api'] }] ] }), // 将源码中的common.scss复制到构建产物目录,作为公开SCSS入口 copy({ targets: [ { src: 'src/styles/common.scss', dest: 'build/style' } // 替换为你项目实际的common.scss存放路径和输出目录 ] }) ] };
最后调整package.json的导出配置,增加SCSS入口映射:
{ "main": "build/index.cjs.js", "module": "build/index.esm.js", "exports": { ".": { "import": "./build/index.esm.js", "require": "./build/index.cjs.js" }, "./style/common.scss": "./build/style/common.scss", "./style/index.css": "./build/style/index.css" } }
二、使用方自定义变量方式
配置完成后,使用方可根据需求选择两种使用模式:
- 无自定义需求:直接引入组件库JS和编译好的静态CSS即可,和普通组件库用法一致
- 需要自定义变量:在项目全局SCSS文件中先声明自定义变量值,再引入组件库的common.scss和样式文件,示例:
// 项目内的global.scss // 先声明自定义变量,会自动覆盖common.scss中带!default标识的默认值 $primary-text: #1D2129; $secondary-text: #4E5969; $tertiary-text: #86909C; // 再引入组件库的变量文件和样式 @import 'your-component-lib/style/common.scss'; @import 'your-component-lib/style/index.css';
注意:如果使用方需要通过SCSS编译全量覆盖变量,不要在组件库的JS入口中自动注入CSS,避免样式重复打包,可以在组件库文档中明确说明两种样式引入方式的差异。
关于Rollup是否适合该类组件库构建场景
Rollup非常适合这类React组件库的构建场景,相比其他构建工具它的优势很明确:
- 构建产物干净冗余少,Tree Shaking支持成熟,非常适合分发独立组件库、工具包
- 插件生态完善,TS处理、样式编译、外部依赖隔离等常见需求都有稳定插件覆盖
- 原生支持同时输出CJS、ESM多种模块格式产物,适配不同业务项目的模块规范
- 配置灵活度高,可以按需调整样式、静态资源的处理规则,完全满足暴露SCSS变量、自定义主题这类定制需求
后续如果要扩展按需引入、组件自动导入等能力,Rollup也有对应插件可以快速实现,不需要切换构建工具。
内容的提问来源于stack exchange,提问作者Nikhil Jagtap
相关产品推荐
相关产品推荐

