You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Storyshots加载本地storybook-static目录时快照测试返回空白截图

问题根因

空白截图本质是file://协议的浏览器安全策略限制,和CORS无关。直接通过本地文件路径打开Storybook构建产物时,页面内的ES模块加载、静态资源请求、前端脚本执行都会被拦截——所有请求的源会被标记为null,触发同源策略阻断,页面JS完全没跑起来,Puppeteer截到的自然是未渲染的空白HTML。手动启动http-server后访问正常,就是因为HTTP协议场景下没有这套本地文件安全限制。

最优解决方案(适配无头服务器/CI环境,无需手动维护服务)

@storybook/addon-storyshots-puppeteer原生内置静态服务托管能力,不需要手动启动服务,也不需要配置file://路径。测试运行时会自动在空闲端口启动临时静态服务指向Storybook构建产物,测试执行完成后自动关闭服务,无残留进程,完全适配无头环境。
修改storybook.spec.js配置如下,注意修正原配置里的语法错误(imageSnapshot需要传入对象参数,原代码缺少对象包裹的大括号):

import { imageSnapshot } from "@storybook/addon-storyshots-puppeteer"
import initStoryshots from "@storybook/addon-storyshots"
import path from 'path'
import puppeteer from 'puppeteer'

initStoryshots({
  suite: "Image storyshots",
  test: imageSnapshot({
    // 指向你的storybook-static目录绝对路径,用path拼接避免相对路径找不到资源的问题
    storybookStaticDir: path.resolve(__dirname, '../storybook-static'),
    // 无头服务器必备Puppeteer启动参数,避免沙箱、内存不足导致的启动失败
    getCustomBrowser: () => puppeteer.launch({
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage'
      ]
    })
  })
})

配置完成后,执行流程不变:先跑npm run build-storybook生成静态产物,再执行npm run test即可,测试过程会自动托管静态资源,不会再出现空白截图。

备选方案(需要自定义服务配置时使用)

如果有固定端口、自定义响应头等特殊需求,无法使用内置静态服务,可以通过Jest的生命周期钩子自动启停本地服务,全程无需手动操作:

  • 安装轻量静态服务依赖:npm install -D serve
  • 编写globalSetup.js脚本,在测试启动前拉起服务,将监听端口写入全局变量
  • 在测试配置中读取端口,将storybookUrl设置为http://localhost:${port}
  • 编写globalTeardown.js脚本,在所有测试用例执行完成后,杀掉服务进程
    这种方案的稳定性和内置服务一致,适合有定制化需求的场景。

避坑提醒

不要通过给Puppeteer添加--disable-web-security参数绕过file协议限制,这种方式会导致渲染行为和正常HTTP访问场景存在差异,且在部分做了安全加固的无头服务器上参数会失效,稳定性极差,不推荐使用。


内容的提问来源于stack exchange,提问作者Beast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:09:23