<p>Solved it by just serving the file within a controller action like this:</p>

<pre class="lang-php prettyprint-override"><code>public function actionCacheCraftServiceWorker () {
    $serviceWorkerFile = Craft::getAlias('@skayo/cachecraft/assetbundles/cachecraft/dist/js/CacheCraftServiceWorker.min.js');

    return Craft::$app-&gt;getResponse()-&gt;sendFile(
        $serviceWorkerFile,
        'CacheCraftServiceWorker.min.js',
        [
            'mimeType' =&gt; 'application/javascript',
            'inline' =&gt; true
        ]
    );
}
</code></pre>

<p>and using this event to register the front-end url:</p>

<pre class="lang-php prettyprint-override"><code>Event::on(
    UrlManager::class,
    UrlManager::EVENT_REGISTER_SITE_URL_RULES,
    function (RegisterUrlRulesEvent $event) {
        Craft::debug(
            'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
            __METHOD__
        );
        $event-&gt;rules['cache-craft-service-worker'] = [
            'route' =&gt; 'cachecraft/frontend/cache-craft-service-worker',
            'suffix' =&gt; '.js'
        ];
    }
);
</code></pre>

<p>Now I can just access it with <code>https://example.com/cache-craft-service-worker.js</code> which works perfectly fine.</p>

CC BY-SA 4.0
2019-09-10T16:11:13.083Z
2019-09-10T16:11:13.083Z
Jonas Geiler
<p>I am currently working on a plugin that uses a service worker which gets registered  on the front-end by some javascript code and the problem is that the service worker scope is restricted to <code>/cpresources/610c42da/</code> as the Asset Manager only serves the file from there.  </p>

<p>Here's the code which I currently use to integrate with the front-end:</p>

<pre class="lang-php prettyprint-override"><code>Craft::$app-&gt;getView()
                   -&gt;hook('cachecraft', function () {
                       // Pass the service worker url to the site
                       Craft::$app-&gt;getView()
                                  -&gt;registerScript(
                                      'const CACHECRAFT_SERVICE_WORKER = "' .
                                      Craft::$app-&gt;assetManager-&gt;getPublishedUrl('@skayo/cachecraft/assetbundles/cachecraft/dist/js/service-worker.js', true) .
                                      '";',
                                      1,
                                      [],
                                      'cachecraft_service_worker'
                                  );

                       // Register asset bundle
                       Craft::$app-&gt;getView()
                                  -&gt;registerAssetBundle(CacheCraftAsset::class);
                   });
</code></pre>

<p>So what I need is to serve my service worker from the root (<code>https://example.com/service-worker.js</code>) of the website.<br>
Is that possible somehow?<br>
Another possible way is to serve the file normally at <code>https://example.com/cpresources/610c42da/service-worker.js</code> BUT with a Service-Worker-Allowed HTTP Header.<br>
But I don't know how to do that either...</p>

<p>Thanks in advance for any help!</p>

CC BY-SA 4.0
2019-09-08T18:23:00.883Z
You'd need to set up a frontend route that redirects from `/sw.js` (or whatever) to the actual URL to your resource.
andrew.welch
CC BY-SA 4.0
2019-09-08T20:37:50.777Z
@andrew.welch Oh no... I just thought it was working when I got this error:  
`The script resource is behind a redirect, which is disallowed.`  
I hate this so much 
So no redirects... Need another solution...
Jonas Geiler
CC BY-SA 4.0
2019-09-08T21:06:41.600Z
@andrew.welch Okay so I finally solved it by just serving the file within a controller action. This should be good enough... Asset Manager would be better tho....
Jonas Geiler
CC BY-SA 4.0
2019-09-09T21:31:04.760Z
@Skayo would you mind adding your solution as an official answer in case it ends up helping someone in the future?
Brad Bell
<assets><plugins><files><scope><headers>
Use Service Worker in Plugin
# Use Service Worker in Plugin

(Asked by: username_0 on 2019-09-08)

I am currently working on a plugin that uses a service worker which gets registered  on the front-end by some javascript code and the problem is that the service worker scope is restricted to /cpresources/610c42da/ as the Asset Manager only serves the file from there.  
Here's the code which I currently use to integrate with the front-end:
Craft::$app->getView()
                   ->hook('cachecraft', function () {
                       // Pass the service worker url to the site
                       Craft::$app->getView()
                                  ->registerScript(
                                      'const CACHECRAFT_SERVICE_WORKER = "' .
                                      Craft::$app->assetManager->getPublishedUrl('@skayo/cachecraft/assetbundles/cachecraft/dist/js/service-worker.js', true) .
                                      '";',
                                      1,
                                      [],
                                      'cachecraft_service_worker'
                                  );

                       // Register asset bundle
                       Craft::$app->getView()
                                  ->registerAssetBundle(CacheCraftAsset::class);
                   });

So what I need is to serve my service worker from the root (https://example.com/service-worker.js) of the website.
Is that possible somehow?
Another possible way is to serve the file normally at https://example.com/cpresources/610c42da/service-worker.js BUT with a Service-Worker-Allowed HTTP Header.
But I don't know how to do that either...
Thanks in advance for any help!

**Tags:** assets, plugins, files, scope, headers
> **Comments:**
> **username_1**: You'd need to set up a frontend route that redirects from `/sw.js` (or whatever) to the actual URL to your resource.  
> **username_0**: @andrew.welch Oh no... I just thought it was working when I got this error:   `The script resource is behind a redirect, which is disallowed.`   I hate this so much  So no redirects... Need another solution...  
> **username_0**: @andrew.welch Okay so I finally solved it by just serving the file within a controller action. This should be good enough... Asset Manager would be better tho....  
> **username_2**: @Skayo would you mind adding your solution as an official answer in case it ends up helping someone in the future?  

---

## 1 answers

### Answer by username_0 on 2019-09-10. Score: 2 | Accepted answer

Solved it by just serving the file within a controller action like this:
public function actionCacheCraftServiceWorker () {
    $serviceWorkerFile = Craft::getAlias('@skayo/cachecraft/assetbundles/cachecraft/dist/js/CacheCraftServiceWorker.min.js');

    return Craft::$app->getResponse()->sendFile(
        $serviceWorkerFile,
        'CacheCraftServiceWorker.min.js',
        [
            'mimeType' => 'application/javascript',
            'inline' => true
        ]
    );
}

and using this event to register the front-end url:
Event::on(
    UrlManager::class,
    UrlManager::EVENT_REGISTER_SITE_URL_RULES,
    function (RegisterUrlRulesEvent $event) {
        Craft::debug(
            'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
            __METHOD__
        );
        $event->rules['cache-craft-service-worker'] = [
            'route' => 'cachecraft/frontend/cache-craft-service-worker',
            'suffix' => '.js'
        ];
    }
);

Now I can just access it with https://example.com/cache-craft-service-worker.js which works perfectly fine.


---

