TypeError: Failed to fetch dynamically imported module:

这个报错通常出现在 RAGFlow 镜像原地升级后,浏览器仍使用旧版 index.html 和旧的 chunk 资源,而服务端已不存在这些文件;同时 nginx 对缺失资源返回 SPA fallback 的 200 text/html,导致动态 import 失败。优先排查 index.html 缓

快速结论:这个报错通常出现在 RAGFlow 镜像原地升级后,浏览器仍使用旧版 index.html 和旧的 chunk 资源,而服务端已不存在这些文件;同时 nginx 对缺失资源返回 SPA fallback 的 200 text/html,导致动态 import 失败。优先排查 index.html 缓存策略与静态资源 fallback 配置。

适用环境:RAGFlow 从 infiniflow/ragflow:v1.0.0-rc2 升级到 infiniflow/ragflow:v1.0.0-rc3(CPU 镜像,docker compose,容器内 nginx 在 :80 提供 SPA,外部发布为 :9080);依赖 MySQL 8.0.40、ES 8.11.3、kvrocks 2.16.0、nats 2.14.2。

最快修复方案:暂无确认的一步修复方案。Issue 中作者使用并经实际验证的方式是修改容器内 nginx 站点配置,对 hashed 资源路径禁用 SPA fallback,并挂载到宿主机以在容器重建后保留。

注意事项:该 nginx 补丁属于 Issue 作者自行修改,不是官方修复,也未在发布镜像中被确认;重启容器后如未做挂载配置会丢失;仅能避免旧客户端拿到 HTML,不能自动让已打开的旧标签页刷新到新版本。

问题场景

用户在 docker compose 部署下将 RAGFlow 从 rc2 原地升级到 rc3(修改 RAGFLOW_IMAGE 后执行 docker compose up -d),升级期间约有 1 分钟停机。浏览器沿用升级前的会话,未清理缓存。此时在数据集编辑页点击 Save 返回 404;刷新页面后出现动态 import 失败的错误页。在服务端 curl 旧 chunk 路径,返回的是 200 状态码和 Content-Type: text/html,响应体为 index.html。

报错原文

404  http://<host>:9080/api/v1/auth/login/channels

Something went wrong
Error details: TypeError: Failed to fetch dynamically imported module:
http://<host>:9080/chunk/js/index-BjCmAP52.js

原因分析

根据 Issue 中在服务器端的验证,可能原因由以下几层叠加构成:

  • 入口文档 / 响应中没有 Cache-Control 或 Expires,浏览器可能继续使用 rc2 的 index.html,因而引用的是旧 hash 的 chunk。
  • rc3 镜像中不存在 /chunk/js/index-BjCmAP52.js,而 nginx 对该路径回落到 SPA 的 index.html,返回 200 text/html。动态 import() 拿到 HTML 而非 JavaScript,于是抛出 Failed to fetch dynamically imported module。
  • 旧 rc2 bundle 仍调用 /api/v1/auth/login/channels,而该接口在 rc3 服务端二进制中已不存在(Issue 指出同形态的 auth 路由只有 /api/v1/auth/login/file),因此保存操作返回 404。
  • Dosu 在评论中确认当前代码库 docker/nginx/ragflow.conf 同样存在该配置缺口:回落到 /index.html、入口文档无缓存策略、长期缓存只作用于 /static/(css|js|media)/;并补充 Vite 的 hashed 资源还包括 /assets/ 路径。

环境排查

  • 确认当前运行的 RAGFlow 镜像版本,是否经历 rc2 → rc3 的原地升级。
  • 确认 nginx 配置来源:是否为容器内默认配置,是否已挂载宿主机配置。
  • 检查 / 与 /index.html 的响应头是否包含 Cache-Control / Expires。
  • 检查 nginx 是否将 /chunk/、/entry/、/assets/ 等 hashed 资源路径回落到 index.html。
  • 确认浏览器是否在升级后未清缓存、仍保持旧会话标签页。
  • 核对后端镜像中是否仍存在旧 bundle 所调用的接口(如 /api/v1/auth/login/channels)。

解决步骤

  1. 在宿主机准备一份 nginx 站点配置副本,基于容器内现有配置修改,确保其余指令与镜像默认保持一致。
  2. 为 hashed 资源路径添加真实 404 规则,禁止回落到 SPA 的 index.html,例如:
# hashed assets: real 404 instead of the SPA fallback
location ^~ /chunk/ { try_files $uri =404; expires 10y; access_log off; }
location ^~ /entry/ { try_files $uri =404; expires 10y; access_log off; }
  1. 按 Issue 讨论的补充点,将 /assets/ 一并纳入同样的 404 规则,覆盖 Vite 输出的其他 hashed 资源。
  2. 为该配置增加入口文档缓存策略:/ 与 /index.html 返回 Cache-Control: no-store(或至少 no-cache),使刷新时总能取到新的入口文档。可优先尝试,Issue 中未提供该部分的完整配置片段。
  3. 将修改后的配置通过 volume 挂载进容器,使其在容器重建后仍然生效,然后重启容器。
  4. 客户端侧清理缓存或强制刷新,重新加载页面以获取新版本 bundle。

验证方法

  • curl 一个不存在的旧 chunk 路径(如 /chunk/js/index-BjCmAP52.js),应返回 404,而不是 200 text/html。
  • curl 一个不存在的 CSS 资源(/assets/ 下),同样应返回 404,作为回归检查项。
  • 检查 / 与 /index.html 响应头已包含 no-store 或 no-cache。
  • 检查 SPA 深链接仍能正常返回应用页面。
  • 在浏览器中强制刷新后重新打开数据集并点击 Save,确认不再出现 404 和动态 import 报错。

参考来源

infiniflow/ragflow #21827

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 32090

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注