Vue/Vite 原生设置中出现“TypeError:无法获取动态导入的模块”

Fer*_*'.' 76 javascript typescript webpack vue.js vite

我们有一个普通的 Vue/Vite 设置,我正在接收TypeError: Failed to fetch dynamically imported module哨兵日志。

尽管我没有足够的数据来确认,但这些错误似乎与新的产品部署及时相关。它不会发生在本地,仅出现在已部署的代码上。
我见过一些关于 React 设置的类似问题,但没有一个得到满意的答复。
我还发现了有关动态导入 svgs 的类似问题,但我们的错误发生在完整组件上。

我们使用动态导入组件的唯一地方是路由:

export const router = createRouter({
  history: routerHistory,
  strict: true,
  routes: [
    {
      path: '/',
      name: routes.homepage.name,
      component: () => import('@/views/Home.vue'),
      children: [
        {
          path: '/overview',
          name: routes.overview.name,
          component: () => import('@/views/Overview.vue'),
        },
        // other similar routes
      ],
    },
  ],
});
Run Code Online (Sandbox Code Playgroud)

我们的部门版本:

    "vue": "^3.0.9",
    "vue-router": "^4.0.5",
    "vite": "^2.0.5",
Run Code Online (Sandbox Code Playgroud)

有关此问题以及如何调试它的任何其他信息将不胜感激!

Fis*_*uto 78

当您动态导入路由/组件时,在构建过程中它会创建一个单独的块。默认情况下,块文件名根据其内容 \xe2\x80\x93进行哈希处理Overview.abc123.js。如果不更改组件代码,哈希值将保持不变。如果组件代码发生变化,哈希值也会发生变化 - Overview.32ab1c.js。这对于缓存来说非常有用。

\n

现在,当您收到此错误时会发生以下情况:

\n
    \n
  1. 您部署应用程序
  2. \n
  3. 您的主页块有一个链接到/overview,该链接将加载Overview.abc123.js
  4. \n
  5. 客户访问您的网站
  6. \n
  7. 您在代码中进行更改,不一定是对 Overview 组件本身进行更改,但可能是对 Overview 导入的某些子组件进行更改。
  8. \n
  9. 您部署更改,并且概述现在使用不同的哈希构建 -Overview.32ab1c.js
  10. \n
  11. 客户端点击/overview链接 - 收到Failed to fetch dynamically imported module错误,因为Overview.abc123.js不再存在
  12. \n
\n

这就是错误与部署相关的原因。解决这个问题的一种方法是不使用延迟加载的路由,但是当你有很多繁重的路由时,这不是一个很好的解决方案 - 它会让你的主包变得很大

\n

  • 这是对这个问题的一个很好的解释。目前,我们也忽略这些错误并要求用户“刷新并重试”。但这对于我们的团队和用户来说都是令人沮丧的。希望Vite团队能针对这个问题做点什么。使用 Vue 2 和 webpack,这个问题从未发生过。 (7认同)
  • @Preetesh但我认为如果部署的应用程序保持不变就不会发生此错误?或者换句话说:这个错误是否仅在开发人员最近重新部署 Web 应用程序并且浏览器客户端的缓存已过时时才会发生? (2认同)
  • @Preetesh 这不是魔法。如果你配置 Webpack 将所有内容捆绑到几个大包中,当然这不会发生。您确定使用 webpack 进行了完全相同的设置吗?这种情况会发生在任何创建无数不同的要加载的包的打包器中,webpack 也不例外。这是预料之中的。 (2认同)

小智 31

接受的答案正确地解释了何时触发此错误,但并没有真正提供一个好的解决方案。

我解决这个问题的方法是使用路由器上的错误处理程序。此错误处理程序确保当发生此错误时(因此当部署新版本的应用程序时),下一个路由更改会触发页面的硬重新加载,而不是动态加载模块。代码如下所示:

router.onError((error, to) => {
  if (error.message.includes('Failed to fetch dynamically imported module') || error.message.includes("Importing a module script failed")) {
    window.location = to.fullPath
  }
})
Run Code Online (Sandbox Code Playgroud)

router你的 vue-router 实例在哪里。

  • 应该是“window.location.href”而不是“window.location”,不是吗? (5认同)
  • 您的错误可能是特定于浏览器的。例如 Firefox 和 Safari:“加载动态导入的模块时出错”“导入模块脚本失败” (4认同)
  • 规范规定即使模块缓存失败也会发生。即使您刷新,Chrome 仍然会为您提供缓存故障,这意味着您需要使用缓存清除。看看这里的一种这样的方法(与框架无关):/sf/answers/5334037551/ (3认同)
  • 有点惊讶,因为 `router.onError` 需要一个 `ErrorHandler` 类型的回调函数,而它只需要一个错误。没有“to”参数。(使用 vue-router 3.x) (2认同)
  • @LéoCoco 关于如何访问“to”路由参数有什么想法吗? (2认同)

Ily*_*ich 26

就我而言,错误是由于未向.vue模块名称添加扩展名引起的。

import MyComponent from 'components/MyComponent'
Run Code Online (Sandbox Code Playgroud)

它在 webpack 设置中工作,但需要 Vite 文件扩展名:

import MyComponent from 'components/MyComponent.vue'
Run Code Online (Sandbox Code Playgroud)

  • 嘿,lyich,谢谢你的回复。恐怕这里的情况并非如此,因为我们使用的是示例中“require”语句中所示的扩展。我们到处都用它。 (2认同)

tho*_*mas 22

我有完全相同的问题。就我而言,有些路线有效,有些则无效。解决方案相对简单。我刚刚重新启动了开发服务器。

  • 这个答案具有误导性。您绝对可以在本地收到此错误,在这种情况下,重新启动开发服务器是一个很好的修复方法,但该错误很可能不是由延迟加载的路由引起的。最初的问题在_生产_和_延迟加载的路线_的上下文中询问此错误。 (7认同)
  • 这个答案适用于本地环境而不是生产。 (5认同)
  • 谢谢。如果我没有看到这个,我肯定会花更长时间用头撞墙。 (2认同)

小智 8

Wouter Sioen 的解决方案很好,但是在修复之后,当发生 chunkLoad 错误时,我遇到了另一个问题:无法读取未定义的属性(读取“fullPath”)。我的解决方案是:

router.onError((error, to) => {
  if (
    error.message.includes('Failed to fetch dynamically imported module') ||
    error.message.includes('Importing a module script failed')
  ) {
    if (!to?.fullPath) {
      window.location.reload();
    } else {
      window.location = to.fullPath;
    }
  }
Run Code Online (Sandbox Code Playgroud)