导致此vue-router异步组件错误-TypeError:undefined不是对象(正在评估't .__ esModule')?

问题描述 投票:0回答:1

我注意到以下堆栈跟踪中的Sentry中有很多错误:

TypeError: undefined is not an object (evaluating 't.__esModule')
  at isESModule(./node_modules/vue-router/dist/vue-router.esm.js:1955:3)
  at ? (./node_modules/vue-router/dist/vue-router.esm.js:1882:27)
  at promiseReactionJob([native code])

我在重现错误并弄清楚是什么原因时遇到了很多麻烦。查看vue-router源,它来自此功能:

  function isESModule (obj) {
    return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
  }

因此obj未定义。如果我们上一级,我们将获得以下功能:

  function resolveAsyncComponents (matched) {
    return function (to, from, next) {
      var hasAsync = false;
      var pending = 0;
      var error = null;

      flatMapComponents(matched, function (def, _, match, key) {
        // if it's a function and doesn't have cid attached,
        // assume it's an async component resolve function.
        // we are not using Vue's default async resolving mechanism because
        // we want to halt the navigation until the incoming component has been
        // resolved.
        if (typeof def === 'function' && def.cid === undefined) {
          hasAsync = true;
          pending++;

          var resolve = once(function (resolvedDef) {
            if (isESModule(resolvedDef)) {
              resolvedDef = resolvedDef.default;
            }
            // save resolved on async factory in case it's used elsewhere
            def.resolved = typeof resolvedDef === 'function'
              ? resolvedDef
              : _Vue.extend(resolvedDef);
            match.components[key] = resolvedDef;
            pending--;
            if (pending <= 0) {
              next();
            }
          });

...

因此resolvedDef似乎未定义。

我的猜测是Vue路由器成功解析了一个异步组件,但最终未定义,并且代码中没有任何内容可以解决这种情况。

我正在使用vue-router 3.1.3,并且这些错误始终仅在iOS(Safari或Chrome)上发生。

我已经尝试使用Google搜索错误,但似乎在其他任何地方都找不到该错误的单个引用。我也无法在vue-router Github上发布问题,因为我无法提供最低限度的复制。

通常(但并非总是)Sentry还会在错误之前显示此控制台日志:

console [vue-analytics] An error occured! Please check your connection or disable your AD blocker
logger console
extra {"arguments":["[vue-analytics] An error occured! Please check your connection or disable your AD blocker"]}

我不确定这是否相关。

我正在考虑的一个疯狂的解决方案是部署了vue-router的修补版本,在未定义resolvedDef的情况下,它会在更有用的上下文中引发错误。该错误有望在我们的Sentry日志中结束。

是什么导致此错误?

ios vuejs2 mobile-safari vue-router mobile-chrome
1个回答
0
投票

我派生了vue-router库,并在此行中修补了resolveAsyncComponents

if (!resolvedDef) {
  window.onerror(`router wtf ${matched.join(',')} ${def} ${_} ${match} ${key} ${pending} ${hasAsync} ${error}`);
}

最终在Sentry中出现以下错误:

router wtf [object Object] function(){return u(Promise.all([n.e("dashboard~orders~products~publicUser"),n.e("dashboard~discounts~products~publicUser"),n.e("orders~publicUser~tips"),n.e("publicUser~tips"),n.e("publicUser")]).then(n.bind(null,"89c6")))...

在生产中,我们的Vue应用程序似乎使用名为bootstrap的启动程序加载了这些组件:

asycn component loading

然后令我震惊的是,我们在router.js中的每个异步组件导入中使用以下包装:

      {
        path: 'dashboard',
        name: 'dashboard',
        component: () =>
          handleChunkLoadError(
            import(/* webpackChunkName: 'dashboard' */ '../views/Dashboard')
          ),
      },
function handleChunkLoadError(importPromise) {
  return importPromise.catch(() => {
    Vue.toasted.error('Network error encountered', {
      duration: null,
      action: {
        text: 'Reload',
        onClick: () => window.location.reload(),
      },
    });
  });
}

应该显示一个吐司,如果块加载失败,该吐司将允许用户刷新页面。

但是我们忘记了将错误传递给vue-router:

function handleChunkLoadError(importPromise) {
  return importPromise.catch(error => {
    Vue.toasted.error('Network error encountered', {
      duration: null,
      action: {
        text: 'Reload',
        onClick: () => window.location.reload(),
      },
    });

    return error;
  });
}

返回.catch处理程序中的错误已解决此问题。

🤦

© www.soinside.com 2019 - 2024. All rights reserved.