Storybook静态构建部署SCSS静态资源路径加载异常问题
Storybook静态构建CSS资源路径异常解决方案
问题根因
该问题是三层配置不匹配导致的:
- SCSS中硬编码了
/开头的站点绝对路径,webpack默认不会对这类硬编码绝对路径做publicPath适配 - Storybook 6.x版本中,
publicPath配置仅作用于HTML入口的脚本、样式标签引用路径,不会处理JS内联CSS中的url()引用 - 之前配置的postcss-url等插件未命中webpack loader的执行顺序(postcss-loader需放在sass-loader编译完成后、css-loader解析url前执行才会生效)
落地修复步骤
- 第一步:调整项目下
.storybook/webpack.config.js配置,在loader层拦截重写CSS中的绝对路径引用,配置示例如下:
const path = require('path'); module.exports = async ({ config }) => { // 匹配内置CSS处理规则 const cssRule = config.module.rules.find(rule => rule.test?.toString().includes('css')); if (cssRule && Array.isArray(cssRule.oneOf)) { cssRule.oneOf.forEach(ruleSet => { if (!Array.isArray(ruleSet.use)) return; ruleSet.use.forEach(loaderConfig => { // 给css-loader加路径拦截逻辑 if (loaderConfig.loader?.includes('css-loader')) { loaderConfig.options = { ...loaderConfig.options, url: (resourcePath) => { // 把/assets开头的绝对路径转成相对路径 if (resourcePath.startsWith('/assets/')) { return resourcePath.slice(1); } return true; } }; } // 补全postcss-url配置,放在正确的loader执行位置 if (loaderConfig.loader?.includes('postcss-loader')) { const existingPlugins = loaderConfig.options?.postcssOptions?.plugins || []; loaderConfig.options.postcssOptions = { ...loaderConfig.options.postcssOptions, plugins: [ ...existingPlugins, ['postcss-url', { url: (asset) => asset.url.startsWith('/assets/') ? asset.url.slice(1) : asset.url }] ] }; } }); }); } // 配置静态资源别名,避免多层目录相对路径写错 config.resolve.alias = { ...config.resolve.alias, '@storybook-assets': path.resolve(__dirname, '../src/assets') }; return config; };
- 第二步:修正项目
project.json中build-storybook目标的静态资源配置,保证构建时资源文件能正确复制到输出目录:
{ "targets": { "build-storybook": { "executor": "@nrwl/storybook:build", "options": { // 保留原有其他配置项 "staticDirs": [ { "from": "src/assets", "to": "assets" } ] } } } }
- 第三步:调整SCSS中的路径写法,不要硬编码
/开头的绝对路径,二选一即可:- 相对路径写法:根据当前SCSS文件和assets目录的层级关系写相对路径,比如
$icon-path: "../../assets/images"; - 别名写法:用前面配置的别名,写
$icon-path: "~@storybook-assets/images";,webpack会自动解析路径,适配任意部署子目录。
- 相对路径写法:根据当前SCSS文件和assets目录的层级关系写相对路径,比如
验证方式
执行nx run ui-common:build-storybook完成构建后,打开storybook-static目录下的main.*.iframe.bundle.js文件,搜索background-image关键字,确认对应的资源路径已变为assets/xxx.svg或./assets/xxx.svg格式,没有开头的/即可。此时本地直接双击打开index.html资源可正常加载,部署到GitHub Pages子路径下也不会出现404问题。
内容的提问来源于stack exchange,提问作者Shining
相关产品推荐
相关产品推荐

