Chrome 108 引入了两种新模式:省内存模式和节能模式,让用户能够更好地控制 Chrome 使用系统资源的方式。
虽然这些新模式主要面向用户,但是它们对网站开发者来说确实有一些重要的意义,因为它们可能会影响您网站的用户体验。
这篇博文将介绍这些新模式的潜在影响,以及 Web 开发者可采取哪些措施来确保提供尽可能出色的体验。
省内存模式
启用省内存模式后,Chrome 会主动舍弃已在后台闲置一段时间的标签页。这会为活动标签页和可能正在运行的其他应用释放内存。用户可以指示 Chrome 不为特定网站舍弃标签页;不过,这属于用户偏好设置,您作为开发者无法控制。
舍弃标签页后,其标题和网站图标仍会显示在标签页栏中,但页面本身会消失,就像标签页正常关闭一样。如果用户再次访问该标签页,页面会自动重新加载。
对于纯内容网页,舍弃并重新加载标签页可能不会影响用户体验,但对于用户流的丰富且互动性较强的网站,如果网站无法将网页恢复到用户上次离开的位置,那么在流程中间进行重新加载可能会非常令人沮丧。
舍弃标签页以节省内存是 Chrome 多年来一直采用的做法,但只能在系统面临内存压力的情况下这样做。由于这种现象相对罕见,网络开发者可能没有意识到这一点。
从 Chrome 108 开始,舍弃标签页将变得越来越常见,因此网站必须妥善处理这类情况,这一点至关重要。
处理标签页舍弃的最佳做法
标签页舍弃并非 Web 开发者面临的一项新挑战。用户在完成任务之前随时可能(无论是有意还是无意)重新加载页面。因此,网站必须存储用户状态,以便在用户离开和返回时恢复用户状态。
最重要的考虑因素不是是否存储用户状态,而是何时存储用户状态。这一点很关键,因为没有在标签页被舍弃时触发的事件,因此开发者无法对这种情况做出反应。相反,开发者需要预测这种可能性,并提前做好准备。
存储用户状态的最佳时机如下:
- 当状态发生变化时定期检查。
- 每当标签页在后台运行时(
visibilitychange
事件)。
存储状态的最坏时间如下:
- 在
beforeunload
事件回调中。 - 在
unload
事件回调中。
这些是最糟糕的状态存储时间,因为这些事件完全不可靠,并且在很多情况下(包括标签页被舍弃时)也不会触发。
您可以参考页面生命周期事件示意图,了解在网页被舍弃时预期会触发哪些事件。从该图中可以看出,标签页可以从“隐藏”状态变为“已舍弃”状态,而不触发任何事件。
事实上,只要网页处于“隐藏”状态,并不保证在网页被浏览器舍弃或用户终止之前触发任何其他事件,因此请务必将所有未保存的用户状态存储在 visibilitychange
事件中,因为您可能没有其他机会。
以下代码概述了一些示例逻辑,该逻辑会在当前用户状态发生变化时将其加入队列,或者在用户转到后台或用户离开标签页时立即保留当前用户状态:
let state = {};
let hasUnstoredState = false;
function storeState() {
if (hasUnstoredState) {
// Store `state` to localStorage or IndexedDB...
}
hasUnstoredState = false;
}
export function updateState(newState) {
state = newState;
hasUnstoredState = true;
requestIdleCallback(storeState);
}
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
storeState();
}
});
检测到标签页被舍弃
如前所述,我们无法检测出某个标签页即将被舍弃,但可以检测到某个标签页在用户返回到标签页并重新加载后被舍弃。在这些情况下,document.wasDiscarded
属性将为 true。
if (document.wasDiscarded) {
// The page was reloaded after a discard.
} else {
// The page was not reloaded after a discard.
}
如果您想了解用户遇到这类情况的频率,可以配置您的分析工具来捕获这些信息。
例如,在 Google Analytics(分析)中,您可以配置自定义事件参数,以确定来自标签页舍弃的网页浏览量所占的百分比:
gtag('config', 'G-XXXXXXXXXX', {
was_discarded: document.wasDiscarded,
});
如果您是分析服务提供商,可以考虑默认将此维度添加到您的产品中。
在省内存模式下测试您的网站
您可以加载网页,然后在单独的标签页或窗口中访问 chrome://discards
,以测试该网页被舍弃的情况。
在 chrome://discards
界面中,您可以找到要从列表中舍弃的标签页,然后点击操作列中的紧急舍弃。
此操作会舍弃该标签页,以便您重新访问该标签页,并验证该网页是否已重新加载到您离开时的状态。
请注意,目前没有办法通过 webdriver 或 puppeteer 等测试工具自动执行标签页舍弃操作;但是,由于标签页舍弃和恢复操作与页面重新加载几乎完全相同,如果您测试在用户流过程中重新加载后用户状态是否恢复,则可能也适用于舍弃/恢复操作。两者之间的主要区别是 beforeunload
、pagehide
和 unload
事件不会在标签页被舍弃时触发,因此只要您不依赖这些事件来保留用户状态,您就可以使用重新加载来测试舍弃/恢复行为。
节能模式
启用节能模式后,Chrome 会通过降低显示屏刷新率来节省电池电量,因为这类操作会影响滚动和动画保真度以及视频帧速率。
一般来说,开发者无需执行任何操作即可支持节能模式。启用该模式后,用于动画、过渡和 requestAnimationFrame()
的 CSS API 和 JavaScript API 会自动适应显示屏刷新频率的任何变化。
此模式可能存在问题的主要原因是,您的网站使用了基于 JavaScript 的动画,假定所有用户的刷新频率都较高。
例如,如果您的网站使用 requestAnimationFrame()
循环,并假设两次回调之间经过了正好 16.67 毫秒,那么在启用节能模式后,动画的运行速度会延长一倍。
请注意,如果开发者假定所有用户的默认刷新率为 60 Hz,则一直都是有问题,因为目前的许多设备并非如此。
测量显示屏刷新率
没有可用于测量显示屏刷新率的专用 Web API,一般而言,不建议使用最新的 API 来测量。
开发者使用现有 API 可以实现的最佳方法是比较连续 requestAnimationFrame()
回调之间的时间戳。虽然在大多数情况下,这可以估算给定时间点的刷新率,但并不会让您知道刷新率何时发生变化。为此,您必须不断运行 requestAnimationFrame()
轮询,这违背了为用户节省能源或电池续航时间的目标。
在节能模式下测试您的网站
若要在节能模式下测试您的网站,一种方法是在 Chrome 设置中启用该模式,然后将该模式配置为在设备未接通电源时运行。
如果您没有可拔下电源的设备,也可以按照以下步骤手动启用该模式:
- 启用
chrome://flags/#battery-saver-mode-available
标志。 - 访问
chrome://discards
,然后点击切换省电模式链接(重要提示:需要启用#battery-saver-mode-available
标志才能让链接生效)。
启用后,您便可以与网站交互,验证所有内容是否均正常显示:例如,动画和过渡是否以期望的速度运行。
摘要
虽然 Chrome 的省内存模式和节能模式主要是面向用户的功能,但它们确实会对开发者造成影响,因为如果处理不当,可能会对您网站的访问体验产生负面影响。
一般来说,这些新模式的设计遵循了现有的开发者最佳实践。如果开发者一直遵循长期的网络最佳实践,他们的网站应该能够继续在这些新模式下正常运行。
但是,如果您的网站包含本博文中提到的任何做法,您的用户可能会遇到的问题可能会在启用这两种模式后增加。
与往常一样,确认您的网站是否提供良好体验的最佳方法是,在符合用户条件的情况下测试您的网站。