Sayfa Yaşam Döngüsü API'sı

Tarayıcı desteği

  • Chrome: 68.
  • Edge: 79.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Modern tarayıcılar, sistem kaynakları kısıtlandığında bazen sayfaları askıya alır veya tamamen siler. Tarayıcılar gelecekte daha az güç ve bellek tüketmek için bunu proaktif olarak yapmak istiyor. Sayfa Yaşam Döngüsü API'si, sayfalarınızın kullanıcı deneyimini etkilemeden bu tarayıcı müdahalelerini güvenli bir şekilde işleyebilmesi için yaşam döngüsü bağlantıları sağlar. Bu özellikleri uygulamanıza uygulamanız gerekip gerekmediğini görmek için API'ye göz atın.

Arka plan

Uygulama yaşam döngüsü, modern işletim sistemlerinin kaynakları yönetmesinin önemli bir yoludur. Android, iOS ve son Windows sürümlerinde uygulamalar, işletim sistemi tarafından herhangi bir zamanda başlatılıp durdurulabilir. Bu sayede bu platformlar, kaynakları kullanıcıya en çok fayda sağlayacak şekilde kolaylaştırıp yeniden dağıtabilir.

Web'de geçmişte böyle bir yaşam döngüsü olmamıştır ve uygulamalar süresiz olarak yayında kalabilir. Çok sayıda web sayfası çalışırken bellek, CPU, pil ve ağ gibi kritik sistem kaynaklarına fazla abone olunabilir. Bu da son kullanıcı deneyiminin kötüleşmesine neden olur.

Web platformunda uzun süredir yaşam döngüsü durumlarıyla ilgili load, unload ve visibilitychange gibi etkinlikler olsa da bu etkinlikler yalnızca geliştiricilerin kullanıcı tarafından başlatılan yaşam döngüsü durumu değişikliklerine yanıt vermesine olanak tanır. Web'in düşük güçlü cihazlarda güvenilir bir şekilde çalışması (ve genel olarak tüm platformlarda daha kaynak bilinçli olması) için tarayıcıların, sistem kaynaklarını proaktif olarak geri alma ve yeniden atama yöntemine ihtiyacı vardır.

Aslında günümüz tarayıcıları, arka plan sekmelerindeki sayfalar için kaynakları korumak amacıyla etkin önlemler alıyor. Birçok tarayıcı (özellikle Chrome), genel kaynak ayak izini azaltmak için bu tür önlemleri çok daha fazla almak istiyor.

Sorun, geliştiricilerin sistem tarafından başlatılan bu tür müdahalelere hazırlanamamaları veya bu müdahalelerin gerçekleştiğini bile bilmemeleridir. Bu nedenle, tarayıcıların muhafazakar olması veya web sayfalarının bozulma riskini göze alması gerekir.

Sayfa Yaşam Döngüsü API'si, aşağıdakileri yaparak bu sorunu çözmeye çalışır:

  • Web'de yaşam döngüsü durumları kavramının kullanıma sunulması ve standartlaştırılması.
  • Tarayıcıların gizli veya etkin olmayan sekmeler tarafından kullanılabilecek kaynakları sınırlamasına olanak tanıyan, sistem tarafından başlatılan yeni durumlar tanımlama.
  • Web geliştiricilerin, sistem tarafından başlatılan bu yeni durumlara geçişlere ve bu durumlardan çıkışlara yanıt vermesine olanak tanıyan yeni API'ler ve etkinlikler oluşturma.

Bu çözüm, web geliştiricilerin sistem müdahalelerine karşı dayanıklı uygulamalar oluşturmak için ihtiyaç duyduğu öngörülebilirliği sağlar ve tarayıcıların sistem kaynaklarını daha agresif bir şekilde optimize etmesine olanak tanır. Bu da nihayetinde tüm web kullanıcılarına fayda sağlar.

Bu gönderinin geri kalanında, yeni Sayfa Yaşam Döngüsü özelliklerini tanıtacak ve bunların mevcut tüm web platformu durumlarıyla ve etkinlikleriyle nasıl ilişkili olduğunu inceleyeceğiz. Ayrıca, geliştiricilerin her eyalette yapması gereken (ve yapmaması gereken) iş türleriyle ilgili öneriler ve en iyi uygulamalar da sağlanır.

Sayfa yaşam döngüsü durumlarına ve etkinliklerine genel bakış

Sayfa yaşam döngüsü durumlarının tümü ayrıdır ve birbirini hariç tutar. Yani bir sayfa aynı anda yalnızca bir durumda olabilir. Ayrıca, bir sayfanın yaşam döngüsü durumundaki çoğu değişiklik genellikle DOM etkinlikleri aracılığıyla gözlemlenebilir (istisnalar için her durum için geliştirici önerilerine bakın).

Sayfa yaşam döngüsü durumlarını ve bunlar arasındaki geçişleri gösteren etkinlikleri açıklamanın en kolay yolu bir şema kullanmaktır:

Bu belgede açıklanan durum ve etkinlik akışının görsel bir temsili.
Sayfa Yaşam Döngüsü API'si durumu ve etkinlik akışı.

Eyaletler

Aşağıdaki tabloda her durum ayrıntılı olarak açıklanmıştır. Ayrıca, bu duruma gelmeden önce ve sonra oluşabilecek durumların yanı sıra geliştiricilerin değişiklikleri gözlemlemek için kullanabileceği etkinlikleri de listeler.

Eyalet Açıklama
Etkin

Görünen ve giriş odağına sahip bir sayfa etkin durumdadır.

Olası önceki durumlar:
pasif (focus etkinliği aracılığıyla)
dondurulmuş (resume etkinliği, ardından pageshow etkinliği aracılığıyla)

Olası sonraki durumlar:
pasif ( blur etkinliği aracılığıyla)

Pasif

Görünen ve giriş odağına sahip olmayan bir sayfa pasif durumdadır.

Olası önceki durumlar:
etkin (blur etkinliği aracılığıyla)
gizli ( visibilitychange etkinliği aracılığıyla)
dondurulmuş (resume etkinliği, ardından pageshow etkinliği aracılığıyla)

Olası sonraki durumlar:
etkin (focus etkinliği aracılığıyla)
gizli ( visibilitychange etkinliği aracılığıyla)

Gizli

Görünmüyorsa (ve dondurulmamış, atılmamış veya sonlandırılmamışsa) bir sayfa gizli durumdadır.

Olası önceki durumlar:
pasif ( visibilitychange etkinliği aracılığıyla)
dondurulmuş (resume etkinliği, ardından pageshow etkinliği aracılığıyla)

Olası sonraki durumlar:
pasif ( visibilitychange etkinliği aracılığıyla)
dondurulmuş (freeze etkinliği aracılığıyla)
reddedildi (etkinlik tetiklenmedi)
feshedildi (etkinlik tetiklenmedi)

Donmuş

Dondurulmuş durumdayken tarayıcı, sayfanın dondurulması kaldırılana kadar sayfanın görev sıralarındaki dondurulabilir görevlerinin yürütülmesini askıya alır. Bu, JavaScript zamanlayıcıları ve getirme geri çağırma işlevleri gibi işlemlerin çalışmadığı anlamına gelir. Devam eden görevler tamamlanabilir (en önemlisi freeze geri çağırma işlevi), ancak yapabilecekleri ve ne kadar süre boyunca çalışabilecekleri sınırlı olabilir.

Tarayıcılar, CPU/pil/veri kullanımını korumak için sayfaları dondurur. Ayrıca, sayfanın tamamen yeniden yüklenmesi gerekmeden daha hızlı geri/ileri gezinme sağlamak için de bunu yapar.

Olası önceki durumlar:
gizli (freeze etkinliği aracılığıyla)

Olası sonraki durumlar:
etkin (resume etkinliği ve ardından pageshow etkinliği aracılığıyla)
pasif (resume etkinliği ve ardından pageshow etkinliği aracılığıyla)
gizli (resume etkinliği aracılığıyla)
reddedildi (etkinlik tetiklenmedi)

Fesih edildi

Bir sayfa, tarayıcı tarafından bellekten kaldırılmaya ve temizlenmeye başladıktan sonra sonlandırılmış durumdadır. Bu durumda yeni görevler başlatılamaz ve devam eden görevler çok uzun süre çalıştırılırsa iptal edilebilir.

Olası önceki durumlar:
gizli (pagehide etkinliği aracılığıyla)

Sonraki olası durumlar:
NONE

Silindi

Bir sayfa, tarayıcı tarafından kaynak tasarrufu sağlamak için yüklendiğinde silinen durumdadır. Atma işlemleri genellikle yeni işlemlerin başlatılamadığı kaynak kısıtlamaları altında gerçekleştiği için bu durumda hiçbir görev, etkinlik geri çağırma veya JavaScript çalıştırılamaz.

Atıldı durumunda, sayfa kaldırılmış olsa bile sekmenin kendisi (sekme başlığı ve simgesi dahil) genellikle kullanıcı tarafından görülebilir.

Olası önceki durumlar:
gizli (etkinlik tetiklenmez)
dondurulmuş (etkinlik tetiklenmez)

Sonraki olası durumlar:
NONE

Etkinlikler

Tarayıcılar çok sayıda etkinlik gönderir ancak bunların yalnızca küçük bir kısmı sayfa yaşam döngüsü durumunda olası bir değişiklik olduğunu gösterir. Aşağıdaki tabloda, yaşam döngüsü ile ilgili tüm etkinlikler özetlenmiştir ve bu etkinliklerin hangi durumlara geçiş yapabileceği listelenmiştir.

Ad Ayrıntılar
focus

Bir DOM öğesine odaklanılmıştır.

Not: focus etkinliği mutlaka durum değişikliğine işaret etmez. Yalnızca sayfa daha önce giriş odağına sahip değilse durum değişikliğini belirtir.

Olası önceki durumlar:
pasif

Olası mevcut durumlar:
etkin

blur

Bir DOM öğesi odağı kaybetti.

Not: blur etkinliği mutlaka durum değişikliğine işaret etmez. Yalnızca sayfa artık giriş odağına sahip değilse (yani sayfa odağını bir öğeden diğerine geçirmediyse) durum değişikliğini bildirir.

Olası önceki durumlar:
etkin

Olası mevcut durumlar:
pasif

visibilitychange

Dokümanın visibilityState değeri değişti. Bu durum, kullanıcı yeni bir sayfaya gittiğinde, sekme değiştirdiğinde, bir sekmeyi kapattığında, tarayıcıyı küçülttüğünde veya kapattığında ya da mobil işletim sistemlerinde uygulama değiştirdiğinde ortaya çıkabilir.

Olası önceki durumlar:
pasif
gizli

Olası mevcut durumlar:
pasif
gizli

freeze *

Sayfa kısa süre önce donduruldu. Sayfanın görev sıralarındaki dondurulabilir görevler başlatılmaz.

Olası önceki durumlar:
gizli

Olası mevcut durumlar:
dondurulmuş

resume *

Tarayıcı, donmuş bir sayfayı devam ettirmiştir.

Olası önceki durumlar:
dondurulmuş

Olası mevcut durumlar:
etkin (ardından pageshow etkinliği gelirse)
pasif (ardından pageshow etkinliği gelirse)
gizli

pageshow

Bir oturum geçmişi girişine gidiliyor.

Bu, yeni yüklenen bir sayfa veya geri/ileri önbellekten alınan bir sayfa olabilir. Sayfa, geri-ileri önbellekten alındıysa etkinliğin persisted özelliği true, aksi takdirde false olur.

Olası önceki durumlar:
dondurulmuş (resume etkinliği de tetiklenir)

Olası mevcut durumlar:
etkin
pasif
gizli

pagehide

Bir oturum geçmişi girişinden geçiliyor.

Kullanıcı başka bir sayfaya gidiyorsa ve tarayıcı mevcut sayfayı daha sonra yeniden kullanılacak şekilde geri/ileri önbelleğe ekleyebiliyorsa etkinliğin persisted mülkü true olur. true olduğunda sayfa dondurulmuş duruma, aksi takdirde sonlandırılmış duruma girer.

Olası önceki durumlar:
gizli

Olası mevcut durumlar:
dondurulmuş (event.persisted doğrudur, freeze etkinliği takip eder)
feshedilmiş (event.persisted yanlıştır, unload etkinliği takip eder)

beforeunload

Pencere, doküman ve kaynakları kaldırılmak üzere. Bu aşamada doküman hâlâ görünür durumdadır ve etkinlik iptal edilebilir.

Önemli: beforeunload etkinliği yalnızca kullanıcıyı kaydedilmemiş değişiklikler konusunda uyarmak için kullanılmalıdır. Bu değişiklikler kaydedildikten sonra etkinlik kaldırılır. Bazı durumlarda performansı olumsuz etkileyebileceğinden, bu dosya hiçbir zaman sayfaya koşulsuz olarak eklenmemelidir. Ayrıntılar için eski API'ler bölümüne bakın.

Olası önceki durumlar:
gizli

Olası mevcut durumlar:
terminated

unload

Sayfa boşaltılıyor.

Uyarı: Güvenilir olmadığı ve bazı durumlarda performansı olumsuz yönde etkileyebileceği için unload etkinliğinin kullanılması hiçbir zaman önerilmez. Daha fazla bilgi için eski API'ler bölümüne göz atın.

Olası önceki durumlar:
gizli

Olası mevcut durumlar:
terminated

* Page Lifecycle API tarafından tanımlanan yeni bir etkinliği gösterir

Chrome 68'de eklenen yeni özellikler

Önceki grafikte, kullanıcı tarafından değil sistem tarafından başlatılan iki durum gösterilmektedir: dondurulmuş ve reddedilmiş. Daha önce de belirtildiği gibi, günümüz tarayıcıları gizli sekmeleri zaman zaman dondurur ve kendi takdirine bağlı olarak atar. Ancak geliştiricilerin bu durumun ne zaman gerçekleştiğini öğrenmesi mümkün değildir.

Chrome 68'de geliştiriciler artık document üzerinde freeze ve resume etkinliklerini dinleyerek gizli bir sekmenin ne zaman dondurulduğunu ve ne zaman çözüldüğünü gözlemleyebilir.

document.addEventListener('freeze', (event) => {
  // The page is now frozen.
});

document.addEventListener('resume', (event) => {
  // The page has been unfrozen.
});

Chrome 68'den itibaren document nesnesi, masaüstü Chrome'da artık wasDiscarded mülkü içeriyor (Android desteği bu sorunda takip ediliyor). Bir sayfanın gizli sekmedeyken atlanıp atlamadığını belirlemek için sayfa yükleme sırasında bu özelliğin değerini inceleyebilirsiniz (not: Atlanan sayfaların tekrar kullanılabilmesi için yeniden yüklenmesi gerekir).

if (document.wasDiscarded) {
  // Page was previously discarded by the browser while in a hidden tab.
}

freeze ve resume etkinliklerinde yapılması gereken önemli işlemler ve sayfaların atılmasına karşı nasıl hazırlık yapılacağı ve bu durumla nasıl başa çıkılacağı hakkında öneriler için her durum için geliştirici önerilerine göz atın.

Sonraki birkaç bölümde, bu yeni özelliklerin mevcut web platformu durum ve etkinliklerine nasıl uyduğuna dair genel bir bakış sunulmaktadır.

Sayfa yaşam döngüsü durumlarını kodda gözlemleme

Etkin, pasif ve gizli durumlarda, mevcut web platformu API'lerinden mevcut Sayfa Yaşam Döngüsü durumunu belirleyen JavaScript kodu çalıştırılabilir.

const getState = () => {
  if (document.visibilityState === 'hidden') {
    return 'hidden';
  }
  if (document.hasFocus()) {
    return 'active';
  }
  return 'passive';
};

Öte yandan dondurulmuş ve sonlandırılmış durumları, yalnızca durum değiştikçe ilgili etkinlik dinleyicisinde (freeze ve pagehide) algılanabilir.

Durum değişikliklerini gözlemleme

Daha önce tanımlanan getState() işlevini temel alarak, aşağıdaki kodla tüm sayfa yaşam döngüsü durumu değişikliklerini gözlemleyebilirsiniz.

// Stores the initial state using the `getState()` function (defined above).
let state = getState();

// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
  const prevState = state;
  if (nextState !== prevState) {
    console.log(`State change: ${prevState} >>> ${nextState}`);
    state = nextState;
  }
};

// Options used for all event listeners.
const opts = {capture: true};

// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
  window.addEventListener(type, () => logStateChange(getState()), opts);
});

// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
  // In the freeze event, the next state is always frozen.
  logStateChange('frozen');
}, opts);

window.addEventListener('pagehide', (event) => {
  // If the event's persisted property is `true` the page is about
  // to enter the back/forward cache, which is also in the frozen state.
  // If the event's persisted property is not `true` the page is
  // about to be unloaded.
  logStateChange(event.persisted ? 'frozen' : 'terminated');
}, opts);

Bu kod üç işlevi yerine getirir:

  • getState() işlevini kullanarak ilk durumu belirler.
  • Bir sonraki durumu kabul eden ve değişiklik varsa durum değişikliklerini konsola kaydeden bir işlev tanımlar.
  • Gerekli tüm yaşam döngüsü etkinlikleri için yakalama etkinlik işleyicileri ekler. Bu işleyiciler de logStateChange()'yi çağırarak bir sonraki durumu iletir.

Kodla ilgili dikkat edilmesi gereken bir nokta, tüm etkinlik işleyicilerin window öğesine eklenmesi ve hepsinin {capture: true} öğesini iletmesidir. Bu durumun birkaç nedeni vardır:

  • Sayfa yaşam döngüsü etkinliklerinin tümü aynı hedefe sahip değildir. pagehide ve pageshow, window üzerinde; visibilitychange, freeze ve resume, document üzerinde; focus ve blur ise kendi DOM öğelerinde tetiklenir.
  • Bu etkinliklerin çoğu kabarcık oluşturmaz. Yani, ortak bir üst öğeye yakalamayan etkinlik işleyicileri eklemek ve bunların tümünü gözlemlemek mümkün değildir.
  • Yakalama aşaması, hedef veya balon aşamalarından önce yürütülür. Bu nedenle, dinleyicileri buraya eklemek, diğer kodlar tarafından iptal edilmeden önce çalıştıklarından emin olmanıza yardımcı olur.

Her eyalet için geliştirici önerileri

Geliştiriciler olarak, hem sayfa yaşam döngüsü durumlarını anlamanız hem de bunları kodda nasıl gözlemleyeceğinizi bilmeniz önemlidir. Yapmanız gereken (ve yapmamanız gereken) iş türü büyük ölçüde sayfanızın hangi durumda olduğuna bağlıdır.

Örneğin, sayfa gizli durumdaysa kullanıcıya geçici bir bildirim göstermenin bir anlamı yoktur. Bu örnek oldukça açık olsa da, bu kadar açık olmayan ve belirtilmeye değer başka öneriler de vardır.

Eyalet Geliştirici önerileri
Active

Etkin durumu, kullanıcı için en kritik zamandır ve bu nedenle, sayfanızı kullanıcı girişine duyarlı hale getirmenin en önemli zamanıdır.

Ana iş parçacığının çalışmasını engelleyebilecek kullanıcı arayüzü dışındaki tüm çalışmaların önceliği boş zamanlara ayarlanmalı veya bir web çalışanına aktarılmalıdır.

Passive

Pasif durumdaki kullanıcılar sayfayla etkileşime geçmez ancak sayfayı görmeye devam eder. Bu, kullanıcı arayüzü güncellemelerinin ve animasyonlarının sorunsuz olmaya devam edeceği ancak bu güncellemelerin zamanlamasının daha az önemli olacağı anlamına gelir.

Sayfa etkin durumundan pasif duruma geçtiğinde, kaydedilmemiş uygulama durumunu kaydetme zamanı gelmiştir.

Hidden

Sayfa pasif durumundan gizli duruma geçtiğinde, kullanıcı sayfayı yeniden yükleyene kadar sayfayla tekrar etkileşime geçemeyebilir.

Gizli durumuna geçiş, genellikle geliştiriciler tarafından güvenilir bir şekilde gözlemlenebilen son durum değişikliğidir (Kullanıcılar sekmeleri veya tarayıcı uygulamasını kapatabileceğinden ve bu durumlarda beforeunload, pagehide ve unload etkinlikleri tetiklenmediğinden bu durum özellikle mobil cihazlarda geçerlidir).

Bu nedenle, gizli durumunu kullanıcı oturumunun muhtemel sonu olarak değerlendirmeniz gerekir. Başka bir deyişle, kaydedilmemiş uygulama durumlarını kaydedin ve gönderilmemiş analiz verilerini gönderin.

Ayrıca, kullanıcı tarafından görülemeyecekleri için kullanıcı arayüzü güncellemeleri yapmayı ve kullanıcının arka planda çalışmasını istemeyeceği tüm görevleri durdurmayı da bırakmanız gerekir.

Frozen

Dondurulmuş durumdayken, görev sıralarındaki dondurulabilir görevler, sayfanın dondurulması kaldırılana kadar askıya alınır.Bu durum hiçbir zaman gerçekleşmeyebilir (ör. sayfa atlanırsa).

Bu nedenle, sayfa gizli durumundan dondurulmuş duruma geçtiğinde, dondurulduğunda aynı kaynaktaki diğer açık sekmeleri veya tarayıcının sayfayı geri/ileri önbelleğe koyma özelliğini etkileyebilecek tüm zamanlayıcıları durdurmanız veya bağlantıları kaldırmanız gerekir.

Özellikle şunları yapmanız önemlidir:

Ayrıca, sayfa atlanıp daha sonra yeniden yüklenirse geri yüklemek istediğiniz tüm dinamik görüntüleme durumlarını (ör. sonsuz liste görünümündeki kaydırma konumu) sessionStorage (veya commit() üzerinden IndexedDB) kaydetmeniz gerekir.

Sayfa dondurulmuş durumundan gizli durumuna geçerse kapalı bağlantıları yeniden açabilir veya sayfa ilk kez dondurulduğunda durdurduğunuz anketleri yeniden başlatabilirsiniz.

Terminated

Bir sayfa feshedilmiş durumuna geçtiğinde genellikle herhangi bir işlem yapmanız gerekmez.

Kullanıcı işlemi sonucunda boşaltılan sayfalar her zaman feshedilmiş durumuna girmeden önce gizli durumundan geçtiğinden, oturumu sonlandırma mantığının (ör. uygulama durumunu kalıcı kılma ve Analytics'e raporlama) gizli durumunda gerçekleştirilmesi gerekir.

Ayrıca (Gizli durumla ilgili önerilerde belirtildiği gibi), geliştiricilerin sonlandırılmış duruma geçişin birçok durumda (özellikle mobil cihazlarda) güvenilir bir şekilde algılanamayacağını fark etmesi çok önemlidir.Bu nedenle, sonlandırma etkinliklerine (ör. beforeunload, pagehide ve unload) dayanan geliştiriciler büyük olasılıkla veri kaybediyordur.

Discarded

Atıldı durumu, sayfa atıldığında geliştiriciler tarafından görülemez. Bunun nedeni, sayfaların genellikle kaynak kısıtlamaları nedeniyle atılması ve bir sayfanın dondurulmasının, yalnızca komut dosyasının bir atma etkinliğine yanıt olarak çalışmasına izin vermek için çoğu durumda mümkün olmamasıdır.

Sonuç olarak, gizli olan bir sayfanın dondurulmuş olarak değiştirilmesi durumunda sayfanın silinmesine hazırlıklı olmalısınız. Ardından, silinen bir sayfanın sayfa yükleme sırasında geri yüklenmesine tepki vermek için document.wasDiscarded seçeneğini işaretleyebilirsiniz.

Yaşam döngüsü etkinliklerinin güvenilirliği ve sıralaması tüm tarayıcılarda tutarlı bir şekilde uygulanmadığından, tablodaki önerileri uygulamanın en kolay yolu PageLifecycle.js'i kullanmaktır.

Kullanılmaması gereken eski yaşam döngüsü API'leri

Mümkün olduğunda aşağıdaki etkinliklerden kaçınılmalıdır.

Boşaltma etkinliği

Birçok geliştirici, unload etkinliğini garantili bir geri çağırma olarak değerlendirir ve durumu kaydetmek ve analiz verilerini göndermek için oturum sonu sinyali olarak kullanır. Ancak bunu yapmak, özellikle mobil cihazlarda son derece güvenilir değildir. unload etkinliği, mobil cihazlardaki sekme değiştiriciden bir sekmenin kapatılması veya uygulama değiştiriciden tarayıcı uygulamasının kapatılması gibi birçok tipik boşaltma durumunda tetiklenmez.

Bu nedenle, oturumun ne zaman sona erdiğini belirlemek için her zaman visibilitychange etkinliğini kullanmak ve gizli durumu uygulama ve kullanıcı verilerini kaydetmek için güvenilir son zaman olarak değerlendirmek daha iyidir.

Ayrıca, kayıtlı bir unload etkinlik işleyicisinin (onunload veya addEventListener() aracılığıyla) varlığı bile tarayıcıların geri ve ileri yüklemelerin daha hızlı olması için sayfaları geri/ileri önbelleğe koymasını engelleyebilir.

Tüm modern tarayıcılarda, olası sayfa boşaltma işlemlerini (diğer adıyla sonlandırılmış durumu) algılamak için her zaman unload etkinliği yerine pagehide etkinliğini kullanmanız önerilir. Internet Explorer 10 ve önceki sürümleri desteklemeniz gerekiyorsa pagehide etkinliğini algılamalı ve tarayıcı pagehide'yi desteklemiyorsa yalnızca unload'ü kullanmalısınız:

const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';

window.addEventListener(terminationEvent, (event) => {
  // Note: if the browser is able to cache the page, `event.persisted`
  // is `true`, and the state is frozen rather than terminated.
});

beforeunload etkinliği

beforeunload etkinliğinin unload etkinliğiyle benzer bir sorunu vardır. Bu sorun, geçmişte beforeunload etkinliğinin varlığı sayfaların geri/ileri önbelleğe uygun olmasını engelleyebiliyordu. Bu kısıtlama, modern tarayıcılarda geçerli değildir. Ancak bazı tarayıcılar, bir sayfayı geri/ileri önbelleğe yerleştirmeye çalışırken önlem olarak beforeunload etkinliğini tetiklemez. Bu da etkinliğin oturum sonu sinyali olarak güvenilir olmadığı anlamına gelir. Ayrıca, bazı tarayıcılar (Chrome dahil) beforeunload etkinliğinin tetiklenmesine izin vermeden önce sayfa üzerinde kullanıcı etkileşimi gerektirir. Bu da güvenilirliğini daha da etkiler.

beforeunload ile unload arasındaki farklardan biri, beforeunload'ün meşru kullanım alanları olmasıdır. Örneğin, sayfayı boşaltmaya devam ederse kaydedilmemiş değişikliklerini kaybedeceği konusunda kullanıcıyı uyarmak istediğinizde.

beforeunload'ü kullanmanın geçerli nedenleri olduğundan, beforeunload dinleyicilerini yalnızca kullanıcının kaydedilmemiş değişiklikleri olduğunda eklemeniz ve değişiklikler kaydedildikten hemen sonra kaldırmanız önerilir.

Başka bir deyişle, koşulsuz olarak bir beforeunload dinleyici eklediği için bunu yapmayın:

addEventListener('beforeunload', (event) => {
  // A function that returns `true` if the page has unsaved changes.
  if (pageHasUnsavedChanges()) {
    event.preventDefault();

    // Legacy support for older browsers.
    return (event.returnValue = true);
  }
});

Bunun yerine, beforeunload dinleyicisini yalnızca gerektiğinde ekleyip gerekmediğinde kaldıracağı için aşağıdakileri yapın:

const beforeUnloadListener = (event) => {
  event.preventDefault();
  
  // Legacy support for older browsers.
  return (event.returnValue = true);
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  removeEventListener('beforeunload', beforeUnloadListener);
});

SSS

Neden "yükleniyor" durumu yok?

Sayfa Yaşam Döngüsü API'si, durumları ayrı ve birbirini hariç tutacak şekilde tanımlar. Bir sayfa etkin, pasif veya gizli durumda yüklenebilir ve yükleme işlemi tamamlanmadan önce durum değiştirebilir ya da sonlandırılabilir. Bu nedenle, bu paradigmada ayrı bir yükleme durumu anlamlı değildir.

Sayfam gizliyken önemli bir işlev görüyor. Sayfamın dondurulmasını veya atılmasını nasıl önleyebilirim?

Web sayfalarının gizli durumda çalışırken dondurulmamasının birçok geçerli nedeni vardır. En belirgin örnek, müzik çalan bir uygulamadır.

Chrome'un bir sayfayı atmasının riskli olduğu durumlar da vardır. Örneğin, sayfa gönderilmemiş kullanıcı girişi içeren bir form içeriyorsa veya sayfayı boşaltırken uyarı veren bir beforeunload işleyicisi varsa.

Şu anda Chrome, sayfaları silerken ihtiyatlı davranacak ve bunu yalnızca kullanıcıları etkilemeyeceğinden emin olduğunda yapacak. Örneğin, gizli durumdayken aşağıdakilerden herhangi birini yaptığı gözlemlenen sayfalar, aşırı kaynak kısıtlamaları altında olmadığı sürece atılmaz:

  • Ses çalma
  • WebRTC'yi kullanma
  • Tablo başlığını veya simgesini güncelleme
  • Uyarıları gösterme
  • Push bildirimleri gönderme

Bir sekmenin güvenli bir şekilde dondurulup dondurulamayacağını veya silinip silinemeyeceğini belirlemek için kullanılan mevcut liste özellikleri için Chrome'daki Dondurma ve Silme İçin Heuristics bölümüne bakın.

Geri-ileri önbellek nedir?

Geri/ileri önbelleği, bazı tarayıcıların uyguladığı ve geri ve ileri düğmelerinin daha hızlı kullanılmasını sağlayan bir gezinme optimizasyonunu tanımlamak için kullanılan bir terimdir.

Bu tarayıcılar, kullanıcı bir sayfadan ayrıldığında sayfanın bir sürümünü dondurur. Böylece, kullanıcı geri veya ileri düğmelerini kullanarak geri döndüğünde sayfaya hızlıca devam edilebilir. unloadBir etkinlik işleyici eklemenin bu optimizasyonun yapılmasını engellediğini unutmayın.

Her açıdan bu dondurma işlemi, CPU/pil tasarrufu yapmak için tarayıcıların gerçekleştirdiği dondurma işlemiyle işlevsel olarak aynıdır. Bu nedenle, dondurulmuş yaşam döngüsü durumunun bir parçası olarak kabul edilir.

Asenkron API'leri dondurulmuş veya sonlandırılmış durumda çalıştıramıyorum. Verileri IndexedDB'e nasıl kaydedebilirim?

Dondurulmuş ve sonlandırılmış durumlarda, sayfanın görev sıralarındaki dondurulabilir görevler askıya alınır. Bu da IndexedDB gibi asenkron ve geri çağırma tabanlı API'lerin güvenilir bir şekilde kullanılamayacağı anlamına gelir.

Gelecekte, IDBTransaction nesnelerine bir commit() yöntemi ekleyeceğiz. Bu yöntem, geliştiricilere geri çağırma gerektirmeyen, yalnızca yazma işlemi olan işlemleri etkili bir şekilde gerçekleştirme olanağı sunacaktır. Diğer bir deyişle, geliştirici yalnızca IndexedDB'e veri yazıyorsa ve okuma ve yazma işlemlerinden oluşan karmaşık bir işlem gerçekleştirmiyorsa commit() yöntemi, görev sıraları askıya alınmadan önce tamamlanabilir (IndexedDB veritabanının zaten açık olduğu varsayılır).

Ancak, şu anda çalışması gereken kod için geliştiricilerin iki seçeneği vardır:

  • Oturum Depolama'yı kullanın: Oturum Depolama senkronizedir ve sayfa atıldığında devam eder.
  • Hizmet çalışanınızdan IndexedDB'i kullanın: Hizmet çalışanları, sayfa sonlandırıldıktan veya atıldıktan sonra verileri IndexedDB'de saklayabilir. freeze veya pagehide etkinlik dinleyicisinde, postMessage() aracılığıyla servis çalışanınıza veri gönderebilirsiniz. Servis çalışanı, verileri kaydedebilir.

Uygulamanızı dondurulmuş ve reddedilmiş durumlarda test etme

Uygulamanızın dondurulmuş ve atılmış durumlarda nasıl davrandığını test etmek için açık sekmelerinizi dondurmak veya atmak üzere chrome://discards sayfasını ziyaret edebilirsiniz.

Chrome'un Kullanılmayan Verileri Silme Kullanıcı Arayüzü
Chrome Discards kullanıcı arayüzü

Bu sayede, sayfanızı freeze ve resume etkinliklerinin yanı sıra sayfalar silindikten sonra yeniden yüklendiğinde document.wasDiscarded işaretini doğru şekilde işlemesini sağlayabilirsiniz.

Özet

Kullanıcılarının cihazlarının sistem kaynaklarına saygı göstermek isteyen geliştiriciler, uygulamalarını sayfa yaşam döngüsü durumlarını göz önünde bulundurarak oluşturmalıdır. Web sayfalarının, kullanıcının beklemediği durumlarda aşırı sistem kaynağı tüketmemesi kritik önem taşır.

Ne kadar çok geliştirici yeni Sayfa Yaşam Döngüsü API'lerini uygulamaya başlarsa tarayıcıların kullanılmayan sayfaları dondurması ve atması o kadar güvenli olur. Bu, tarayıcıların daha az bellek, CPU, pil ve ağ kaynağı tüketeceği anlamına gelir. Bu da kullanıcılar için bir avantajdır.