javascript 无法获取动态导入的模块:

bvk5enib  于 2022-12-25  发布在  Java
关注(0)|答案(4)|浏览(337)

我在App.tsx中有一些延迟导入的React组件。App.tsxIndex.tsx中使用,在Index.tsx中呈现并附加到body

const IndexPage = lazy(() => import("../features//IndexPage"));
    const TagsPage = lazy(
      () => import("../features/tags/TagsPage")
    );
    const ArticlePage = lazy(() => import("../features/article/ArticlePage"));

    const SearchResultPage = lazy(
      () => import("../features/search-result/SearchResultPage")
    );

    const ErrorPage = lazy(() => import("../features/error/ErrorPage"));

    ----

    <BrowserRouter basename={basename}>
      <Suspense fallback={<Fallback />}>
        <Routes>
          <Route path={INDEX} element={<IndexPage />} />
          <Route path={ARTICLE} element={<ArticlePage />} />
          <Route path={TAGS} element={<TagsPage />} />
          <Route path={SEARCH} element={<SearchResultPage />} />
          <Route path={ERROR} element={<ErrorPage />} />
          <Route path="/*" element={<ErrorPage />} />
        </Routes>
      </Suspense>
    </BrowserRouter>

在生产中经常会发生以下错误。

无法获取动态导入的模块:

所有路线都发生了这种情况。

https://help.example.io/static/js/SearchResultPage-c1900fe3.js

 https://help.example.io/static/js/TagsPage-fb64584c.js

 https://help.example.io/static/js/ArticlePage-ea64584c.js

 https://help.example.io/static/js/IndexPage-fbd64584c.js

我更改了构建路径,因此它是/static/js

build: {
    assetsInlineLimit: 0,
    minify: true,
    rollupOptions: {
      output: {
        assetFileNames: (assetInfo) => {
          var info = assetInfo.name.split(".");
          var extType = info[info.length - 1];
          if (/png|jpe?g|svg|gif|tiff|bmp|ico/i.test(extType)) {
            extType = "img";
          } else if (/woff|woff2/.test(extType)) {
            extType = "css";
          }
          return `static/${extType}/[name]-[hash][extname]`;
        },
        chunkFileNames: "static/js/[name]-[hash].js",
        entryFileNames: "static/js/[name]-[hash].js",
      },
    },
    outDir: "./../backend/src/main/resources/static/articles/",
    emptyOutDir: true,
  },

有人知道如何解决此问题吗?

更新:

我在开发中从来没有遇到过这个错误,我使用Sentry来跟踪错误,在两个月内至少发生了274次。
这是哨兵号上的所有资料。

{
  arguments: [
    {
      message: Failed to fetch dynamically imported module: https://help.example.io/static/js/SearchResultPage-c1900fe3.js,
  name: TypeError,
    stack: TypeError: Failed to fetch dynamically imported module: https://help.example.io/static/js/SearchResultPage-c1900fe3.js
  }
],
  logger: console 
}

更新

我们过去两个月有50万的访问量,发生了274次,既然tracesSampleRate0.3,那肯定不止这些。

Sentry.init({
    dsn: "",
    integrations: [new BrowserTracing()],
    tracesSampleRate: 0.3,
  });

这种情况在各种浏览器上都发生过,但主要是在Chrome上。
我不能在开发和生产中重现它。

更新

我终于重现了这个错误。如果你在一个页面上发布了一个新版本,就会发生这个错误。包含动态导入模块的文件已经不存在了,例如:

https://help.example.io/static/js/IndexPage-fbd64584c.js

上面的链接返回404

gz5pxeao

gz5pxeao1#

没有所有的数据,很难直接回答这个问题,但我会尽我所能,分享一些资源。
正如在评论中所讨论的,发生这种情况可能有许多原因。因为你不能重现,而且它不是恒定的,我们可能可以排除它来自你的代码或部署配置的理论。
我脑子里有几个理由:

  • 在试图获取资源时,网络正在变慢。您可以通过限制网络来重现此问题。
  • 分析错误或遇到异常

我相信这个错误类似于'ChunkLoadError'(它也在许多其他框架中遇到,而不仅仅是React),附加了一个类似的问题:Webpack code splitting: ChunkLoadError - Loading chunk X failed, but the chunk exists,也注意相同数量的失败业务等。
尝试修复此问题,尝试捕获错误并强制重新加载以重新获取资源,但确保不在那里循环。

希望这能帮上忙。

fdbelqdn

fdbelqdn2#

以下是对这个问题的几种不同看法。

完全回避这个问题

这是显而易见的,我怀疑从您的Angular 来看,这可能不是一个理想的答案,但切换到静态导入将解决您的问题。
在许多情况下,即使使用静态导入,捆绑包的大小仍然足够小,不会影响用户体验,而且肯定比遇到错误要小。
这也可以说是唯一有保证的方式来解决它,因为即使您的问题是由故障造成的某处,你设法跟踪和修复,仍然有合法的情况下,这个问题可能会发生。

优雅地管理错误

另一方面,仍然在错误可能并且仍然会发生的思维定势中,React有ErrorBoundaries的概念,当错误发生时,您可以利用它来处理用户体验:https://reactjs.org/docs/error-boundaries.html和https://reactjs.org/docs/code-splitting.html#error-boundaries

把事情掌握在自己手中

最后,React lazy需要一个函数,该函数返回解析为模块的promise。如果没有,那就是TypeError。很明显,它的使用方式与您的完全相同,但是如果您愿意,您可以自由地将其 Package 为更智能的方式。您所需要做的就是确保promise最终解析为导入的模块。在这里可以看到很多关于重新尝试承诺的内容。Promise Retry Design Patterns

eimct9ow

eimct9ow3#

我在从cra迁移到vite并部署到netlify时也遇到了同样的问题,遍历非惰性组件没有问题,但是当尝试加载惰性组件时出错,尽管在我的本地计算机上运行它时没有出错(使用vite & vite build)。
如果你要部署到netlify,我必须关闭资产优化并重新部署应用程序,以使惰性组件正确加载,否则,可能需要关闭一组不同的设置,如bundling或minify。

hrysbysz

hrysbysz4#

我想我可能找到了解决这个问题的好办法!
我也遇到过同样的情况,我在React项目中使用Vite,每次汇总生成bundle块时,它都会生成不同的哈希值,这些哈希值包含在文件名中(例如:在我的路线中,我也使用了很多代码拆分,所以每次我部署到生产环境中,块名称都会改变,这会在客户每次点击链接(指向旧块)时为客户生成空白页面,并且只有在用户刷新页面(强制页面使用新块)时才能解决。
我的解决方案是为我的React应用程序创建一个ErrorBoundary Package 器,它将“拦截”错误,并显示一个漂亮的错误页面,解释问题,并为用户提供重新加载页面(或自动重新加载)的选项

相关问题