【问题标题】:Retrying a failed dynamic import? (SPA/PWA)重试失败的动态导入? (SPA/PWA)
【发布时间】:2019-10-09 19:36:07
【问题描述】:

我正在处理的项目中遇到的问题是,我有一个单页应用程序。我正在处理浏览器客户端的导航路由,这让我可以在路由匹配时动态导入一些模块。我的路由设置看起来有点像这样:

router.setRoutes([
    {
        path: '/',
        component: 'app-main', // statically loaded
    },
    {
    path: '/posts',
        component: 'app-posts',
        action: () => { import('./app-posts.js').catch(() => Router.go('/offline');} // dynamically loaded
    },
    {
        path: '/offline', network
        component: 'app-offline', // also statically loaded
    }
]);

为了清楚起见,这里是“应用”的简单图像:

我在我的服务工作者中缓存应用程序外壳,这意味着 main 页面和 offline 页面被预缓存,posts 页面应该在运行时被缓存(一旦请求,所以如果用户点击posts链接)

所以我的预缓存清单缓存:main.jsoffline.js 和我的index.html

我遇到的问题是:

  • 用户失去网络连接
  • 用户尝试转到posts 页面
  • 如果之前没有被请求和缓存过,动态导入可能会失败(用户将被重定向到offline页面)

但是当我的用户再次获得网络连接时,点击posts链接,动态导入仍然会失败;我猜是因为浏览器对动态导入进行了重复数据删除。

这是一个巨大的耻辱,因为我的用户有网络连接;这个请求应该成功!我能弄清楚如何处理这个问题的唯一方法是让用户重新加载页面,并再次请求posts 页面。

所以我的问题是,我应该怎么做?

【问题讨论】:

    标签: service-worker progressive-web-apps workbox dynamic-import


    【解决方案1】:

    通过在尝试像这样导入之前检查用户是否有网络连接来解决它:

    function handleRoute(url) {
      if('onLine' in navigator) {
        if(navigator.onLine) {
          // user is online, safe to import
          import(url);
        } else {
          // user is offline, don't even try to import -> straight to `/offline`
          Router.go('/offline');
        }
      } else {
        // incase the browser doesnt support `navigator.onLine`, try to import anyway
        import(url);
      }
    }
    

    感觉有点老套,但是browser support for navigator.onLine 还是很不错的。

    有关重试失败的动态导入的更多信息,我在tc39/proposal-dynamic-import github 存储库中找到了this 问题。

    【讨论】:

    • 这个解决方案很好,但是如果你的代码已经缓存了 url 并且你想在离线时动态加载它怎么办?当我在离线时尝试这样的文件时,提取工作正常(我看到工作箱消息说它正在从缓存中提供文件),但是导入不起作用,出现错误。就像浏览器完全绕过 service worker 进行动态导入一样。
    【解决方案2】:

    浏览器没有做那种缓存/重复数据删除/任何事情。您可以通过从控制台调用 import 并切换您的网络在线/离线来轻松验证这一点。

    所以问题很可能出在您使用的框架上。对路由操作的第一次调用的缓存发生在框架的某个地方。也许查阅文档?

    【讨论】:

    • 我确实用调试器运行了路由器代码,我可以验证action函数被多次调用。进一步的信息,我认为浏览器正在在这里进行某种重复数据删除,最小的复制是:<html> <body><button onClick="myFun()">click</button></body> <script>function myFun() {import('./my-module.js')}</script> </html>,打开网络选项卡,导入只会运行一次
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 2011-09-02
    相关资源
    最近更新 更多