我在 Superset 6.x 做自定义图表 + Embedded SDK 集成的实战复盘(附踩坑清单)
最近这段时间,我在 Superset 6.0.0 上做了两件事:
- 开发自定义图表插件并接入主应用;
- 通过
@superset-ui/embedded-sdk把仪表盘嵌入到外部系统。
功能本身不算“黑科技”,但过程中遇到的坑很真实:插件明明写了却不生效、403 Forbidden、CSRF 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-server 和 superset 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 missingThe CSRF token is missing
核心原因往往是 Cookie / SameSite / CORS 凭据配置不匹配。
开发调试阶段我会用“可用优先”的配置先打通链路,再按生产安全要求收紧。
二、我的开发主线(从插件到嵌入)
1. 自定义图表插件接入流程
我采用的是在 superset-frontend/building/ 下维护插件包,然后接入主工程:
- 创建插件目录,包名统一用
superset-plugin-chart-*; - 在插件里实现
ChartPlugin并定义唯一viz key; - 在
VizType增加对应枚举; - 在
MainPreset注册插件; - 确保 webpack 对
superset-plugin源码解析规则生效; - 构建并验证页面是否出现新图表。
经验点:
viz key 必须全局唯一且前后端元数据一致,不一致时最容易出现“看起来注册了,实际找不到图表类型”的隐性问题。
2. Embedded SDK 集成流程
我的集成路径是标准“四段式”:
- Superset 端开启
EMBEDDED_SUPERSET等配置; - 在 Superset UI 中启用 Dashboard 的 Embedded;
- 宿主后端调用
/api/v1/security/guest_token/签发 token; - 宿主前端
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_token的resources.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_credentials与origins是否正确。
解决思路:
- 开发环境优先打通链路(必要时临时关闭 CSRF);
- 生产环境务必恢复严格策略,并通过 BFF/白名单/CSP 收紧风险面。
坑 D:Webpack 5 报 Node 核心模块缺失(tty / crypto)
现象: 构建报 Module not found。
原因: Webpack 5 不再默认注入 Node core polyfill。
解决:
- 安装
tty-browserify、crypto-browserify等替代包; - 在
resolve.fallback中配置映射; - 必要时用
ProvidePlugin注入Buffer/process。
四、我整理的一份“可落地检查清单”
每次发版前我都会过这份 checklist:
supersetimport 路径是否确实来自当前仓库源码;- 插件
viz key、VizType、MainPreset注册是否一致; npm run build后manifest与浏览器请求 hash 是否一致;- Embedded 的 dashboard UUID 是否正确;
- Guest token 是否未过期、签名密钥是否一致;
- Guest 角色权限是否覆盖读数据与必要接口;
- 跨域配置(CORS/Cookie/SameSite/Secure)是否与部署方式匹配;
- 生产配置是否移除开发期宽松项(例如过宽的角色或过松的安全策略)。
五、一些实践建议(给后来者)
-
把“环境一致性”放在第一位。
很多“代码问题”其实是运行环境错位(尤其 Python 包路径 + 前端静态资源来源)。 -
先打通链路,再做安全收敛。
Embedded 场景涉及鉴权、权限、跨域、浏览器策略,多因素耦合。先可用,再逐步收紧是更稳的节奏。 -
把排错经验沉淀成文档和脚本。
比如统一启动脚本、自检命令、角色权限模板,能显著减少团队协作成本。
结语
这次在 Superset 6.x 的扩展实践,最大的感受是:
真正耗时的不是“写功能”,而是让插件构建链路、鉴权链路、权限模型和部署环境形成闭环。
如果你也在做 Superset 的二开(特别是“自定义图表 + Embedded”这条线),希望这篇复盘能帮你绕开我踩过的坑。