5

我正在尝试在我的 Ruby on Rails 应用程序中使用服务工作者。

我需要在我的app/javascripts/service-worker.js.erb文件中使用一些 erb 功能。Service Worker 注册脚本如下所示:

var registerServiceWorker = function() {
  navigator.serviceWorker.register(
    '<%= asset_path('service-worker.js') %>',
    { scope: '/assets/' }
  )
  .then(function() {
    console.info('Service worker successfully registered');
  })
  .catch(function(error) {
    console.warn('Cannot register sercie worker. Error = ', error);
  });
}

这不起作用;我从来没有在这里得到承诺:

navigator.serviceWorker.ready.then

我也试过.//范围,但我得到了这个错误:

DOMException:注册 ServiceWorker 失败:提供的范围 ('/') 的路径不在允许的最大范围 ('/assets/') 之下。调整范围,移动 Service Worker 脚本,或者使用 Service-Worker-Allowed HTTP 标头来允许范围。

如果我将我service-worker.js的移动到public文件夹,删除.erb扩展名并将范围更改为./,一切正常,但我没有模板引擎。

有什么建议么?

4

6 回答 6

4

现在有一个 gem,serviceworker-rails它将允许您代理对资产管道中的 serviceworker 脚本的请求。由于浏览器注册 serviceworker 脚本的方式,最好避免缓存它们。

Sprockets 将对资产进行指纹识别,Rails(或您的网络服务器)通常为编译后的文件提供目录中具有积极缓存头的/assets文件。

我们想要的是自定义服务工作者路径和响应头的能力,并且仍然可以获得 Sprockets 预处理,即 CoffeeScript/ES2015 到 JavaScript 转换。

gem 将中间件插入到您的 Rails 堆栈中,该堆栈将代理(例如)对生产中相应的指纹编译资产serviceworker-rails的请求。/serviceworker.js在开发中,您会得到您期望的自动重新加载行为。您也可以在不同的范围内设置多个 serviceworker。

https://github.com/rossta/serviceworker-rails

于 2016-04-25T19:50:01.770 回答
2

由于安全目的,您不能在比执行位置更高的范围内注册 ServiceWorker。

如果您真的需要模板引擎,您可以尝试从 /public 文件夹中的文件动态加载 JS 文件(如何在另一个 JavaScript 文件中包含 JavaScript 文件?)。目前在 Firefox 中尚未实现 Service-Worker-Allowed HTTP 标头 ( https://bugzilla.mozilla.org/show_bug.cgi?id=1130101 )

于 2015-05-04T07:27:30.143 回答
2

我现在也遇到了这个问题。根据我的研究,我认为 Rails 应用程序处理服务工作者的正确方法是使用资产管道正常提供服务工作者 javascript 文件,使用范围选项限定服务工作者(就像你所做的那样),然后使用Service-Worker-Allowed HTTP 标头显式允许新范围。

不幸的是,目前实施这种方法有几个障碍:

  1. Rails 4(显然)不允许将 HTTP 标头添加到它所服务的资产中,除了缓存控制标头。要解决此问题,您可以添加一个 Rack 插件,如本SO 答案中所述,或者如果您使用的是 Nginx 等资产服务器,则可以在生产中通过让 Nginx 添加 HTTP 标头来解决此问题。虽然这在开发过程中没有帮助。
  2. 但是,Rails 5 确实允许将 HTTP 标头添加到资产,如本博文中所述
  3. 浏览器对服务工作者和 Service-Worker-Allowed HTTP 标头的支持目前很差
于 2016-04-14T20:16:08.220 回答
1

只需在根目录中执行即可。例如,我放了一条路线

get 'service-worker(.format)', to: 'core#service_worker'

然后只需放入您的控制器(在我的示例中为 core_controller.rb)

def service_worker
end

然后创建 app/views/core/service_worker.js.erb 并将你的 JS 放在那里(包括任何 <%= stuff %>)。

于 2015-08-03T16:58:12.260 回答
0

我最近写了一篇关于如何完全使用 Webpacker 做到这一点的文章。请找到我的Rails 渐进式 Web 应用指南。简而言之:

添加 webpacker-pwa npm 包yarn add webpacker-pwa并编辑environment.js

const { resolve } = require('path');
const { config, environment, Environment } = require('@rails/webpacker');
const WebpackerPwa = require('webpacker-pwa');
new WebpackerPwa(config, environment);
module.exports = environment;

这将允许您使用服务人员。请同时查看项目的 README:https ://github.com/coorasse/webpacker-pwa/tree/master/npm_package

于 2020-06-13T06:59:48.810 回答
-1

将 service worker 文件保留在项目结构强加的任何目录中,并设置scope选项/并将Service-Worker-AllowedHTTP 标头添加到 service worker 文件的响应中。

在 ASP.Net 中,我在 web.config 文件中添加了以下内容:

<location path="assets/serviceWorker.js">
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <add name="Service-Worker-Allowed" value="/" />
            </customHeaders>
        </httpProtocol>
    </system.webServer>
</location>

并通过以下方式注册工人:

navigator.serviceWorker.register('/assets/serviceWorker.js', { scope: '/' })
        .then(function (registration)
        {
          console.log('Service worker registered successfully');
        }).catch(function (e)
        {
          console.error('Error during service worker registration:', e);
        });

在 Firefox 和 Chrome 上测试。

请参阅Service Worker 规范中的示例

于 2018-01-02T22:24:02.357 回答