我在 Superset 6.x 做自定义图表 + Embedded SDK 集成的实战复盘(附踩坑清单)

2 阅读5分钟

我在 Superset 6.x 做自定义图表 + Embedded SDK 集成的实战复盘(附踩坑清单)

最近这段时间,我在 Superset 6.0.0 上做了两件事:

  • 开发自定义图表插件并接入主应用;
  • 通过 @superset-ui/embedded-sdk 把仪表盘嵌入到外部系统。

功能本身不算“黑科技”,但过程中遇到的坑很真实:插件明明写了却不生效、403 ForbiddenCSRF token is missing、Webpack 5 的 polyfill 报错等。
这篇文章把我这次的完整经验做一次复盘,希望能帮你少走弯路。


一、先说结论:最容易踩的 4 个坑

1)插件“开发好了但页面不显示”,大概率不是代码问题,而是资源来源错了

我最早一直以为是插件注册失败,后来发现是运行环境加载了 site-packages 里的 Superset 静态资源,而不是仓库里刚构建出来的 superset/static/assets

自检命令:

python -c "import superset; print(superset.__file__)"

如果输出路径在 site-packages,你当前 superset run 不是在用你本地源码树。

2)npm run dev-serversuperset run 混用时,静态资源容易“串台”

开发时热更新很方便,但如果你在验证生产构建结果,还开着 dev-server,就可能出现 manifest.json 与实际 chunk 不一致,最终表现为“页面资源 hash 对不上”。

我的建议:

  • 验证生产包前先停掉 dev-server
  • 改完插件后走一次完整流程:npm run build -> 启后端 -> 浏览器强刷。

3)Embedded 场景下 403,最常见不是 token 生成失败,而是权限链不完整

我遇到过 token 正常返回,但图表数据接口仍然 403。根因通常有两类:

  • chart/data 请求没带 dashboardId(某些版本/场景会触发);
  • Guest 角色权限缺项(尤其是 Dataset、Dashboard、Chart、Database 的读取权限与 Security 相关权限)。

4)跨域 iframe 下 CSRF 问题,本质是“会话上下文没建立起来”

报错表现通常是:

  • CSRF session token is missing
  • The CSRF token is missing

核心原因往往是 Cookie / SameSite / CORS 凭据配置不匹配。
开发调试阶段我会用“可用优先”的配置先打通链路,再按生产安全要求收紧。


二、我的开发主线(从插件到嵌入)

1. 自定义图表插件接入流程

我采用的是在 superset-frontend/building/ 下维护插件包,然后接入主工程:

  1. 创建插件目录,包名统一用 superset-plugin-chart-*
  2. 在插件里实现 ChartPlugin 并定义唯一 viz key
  3. VizType 增加对应枚举;
  4. MainPreset 注册插件;
  5. 确保 webpack 对 superset-plugin 源码解析规则生效;
  6. 构建并验证页面是否出现新图表。

经验点:
viz key 必须全局唯一且前后端元数据一致,不一致时最容易出现“看起来注册了,实际找不到图表类型”的隐性问题。

2. Embedded SDK 集成流程

我的集成路径是标准“四段式”:

  1. Superset 端开启 EMBEDDED_SUPERSET 等配置;
  2. 在 Superset UI 中启用 Dashboard 的 Embedded;
  3. 宿主后端调用 /api/v1/security/guest_token/ 签发 token;
  4. 宿主前端 embedDashboard + fetchGuestToken 完成挂载。

这里最关键的是:token 鉴权只是一环,权限模型、资源 ID、请求头、跨域策略都要一致
任意一环错了,最终都可能表现为 401/403。


三、我踩过的坑与解决方式

坑 A:插件打包后不生效

现象: 页面还是旧资源,或者插件入口找不到。
定位:

  • 检查 superset.__file__ 是否来自仓库源码;
  • 核对 manifest.json 与浏览器请求的 entry hash 是否一致;
  • 停止 dev-server,重新 build 并强刷缓存。

解决:

  • 用统一脚本启动后端(确保 PYTHONPATH 指向仓库);
  • 固化“改插件 -> build -> run -> hard refresh”流程。

坑 B:Embedded 请求 403 Forbidden

现象: Dashboard iframe 打开了,但图表数据接口 403。
定位:

  • Network/api/v1/chart/data 请求体是否带 dashboardId
  • 确认 guest_tokenresources.id 是否是正确的 dashboard UUID;
  • 检查 Guest 角色权限是否覆盖 Dataset/Chart/Dashboard/Database 与 security 相关操作。

解决:

  • 补齐请求参数与角色权限;
  • 必要时升级到已修复版本,避免吃历史版本缺陷。

坑 C:CSRF token 无效

现象: CSRF session token is missing
定位:

  • 跨域 iframe 下 Cookie 是否被浏览器拒绝;
  • SameSite=None 是否搭配 Secure=True
  • CORS_OPTIONS.supports_credentialsorigins 是否正确。

解决思路:

  • 开发环境优先打通链路(必要时临时关闭 CSRF);
  • 生产环境务必恢复严格策略,并通过 BFF/白名单/CSP 收紧风险面。

坑 D:Webpack 5 报 Node 核心模块缺失(tty / crypto

现象: 构建报 Module not found
原因: Webpack 5 不再默认注入 Node core polyfill。
解决:

  • 安装 tty-browserifycrypto-browserify 等替代包;
  • resolve.fallback 中配置映射;
  • 必要时用 ProvidePlugin 注入 Buffer / process

四、我整理的一份“可落地检查清单”

每次发版前我都会过这份 checklist:

  • superset import 路径是否确实来自当前仓库源码;
  • 插件 viz keyVizTypeMainPreset 注册是否一致;
  • npm run buildmanifest 与浏览器请求 hash 是否一致;
  • Embedded 的 dashboard UUID 是否正确;
  • Guest token 是否未过期、签名密钥是否一致;
  • Guest 角色权限是否覆盖读数据与必要接口;
  • 跨域配置(CORS/Cookie/SameSite/Secure)是否与部署方式匹配;
  • 生产配置是否移除开发期宽松项(例如过宽的角色或过松的安全策略)。

五、一些实践建议(给后来者)

  1. 把“环境一致性”放在第一位。
    很多“代码问题”其实是运行环境错位(尤其 Python 包路径 + 前端静态资源来源)。

  2. 先打通链路,再做安全收敛。
    Embedded 场景涉及鉴权、权限、跨域、浏览器策略,多因素耦合。先可用,再逐步收紧是更稳的节奏。

  3. 把排错经验沉淀成文档和脚本。
    比如统一启动脚本、自检命令、角色权限模板,能显著减少团队协作成本。


结语

这次在 Superset 6.x 的扩展实践,最大的感受是:
真正耗时的不是“写功能”,而是让插件构建链路、鉴权链路、权限模型和部署环境形成闭环。

如果你也在做 Superset 的二开(特别是“自定义图表 + Embedded”这条线),希望这篇复盘能帮你绕开我踩过的坑。