Vue3+Storybook项目Sass全局变量未生效及导入问题
解决Vue3+Storybook中Sass全局变量未定义的问题
问题根源
在preview.ts中导入全局样式文件仅能让样式在浏览器运行时生效,但组件内的SCSS代码在编译阶段(由sass-loader处理)无法访问这些全局变量,因此会抛出"Undefined variable"错误。另外你组件中的样式标签写成了<styling>,这是语法错误,需要修正为<style>。
解决方案
通过配置sass-loader的additionalData选项,在每个SCSS文件编译前自动注入全局变量文件,让编译阶段就能识别全局变量。
修改.storybook/main.js的Webpack配置
更新webpackFinal中的规则,确保sass-loader能自动导入全局变量文件:
import type { StorybookConfig } from '@storybook/vue3-webpack5'; import path from 'path'; const config: StorybookConfig = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions', ], framework: { name: '@storybook/vue3-webpack5', options: {}, }, docs: { autodocs: 'tag', }, async webpackFinal(config) { if (config?.resolve?.alias) { config.resolve.alias = { ...config.resolve.alias, '@': path.resolve(__dirname, '../src/'), } } if(config.module?.rules) { // 遍历现有规则,修改sass-loader配置 config.module.rules.forEach(rule => { if (rule.test?.test('.scss')) { rule.use?.forEach(loader => { if (loader.loader?.includes('sass-loader')) { loader.options = { ...loader.options, additionalData: `@import "${path.resolve(__dirname, '../src/styles/__main.scss')}";` }; } }); } }); // 如果没有现有SCSS规则,添加带全局变量注入的新规则 const hasScssRule = config.module.rules.some(rule => rule.test?.test('.scss')); if (!hasScssRule) { config.module.rules.push({ test: /\.scss$/, use: [ 'style-loader', 'css-loader', { loader: 'sass-loader', options: { additionalData: `@import "${path.resolve(__dirname, '../src/styles/__main.scss')}";` } } ], include: path.resolve(__dirname, '../src'), }); } } return config; }, }; export default config;
修正组件中的样式标签语法
将组件内的错误标签替换为标准的<style>:
<style lang="scss" scoped> .loader{ color: $color-primary; } </style>
原理说明
additionalData会在每个被编译的SCSS文件顶部自动插入全局变量文件的导入语句,让组件内的SCSS代码在编译阶段就能访问到$color-primary这类全局变量,从根源避免编译错误。preview.ts中的导入仍需保留,确保全局样式(如重置样式、全局通用类)在Storybook运行时正常生效。
内容的提问来源于stack exchange,提问作者user9875
相关产品推荐
相关产品推荐

