【问题标题】:Rails Progressive Web Application problemsRails 渐进式 Web 应用程序问题
【发布时间】:2020-02-21 13:41:19
【问题描述】:

我正在尝试在我的 Rails 6 应用程序中实现渐进式 Web 应用程序功能,它首先运行良好。我正在为一家医院开发一个应用程序,该应用程序也应该可以从医院外部访问,因此我们决定将其 DMZ 中的外部请求重定向到我的网络服务器。

这导致了我的问题:注册服务工作者的脚本资源位于重定向后面并且无法访问它,这就是为什么服务工作者没有被加载并且用户无法使用的功能PWA。

这是我在 application.js 中注册工作者的代码:

    if (navigator.serviceWorker) {
    navigator.serviceWorker.register('/service-worker.js', { scope: './' })
                           .then(function(registration) {
                             console.log('[Companion]', 'Service worker registered!')
                             console.log(registration)
                           })
}

然后我使用两个控制器的方法,一个用于清单文件,另一个用于重定向到相应视图/文件的服务人员。

在我的 head 标签中,我在 application.html.erb 中添加了 <link rel="manifest" href="/manifest.json">

我的路线如下:

get '/service-worker.js', to: 'service_workers/workers#index'
get '/manifest.json', to: 'service_workers/manifests#index'

那是我的 service-worker.js:

var CACHE_VERSION = 'v1';
var CACHE_NAME = CACHE_VERSION + ':sw-cache-';

function onInstall(event) {
  console.log('[Serviceworker]', "Installing!", event);
  event.waitUntil(
    caches.open(CACHE_NAME).then(function prefill(cache) {
      return cache.addAll([
        '<%= asset_pack_path 'application.js' %>',
        '<%= root_path %>',
        '/mealplan',
      ]);
    })
  );
}

function onActivate(event) {
  console.log('[Serviceworker]', "Activating!", event);
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          // Return true if you want to remove this cache,
          // but remember that caches are shared across
          // the whole origin
          return cacheName.indexOf(CACHE_VERSION) !== 0;
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
}

// Borrowed from https://github.com/TalAter/UpUp
function onFetch(event) {
  event.respondWith(
    // try to return untouched request from network first
    fetch(event.request).catch(function() {
      // if it fails, try to return request from the cache
      return caches.match(event.request).then(function(response) {
        if (response) {
          return response;
        }
        // if not found in cache, return default offline content for navigate requests
        if (event.request.mode === 'navigate' ||
          (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
          console.log('[Serviceworker]', "Fetching offline content", event);
          return caches.match('/offline.html');
        }
      })
    })
  );
}

self.addEventListener('install', onInstall);
self.addEventListener('activate', onActivate);
self.addEventListener('fetch', onFetch);  

我在访问应用程序以供外部使用时在浏览器中遇到的错误如下:

脚本资源位于重定向后面,这是不允许的。

Uncaught (in promise) DOMException: Failed to register a ServiceWorker for scope ('https://xxxxxxx.nkbrf.de/') with script ('https://xxxxxxx.nkbrf.de/service-worker.js'): 脚本资源在重定向后面,这是不允许的。

我认为范围属性可能是问题所在,但我不想将其设置为固定值。有没有办法解决这个问题?

感谢您的帮助!

【问题讨论】:

  • 我想看看你的文件service-worker.js的内容,可能这个文件有错误。
  • 其他,我认为这是一个小错误,但在您的消息中:Failed to register a ServiceWorker for scope ('https://xxxxxxx/service-worker.js') with script ('https://xxxxxx/service-worker.js'),这个https://xxxxxxx/service-worker.js 与这个https://xxxxxxx/service-worker.js 不同。在最后一个 URL 中缺少一个字符。
  • 不,我只是不想显示真实的 URL,这就是我删除它并输入一些“x”字符的原因。两种情况下的真实 URL 是相同的 :)

标签: ruby-on-rails service-worker progressive-web-apps


【解决方案1】:

如果删除范围属性,错误会消失吗?做这个测试,因为范围属性是可选的,在你的情况下,不一定是不同的。

根据 Mozilla 网站:

范围参数是可选的,可用于指定您希望服务工作者控制的内容子集。在这种情况下,我们指定了“/sw-test/”,这意味着应用程序源下的所有内容。如果您忽略它,无论如何它都会默认为该值,但我们在此处指定它是为了便于说明。

https://developer.mozilla.org/pt-BR/docs/Web/API/Service_Worker_API/Using_Service_Workers

【讨论】:

  • 确实,如果我删除 application.js 中的范围,它确实可以工作。感谢您的提示:)
【解决方案2】:

我在这里发现了一个类似的 RoR 问题:Drifting Ruby Example

为了使重定向工作(我也无法使用它们),我必须对上面列出的示例中提供的代码进行两次更改。

  1. 我必须在 ruby​​ 中获取“范围”的值(因此,index.json 变成了 index.json.erb),并且我必须将值设置为 URI.join,&lt;%= response.headers["Service-Worker-Allowed"] = URI.join(request.original_url, "/").to_s %&gt;"

    1. 接下来,我必须将 routes.rb 中的 service-worker.js 完全限定为我的 worker 文件的完整路径。 get "/service-worker.js", to: "xyz_abc/service_workers/workers#show"

    2. 最后,我必须在父资源中为我的两个文件命名空间和资源:routes.rb namespacing

这 3 个步骤让我通过了。

【讨论】:

    猜你喜欢
    • 2018-12-23
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2019-05-16
    • 2019-10-04
    • 2023-03-07
    相关资源
    最近更新 更多