web-dev-qa-db-ja.com

Service Workerで定義されたフォルダー/パスのすべてのファイルをキャッシュする方法はありますか?

Service Workerでは、Service Workerの開始時にキャッシュされるリソースの配列を定義できます。

self.addEventListener('install', event => {
    event.waitUntil(caches.open('static-${version}')
        .then(cache => cache.addAll([
            '/styles.css',
            '/script.js'
        ]))
    );
});

Service Workerでパス/ディレクトリを定義して、すべてのファイル名を書き込む代わりに、Service Workerが特定のパス/ディレクトリからすべてのファイルを選択してすべてをキャッシュに追加するにはどうすればよいですか?

7
Mohd Yasin

それは不可能です。 SW(つまり、ブラウザ)には、Webサーバー上の特定のパスにあるファイルについての手掛かりはありません。キャッシュしたいファイルの名前を指定する必要があります。同じ問題の詳細 こちら

いくつかのビルドツールを使用して、ファイルのリストを自動的に生成していますか?そうでない場合は、おそらく:)

編集:

SWツールで最も使用されるライブラリの1つはワークボックスです。 runtime-cachingprecaching の両方のアセットを提供します。彼らはまた例えばのための構築ツールのプラグインを持っています。 WebpackとGulp。

実行時キャッシュは、アセットが存在する場合はキャッシュからアセットを提供し、サーバーからアセットを更新することで機能します。基本的に、すべての新しいアセットは最初にネットワークからリクエストされ、その後のリクエストでキャッシュから返されます。

EDIT2:

はい、ある程度NPMなしでWorkboxを使用できます。キャッシュするファイルのファイル名を収集するには、NPMスクリプトなどを実行する必要がありますが、手書きのSWファイルにWorkbox.jsスクリプトをインポートするだけで、ランタイムキャッシュを実装できます。

言うだけで

importScript("https://unpkg.com/[email protected]/build/importScripts/workbox-sw.prod.v2.1.0.js") 

SWの一番上に、Workboxの最新(現時点で)バージョンがインポートされます。 ここでもランタイムキャッシュの例 でそれが起こっていることがわかります。

上記の.jsファイルをダウンロードして独自のサーバーに配置し、代わりに相対パスからインポートすることもできます。

3
pate

Workbox swを使用したランタイムキャッシング.

service-worker.js:

importScripts('https://unpkg.com/[email protected]/build/importScripts/workbox-sw.dev.v0.0.2.js');
importScripts('https://unpkg.com/[email protected]/build/importScripts/workbox-runtime-caching.prod.v1.3.0.js');
importScripts('https://unpkg.com/[email protected]/build/importScripts/workbox-routing.prod.v1.3.0.js');

const assetRoute = new workbox.routing.RegExpRoute({
    regExp: new RegExp('^http://localhost:8081/jobs/static/*'),
    handler: new workbox.runtimeCaching.CacheFirst()
});

const router = new workbox.routing.Router();
//router.addFetchListener();
router.registerRoutes({routes: [assetRoute]});
router.setDefaultHandler({
    handler: new workbox.runtimeCaching.CacheFirst()
});

Servcieワーカーをロードするためのhtmlファイルのスクリプト。

<script>
    if ('serviceWorker' in navigator) {
        window.addEventListener('load', function() {
            navigator.serviceWorker.register('http://localhost:8081/jobs/static/service-worker.js?v=4').then(function(registration) {
            // Registration was successful
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, function(err) {
            // registration failed :(
            console.log('ServiceWorker registration failed: ', err);
            });
        });
    }
</script>
1
Mohd Yasin

はい、できます。私もそのような種類の問題を抱えており、performanceを使用してクールな解決策を見つけています。これが私のsw.js

const KEY = 'key';

self.addEventListener('install', (event) => {
    event.waitUntil(self.skipWaiting());
});

self.addEventListener('message', (event) => {
    if (event.data.type === 'CACHE_URLS') {
        event.waitUntil(
            caches.open(KEY)
                .then( (cache) => {
                    return cache.addAll(event.data.payload);
                })
        );
    }
});

これが私のmain.js

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js', { scope: '/' })
        .then((registration) => {
            const data = {
                type: 'CACHE_URLS',
                payload: [
                    location.href,
                    ...performance.getEntriesByType('resource').map((r) => r.name)
                ]
            };
            registration.installing.postMessage(data);
        })
        .catch((err) => console.log('SW registration FAIL:', err));
}

これにより、特定のパスをキャッシュするフィルターを追加することもできます。

1
Jahongir