Linux開發環境,Chrome除錯
Github連結weatherPWA
weatherPWA demo:
- 伺服器使用Chrome的內建app
Web Server
,更改埠即可使用(也可以自己搭建koa伺服器) - 使用linux的chrome瀏覽器在使用
sync
功能的ServiceWoker監聽器時會抽風,windows親測無此類問題,所以儘量使用window開發PWA程式!! - 使用
push Notification
功能時要用到公鑰
和私鑰
,可用Postman進行推送測試
var vapidKeys = {
publicKey:"BPwgIYTh9n2u8wpAf-_VzZ4dwaBY8UwfRjWZzcoX6RN7y5xD0RL9U4YDCdeoO3T8nJcWsQdvNirT11xJwPljAyk",
privateKey:"TIrMnK-r--TE7Tnwf-x4JfKwuFKz5tmQuDRWYmuwbhY"
}
function subscribeUserToPush(registration , publicKey){
var subscribeOptions = {
userVisibleOnly : true,
applicationServerKey : window.urlBase64ToUint8Array(publicKey)
};
return registration.pushManager.subscribe(subscribeOptions).then(function(pushSubscription){
console.log('pushscription' ,pushSubscription)
return pushSubscription;
})
}
// base64 => Unit8Array
// https://github.com/web-push-libs/web-push#using-vapid-key-for-applicationserverkey
window.urlBase64ToUint8Array = function (base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function sendSubscriptionToServer(body, url) {
url = url || 'http://192.168.1.236:3000/subscription';
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.timeout = 60000;
xhr.onreadystatechange = function () {
var response = {};
if (xhr.readyState === 4 && xhr.status === 200) {
try {
response = JSON.parse(xhr.responseText);
console.log("user subscribed!");
alert("subscribed!");
sub_state = 1;
window.localStorage.setItem("subscription",1);
$('#subscription_btn').remove();
$('#add_btn').remove();
}
catch (e) {
response = xhr.responseText;
}
resolve(response);
}
else if (xhr.readyState === 4) {
resolve();
}
};
xhr.onabort = reject;
xhr.onerror = reject;
xhr.ontimeout = reject;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(body);
});
}
function PUSH() {
if (sub_state === 0) {
if ('serviceWorker' in navigator && 'PushManager' in window) {
var publicKey = "BPwgIYTh9n2u8wpAf-_VzZ4dwaBY8UwfRjWZzcoX6RN7y5xD0RL9U4YDCdeoO3T8nJcWsQdvNirT11xJwPljAyk";
window.navigator.serviceWorker.ready.then(function (registration) {
//displayNotification();
// open the subscription function of the page
return subscribeUserToPush(registration, publicKey);
}).then(function (subscription) {
var body = {subscription: subscription};
// give every user a unique id in order to push notification
body.uniqueid = new Date().getTime();
console.log('uniqueid', body.uniqueid);
console.log(JSON.stringify(body))
// save the subscription info in the server (bedb used for saving)
return sendSubscriptionToServer(JSON.stringify(body));
}).then(function (res) {
console.log(res);
}).catch(function (err) {
console.log(err);
});
}else{
console.log('Push messaging is not supported.')
}
}else{
alert("you have already subscribed.")
}
}
複製程式碼
- 在
ServiceWorker
內部無法使用Localstorage
進行資料儲存,因為ServiceWorker
是非同步儲存,所以如果需要將資料從ServiceWorker
傳遞到前端,需要使用IndexedDB
,建立新objectStore
來進行資料通訊。在使用indexedDB
是需要注意更新的版本號,如果版本號不變,則無法新增新的store,也就無法給資料庫新增新專案,只能更新已有資料。 - 在使用手機進行網頁測試時,對於後端伺服器的ip地址設定問題,需要格外注意。因為在手機chrome上除錯網頁時,需要使用
PortForwarding
來將localhost
的網頁推到公網ip上測試,所以在後端的push
埠和sync
埠的ip地址就是當下手機和PC共有網路的ip地址,並不在localhost
。也就是說在ServiceWorker中對於埠ip地址的呼叫,必須將ip地址更改,才能正常使用後端埠。 - 在ServiceWorker中無法使用
ajax
網路請求,需要使用fetch()
方法來進行網路請求
fetch('http://192.168.1.137:3000/sync').then(function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: '+response.status);
return;
}
response.text().then(function (data) {
console.log("succeed access to sync interface");
var request = indexedDB.open("weatherPWA");
request.onupgradeneeded = function (event) {
var store = event.target.result.createObjectStore("real time", {keyPath:'id',autoIncrement: true });
store.createIndex('time','time',{unique:false});
}
request.onsuccess = function (event) {
console.log(data);
db = this.result;
var tx = db.transaction("real time",'readwrite');
store = tx.objectStore("real time");
var obj = {
id:0,
time:data
}
var req = store.put(obj);
req.onsuccess = function (event) {
//console.log(obj+" insert in DB successful");
};
req.onerror = function (event) {
console.log(obj+" insert in DB error",this.error);
}
}
request.onerror = function (event) {
console.log("opendb:", event);
};
console.log(data);
})
})
複製程式碼