近百年來,Betty Crocker 一直是美國現代烹飪教學和值得信賴的食譜開發來源。該公司於 1997 年推出 BettyCrocker.com 網站,如今每月訪客人數超過 1, 200 萬。導入 Wake Lock API 後,與所有使用者相比,使用 Wake Lock 的使用者購買意願指標提升了約 300%。
已淘汰的 iOS 和 Android 應用程式
Betty Crocker 的應用程式於 2014 年盛大推出,但最近因優先順序降低,已從 Apple App Store 和 Google Play 商店下架。長期以來,Betty Crocker 團隊偏好在行動網站上新增功能,而非 iOS/Android 應用程式。iOS/Android 應用程式的技術平台已過時,且商家沒有資源來支援應用程式的更新和維護作業。就流量而言,網頁應用程式也明顯較大, 而且更現代化,也更容易強化。
不過,iOS/Android 應用程式確實有一項殺手級功能深受使用者喜愛:
千禧世代的烹飪專業提示:使用 @BettyCrocker 行動應用程式時,螢幕不會變暗或鎖定,—@AvaBeilke
80% 的人會在廚房使用裝置烹調料理,但螢幕變暗和鎖定是個問題。 @BettyCrocker 做了什麼? 更新應用程式,讓使用者在食譜中時,應用程式不會變暗。 —@KatieTweedy
使用 Wake Lock API 將殺手級功能帶到網頁
使用裝置烹調時,最令人沮喪的事莫過於螢幕關閉時,必須用髒手或甚至鼻子觸碰螢幕。Betty Crocker 團隊自問,如何將 iOS/Android 應用程式的殺手級功能移植到網頁應用程式。此時,他們瞭解了 Project Fugu 和 Wake Lock API。

Wake Lock API 可防止裝置調暗或鎖定螢幕。這項功能可提供全新體驗,而這類體驗過去需要 iOS/Android 應用程式才能實現。Wake Lock API 可減少對耗電量可能較高的權宜解決方案的需求。
要求 Wake Lock
如要要求喚醒鎖定,您需要呼叫 navigator.wakeLock.request() 方法,該方法會傳回 WakeLockSentinel 物件。您會將這個物件做為哨兵值。
瀏覽器可能會因各種原因拒絕要求 (例如電池電量過低),因此建議將呼叫包裝在 try…catch 陳述式中。
釋放 Wake Lock
您還需要釋放喚醒鎖定的方法,也就是呼叫 WakeLockSentinel 物件的 release() 方法。如要在經過一段時間後自動釋放喚醒鎖定,可以使用 window.setTimeout() 呼叫 release(),如下列範例所示。
// The wake lock sentinel.
let wakeLock = null;
// Function that attempts to request a wake lock.
const requestWakeLock = async () => {
try {
wakeLock = await navigator.wakeLock.request('screen');
wakeLock.addEventListener('release', () => {
console.log('Wake Lock was released');
});
console.log('Wake Lock is active');
} catch (err) {
console.error(`${err.name}, ${err.message}`);
}
};
// Request a wake lock…
await requestWakeLock();
// …and release it again after 5s.
window.setTimeout(() => {
wakeLock.release();
wakeLock = null;
}, 5000);
實作
有了這項新功能,使用者就能輕鬆瀏覽食譜、完成步驟,甚至在不鎖定螢幕的情況下離開。為達成這個目標,團隊首先建構了快速前端原型,做為概念驗證並收集使用者體驗輸入內容。
原型證明實用性後,他們設計了 Vue.js 元件,可供所有品牌 (BettyCrocker、Pillsbury 和 Tablespoon) 共用。雖然只有 Betty Crocker 推出 iOS 和 Android 應用程式,但這三個網站共用程式碼集,因此只要實作一次元件,就能部署到所有平台,如下方螢幕截圖所示。
根據新網站的現代化架構開發元件時,我們著重於 MVVM 模式的 ViewModel 層。此外,團隊在程式設計時也考量到互通性,以便在網站的舊架構和新架構上啟用功能。
為了追蹤可視性和可用性,Betty Crocker 針對喚醒鎖定生命週期中的核心事件,整合了 Analytics 追蹤功能。該團隊運用功能管理,將喚醒鎖定元件部署至單一網站,進行初步的正式版推出作業,然後監控使用情形和網頁健康狀態,再將這項功能部署至其餘網站。他們會繼續根據這個元件的使用情況監控 Analytics 資料。
為確保使用者安全,團隊建立強制逾時機制,在閒置一小時後停用喚醒鎖定。他們最終決定在網站的所有食譜頁面上,短期內導入切換按鈕。長期而言,他們希望重新設計食譜頁面檢視畫面。
Wake Lock 容器
var wakeLockControl = () => {
return import(/* webpackChunkName: 'wakeLock' */ './wakeLock');
};
export default {
components: {
wakeLockControl: wakeLockControl,
},
data() {
return {
config: {},
wakeLockComponent: '',
};
},
methods: {
init: function(config) {
this.config = config || {};
if ('wakeLock' in navigator && 'request' in navigator.wakeLock) {
this.wakeLockComponent = 'wakeLockControl';
} else {
console.log('Browser not supported');
}
},
},
};
Wake Lock 元件
<template>
<div class="wakeLock">
<div class="textAbove"></div>
<label class="switch" :aria-label="settingsInternal.textAbove">
<input type="checkbox" @change="onChange()" v-model="isChecked">
<span class="slider round"></span>
</label>
</div>
</template>
<script type="text/javascript">
import debounce from 'lodash.debounce';
const scrollDebounceMs = 1000;
export default {
props: {
settings: { type: Object },
},
data() {
return {
settingsInternal: this.settings || {},
isChecked: false,
wakeLock: null,
timerId: 0,
};
},
created() {
this.$_raiseAnalyticsEvent('Wake Lock Toggle Available');
},
methods: {
onChange: function() {
if (this.isChecked) {
this.$_requestWakeLock();
} else {
this.$_releaseWakeLock();
}
},
$_requestWakeLock: async function() {
try {
this.wakeLock = await navigator.wakeLock.request('screen');
//Start new timer
this.$_handleAbortTimer();
//Only add event listeners after wake lock is successfully enabled
document.addEventListener(
'visibilitychange',
this.$_handleVisibilityChange,
);
window.addEventListener(
'scroll',
debounce(this.$_handleAbortTimer, scrollDebounceMs),
);
this.$_raiseAnalyticsEvent('Wake Lock Toggle Enabled');
} catch (e) {
this.isChecked = false;
}
},
$_releaseWakeLock: function() {
try {
this.wakeLock.release();
this.wakeLock = null;
//Clear timer
this.$_handleAbortTimer();
//Clean up event listeners
document.removeEventListener(
'visibilitychange',
this.$_handleVisibilityChange,
);
window.removeEventListener(
'scroll',
debounce(this.$_handleAbortTimer, scrollDebounceMs),
);
} catch (e) {
console.log(`Wake Lock Release Error: ${e.name}, ${e.message}`);
}
},
$_handleAbortTimer: function() {
//If there is an existing timer then clear it and set to zero
if (this.timerId !== 0) {
clearTimeout(this.timerId);
this.timerId = 0;
}
//Start new timer; Will be triggered from toggle enabled or scroll event
if (this.isChecked) {
this.timerId = setTimeout(
this.$_releaseWakeLock,
this.settingsInternal.timeoutDurationMs,
);
}
},
$_handleVisibilityChange: function() {
//Handle navigating away from page/tab
if (this.isChecked) {
this.$_releaseWakeLock();
this.isChecked = false;
}
},
$_raiseAnalyticsEvent: function(eventType) {
let eventParams = {
EventType: eventType,
Position: window.location.pathname || '',
};
Analytics.raiseEvent(eventParams);
},
},
};
</script>
結果
Vue.js 元件已部署在所有三個網站上,並帶來出色的成效。 2019 年 12 月 10 日至 2020 年 1 月 10 日期間,BettyCrocker.com 網站的指標如下:
- 在所有使用與 Wake Lock API 相容瀏覽器的 Betty Crocker 使用者中,有 3.5% 的使用者立即啟用這項功能,成為前 5 大動作。
- 啟用喚醒鎖定的使用者工作階段時間長度,比未啟用者長 3.1 倍。
- 啟用喚醒鎖定的使用者跳出率,比未使用這項功能的使用者低 50%。
- 相較於所有使用者,使用喚醒鎖定的使用者購買意願指標高出約 300%。
3.1×
工作階段持續時間較長
50%
跳出率降低
300%
購買意願指標較高
結論
Betty Crocker 使用 Wake Lock API 後,獲得了絕佳成效。如要自行測試這項功能,請在上述任一網站 (BettyCrocker、Pillsbury 或 Tablespoon) 搜尋喜愛的食譜,然後啟用「烹飪時防止螢幕變暗」切換鈕。
喚醒鎖定的用途不只適用於食譜網站。其他範例包括:需要保持螢幕開啟直到條碼掃描完畢的登機證或票券應用程式、持續保持螢幕開啟的資訊站式應用程式,或是防止螢幕在簡報期間進入休眠狀態的網頁簡報應用程式。
我們已在本網站的全面性文章中,彙整您需要瞭解的 Wake Lock API 相關資訊。祝您閱讀愉快,並享受烹飪樂趣!