preview.js中import未编译SCSS无效,因其非构建上下文,仅支持纯CSS或已编译样式;需先编译SCSS为CSS再导入,或通过webpackFinal配置sass-loader处理组件内SCSS。

preview.js 里 import '../src/Button.scss' 为什么没样式?
因为 preview.js 不是构建上下文,它只负责在预览 iframe 的 <head> 中注入纯 CSS。直接 import 一个未编译的 .scss 文件会触发 You may need an appropriate loader 错误——Webpack 根本没机会介入,preview.js 的 JS 运行时无法解析 @mixin 或 $color-primary。
真正能生效的只有两类文件:
-
import '../src/style/reset.css'(已编译的纯 CSS) -
import '../dist/tailwind.css'(PostCSS 处理后的产物)
如果你的 SCSS 文件含变量或嵌套,必须先编译成 CSS,再导入。
如何让组件内部的 Button.scss 正常生效?
组件自己的 .scss 文件(比如 Button.scss)要靠 Webpack 构建链处理,不是靠 preview.js。你需要在 .storybook/webpack.config.js 或 main.js 的 webpackFinal 中显式配置 sass-loader 和 postcss-loader:
立即学习“前端免费学习笔记(深入)”;
- 顺序必须是
sass-loader → postcss-loader → css-loader,否则@apply会被原样保留 -
include路径要覆盖src/和storybook/,不能只写./storybook - 如果用了 Tailwind,
postcss-loader的config.path必须指向含postcss.config.cjs的目录(通常是项目根目录)
示例关键片段:
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
include: path.resolve(__dirname, '../src'),
});
return config;
}
Tailwind 的 md:flex 在 Storybook 里不生效?
这是静态扫描失效的典型表现。Tailwind JIT 只读取 content 配置里声明的文件路径,而 Storybook 的 .stories.ts 文件默认不在其中。
检查你的 tailwind.config.js 的 content 数组是否包含:
-
"./storybook/**/*.{js,ts,jsx,tsx,vue}"(注意必须以./开头) - 如果你把 stories 放在
src/stories/,也得加上"./src/stories/**/*.{js,ts,jsx,tsx}"
漏掉任意一项,md:flex、hover:bg-blue-500 这类响应式或伪类规则就不会生成。
动态 class 名如 class={`text-${size}-lg`} 怎么办?
Tailwind 不执行 JS,它只扫描字面量。你在 story 里写 class={`text-${size}-lg`},JIT 看到的只是 text-${size}-lg,不会生成任何对应规则。
可行方案只有两个:
- 改用静态变体:为每个
size值单独写一个 story,比如text-sm-lg、text-md-lg - 配合
clsx+ 白名单:提前定义const sizes = ['sm', 'md', 'lg'],然后在content中加入text-${sizes.join('|')}-lg这类正则匹配(需 Tailwind v3.3+)
别指望运行时插值能在 Storybook 里“热生成”样式——它不是服务端渲染环境,也没做 AST 解析。
最易被忽略的一点:确认样式是否真进了预览 iframe 的 <head>,而不是只看控制台有没有报错。打开 DevTools,切到 Elements 面板,展开 Storybook 的 iframe,检查 <head> 里有没有你期望的 <style> 标签。没有,说明路径或内容根本没加载进去;有但没效果,大概率是优先级或 specificity 被覆盖了。


















