この記事では、サービスワーカー(SW)についてお話したいと思います。SWを使用すると、アプリケーションをオフラインで動作できるようにすることができるため、インターネットに接続していなくても動作します。また、プッシュ通知やバックグラウンド同期など、他の多くの高度な機能を使用することもできます。SWは、ブラウザを閉じた後も実行を継続します。つまり、ServiceWorkerは実行を継続します。これはバックグラウンドプロセスです。それでは、最初のServiceWorkerを登録しましょう。
(この記事では、SW関連の機能をプレーンJSに実装します。コードはプレーンJSで記述されているため、Angular、React、VueなどのJSフレームワークに統合できます)
最初のステップとして、sw.jsファイルをプロジェクトのルートに追加します。app.jsでは、SWがナビゲーターで使用可能かどうか、つまりSWがこのブラウザーでサポートされているかどうかを確認する必要があります。SWが使用可能であることがわかったので、navigator.serviceWorker.register()メソッドを実行して、SWが存在するファイルへのパスを指定して登録できます。このメソッドは実際にはPromiseを返します。ですから、情報を得るために、それが終わったら、私たちは彼に加わることができます。

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js')
.then(event => {
console.log('Service worker registered', event);
});
}
SW, . , SW . , . SW, , , self, « SW», addEventListener (). SW , , , , Service Worker’a. , , . , Service Worker .

self.addEventListener('install', event => {
console.log('Installing [Service Worker]', event);
});
. Service Worker’a - , , . caches, API , open (), . , . event.waitUntil (). , . . then . cache.addAll () , .

self.addEventListener('install', event => {
console.log('Installing [Service Worker]', event);
event.waitUntil(
caches.open('static')
.then(cache => {
console.log('[Service Worker] Precaching App Shell');
cache.addAll([
'/',
'/index.html',
'/favicon.ico',
'/src/js/app.js',
'/src/js/chart.js',
'/src/js/materialize.js',
'/src/js/materialize.min.js',
'/src/css/materialize.css',
'/src/css/materialize.min.css',
'/src/css/style.css',
'https://fonts.googleapis.com/icon?family=Material+Icons',
'https://code.jquery.com/jquery-2.1.1.min.js',
'https://cdn.jsdelivr.net/npm/chart.js@2.8.0'
]);
}));
});
, -.

, . , . , , - . Fetch , - - , css js xhr. , fetch Service Worker’a , . , , .

self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
if (response) {
return response;
} else {
return fetch(event.request);
}
})
);
});
event.respondWith () , . Service Worker’ , , fetch. , Service Worker, . , , . cashes.match () , . , . , , , , , , . , , , , fetch (event.request). - .

, - , « » . , , , . , . , . , , , . , .

Object.keys(pureData).forEach(key => tmp[sorter[key.toLowerCase()]] = { key, value: pureData[key] });
tmp.forEach(obj => orderedData[obj.key] = obj.value);
const ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: Object.entries(orderedData).map(([key, _]) => key),
datasets: [{
label: 'Users',
backgroundColor: '#26a69a',
borderColor: '#26a69a',
fill: false,
data: Object.entries(orderedData).map(([_, value]) => value),
}]
}
});
});
};

, , , .

self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
if (response) {
return response;
} else {
return fetch(event.request)
.then(res => {
return caches.open('dynamic')
.then(cache => {
cache.put(event.request.url, res.clone());
return res;
})
});
}
})
);
});
, , , . , caches, API open (), . cache.put () , . , , - URL- , . - . , , , , . . . . xhr. , css .

. - , . ? SW . , - , , , , indexedDB. , , SW . SW, . , , . , , Service Worker’y . , . - , , API, . Service Worker’y, ready, , . , . , ( ), . , , . , « ». Service Worker’, , , , , .

if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready
.then(sw => {
sw.sync.register('sync-request')
});
}
, «POST DATA» , , indexedDB . , indexedDB. , . . - . «sunday», 10 ( :)). writeData utility.js, . - , , - . .

const syncButton = document.getElementById('sync-button');
syncButton.addEventListener('click', _ => {
if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready
.then(sw => {
const data = {
id: new Date().getTime(),
sunday: 10
};
writeData('sync-requests', data)
.then(_ => {
sw.sync.register('sync-request')
});
});
}
});
, , - . , , .

self.addEventListener('sync', event => {
console.log('[Service Worker] Syncing');
if (event.tag === 'sync-request') {
event.waitUntil(
readAllData('sync-requests')
.then(async data => {
const requests = [];
for (const d of data) {
requests.push(fetch('https://simple-pwa-8a005.firebaseio.com/data.json', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
sunday: d.sunday
})
}));
}
const results = await Promise.all(requests);
results.map((response, index) => {
if (response.ok) {
deleteItemFromData('sync-requests', data[index].id);
}
})
})
);
}
});
. event.waitUntil (), , , . , indexedDB ( utility.js), , post , indexedDB, . . . , , «POST DATA» .

「POSTDATA」ボタンを押した後、オフラインのときは何も起こりませんが、接続が復元されると、同期が完了したことがわかります。

また、データが実際にサーバーに送信されたことを確認するには、最初に動的キャッシュからフェッチ要求を削除して、[データの取得]ボタンをクリックする必要があります。

それは今のところすべてです。じゃあまたね。私のコードはgithubで入手できます:https://github.com/Draakan/simplePWA