Ruby on Rails&服务人员

时间:2015-05-02 21:16:42

标签: javascript ruby-on-rails html5 service-worker

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

我需要在app/javascripts/service-worker.js.erb文件中使用某些erb功能。服务工作者注册脚本如下所示:

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扩展名并将范围更改为./,一切正常,但我没有模板引擎

有什么建议吗?

6 个答案:

答案 0 :(得分:4)

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

Sprockets将指纹资产和Rails(或您的网络服务器)通常使用来自/assets目录的积极缓存标头来提供编译文件。

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

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

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

答案 1 :(得分:2)

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

如果您确实需要模板引擎,可以尝试从/ public文件夹(How do I include a JavaScript file in another JavaScript file?)中的文件动态加载JS文件。目前,Firefox(https://bugzilla.mozilla.org/show_bug.cgi?id=1130101

中尚未实现Service-Worker-Allowed HTTP标头

答案 2 :(得分:2)

我现在也遇到了这个问题。根据我的研究,我认为Rails应用程序处理服务工作者的正确方法是使用Asset管道正常服务于服务工作者javascript文件,使用scope选项对服务工作者进行范围调整(就像你已经完成的那样),然后使用Service-Worker-Allowed HTTP header明确允许新范围。

不幸的是,目前实施此方法存在一些障碍:

  1. Rails 4(显然)不允许将HTTP标头添加到它所服务的Assets,而不是缓存控制标头。要解决这个问题,你可以添加一个如本S.O. answer中详述的Rack插件,或者如果你正在使用资产服务器(如Nginx),你可以通过让Nginx添加HTTP头来解决这个问题。虽然这在开发过程中没有帮助。
  2. Rails 5允许将HTTP标头添加到Assets,但是detailed in this blog post
  3. 对服务工作者和服务工作者允许的HTTP标头的浏览器支持为currently poor

答案 3 :(得分:1)

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

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

然后只需放入你的控制器(我的例子中的core_controller.rb)

def service_worker
end

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

答案 4 :(得分:0)

将服务工作者文件保留在项目结构强加的任何目录中,并将scope选项设置为/,并将Service-Worker-Allowed HTTP标头添加到服务工作者文件的响应中。

在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 specification

中的示例

答案 5 :(得分:0)

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

使用yarn add webpacker-pwa添加webpacker-pwa npm软件包,并使用以下命令编辑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;

这将使您可以使用服务人员。请同时检查项目的自述文件:https://github.com/coorasse/webpacker-pwa/tree/master/npm_package