1

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!

  • 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 Sep 8 at 18:23
  • @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... – Skayo Sep 8 at 20:37
  • @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.... – Skayo Sep 8 at 21:06
  • @Skayo would you mind adding your solution as an official answer in case it ends up helping someone in the future? – Brad Bell Sep 9 at 21:31
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.