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

Philip Walton
Philip Walton

Tarayıcı desteği

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

Modern tarayıcılar, sistem kaynakları kısıtlandığında bazen sayfaları askıya alır veya tamamen siler. Gelecekte tarayıcılar bunu proaktif olarak yapmak isteyecek, bu nedenle daha az güç ve bellek tüketecektir. Page Lifecycle API, 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ü kancaları 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ılabilir ve 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 şu ki, geliştiricilerin sistem tarafından başlatılan bu tür müdahalelere hazırlanmaları veya bunların meydana geldiğini bile bilmeleri mümkün değildir. Bu, tarayıcıların muhafazakar olması gerektiği anlamına gelir. Aksi takdirde web sayfalarını bozabilir.

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ı kullanıma sunuyoruz ve standart hale getiriyoruz.
  • 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ştiricilerinin sistem tarafından başlatılan bu yeni durumlardaki geçişlere yanıt vermesine olanak tanıyan yeni API'ler ve etkinlikler oluşturma.

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

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 belirten etkinlikleri açıklamanın en kolay yolu bir şema kullanmaktır:

Bu dokümanda açıklanan durumun 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 bir eyalet ayrıntılı olarak açıklanmaktadır. Ayrıca, bu durumun öncesinde ve sonrasında gerçekleşebilecek olası 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.

Önceki olası durumlar:
pasif (focus etkinliği aracılığıyla)
donduruldu (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.

Önceki olası durumlar:
pasif ( visibilitychange etkinliği aracılığıyla)
donduruldu (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)

Dondurulmuş

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ğırmaları gibi özelliklerin çalışmayacağı 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)

Sonlandırıldı

Bir sayfa, tarayıcı tarafından bellekten kaldırılmaya ve temizlenmeye başlandı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. Bu durumda hiçbir görev, etkinlik geri çağırması veya herhangi bir JavaScript çalıştırılamaz. Çünkü silme işlemleri genellikle yeni işlemlerin başlatılmasının imkansız olduğu kaynak kısıtlamaları altında gerçekleşir.

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 sayfada artık giriş odağı yoksa (yani sayfa yalnızca odağı bir öğeden diğerine geçirmemişse) durum değişikliği sinyalini verir.

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.

Önceki olası durumlar:
gizli

Olası mevcut durumlar:
dondurulmuş

resume *

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

Önceki olası durumlar:
Donduruldu

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, hiçbir zaman sayfaya koşulsuz olarak eklenmemelidir. Ayrıntılar için eski API'ler bölümüne bakın.

Önceki olası durumlar:
gizli

Olası mevcut durumlar:
terminated

unload

Sayfa kaldırılıyor.

Uyarı: unload etkinliğinin kullanılması, güvenilir olmadığı ve bazı durumlarda performansı düşürebileceği için 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:
sonlandırıldı

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

Chrome 68'e 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 üzerindeki freeze ve resume etkinliklerini dinleyerek gizli bir sekmenin ne zaman dondurulduğunu ve dondurulmadığını gözlemleyebilir.

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

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

Chrome 68 sürümünden itibaren document nesnesi artık masaüstü Chrome'da bir wasDiscarded mülkü içeriyor (Bu sorunla ilgili Android desteği 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ı gerekenlerin yanı sıra silinen sayfaların nasıl ele alınacağı ve bu etkinliklere nasıl hazırlanacağı ile ilgili tavsiyeler için her eyaletle ilgili geliştirici önerilerine bakın.

Sonraki bölümlerde, bu yeni özelliklerin mevcut web platformu durum ve etkinliklerine nasıl uyduğuna genel bir bakış sunulur.

Kodda Sayfa Yaşam Döngüsü durumlarını gözlemleme

Etkin, pasif ve gizli durumlarda, mevcut web platformu API'lerinden geçerli 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şlevi temel alındığında, aşağıdaki kodu kullanarak tüm Sayfa Yaşam Döngüsü durum 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 üç şey yapar:

  • 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 dinleyicileri ekler. Bu dinleyiciler de logStateChange()'yi çağırarak sonraki durumu iletir.

Kodla ilgili önemli bir nokta, tüm etkinlik işleyicilerin window öğesine eklendiği ve tümünün {capture: true} başarılı olduğudur. Bu durumun birkaç nedeni vardır:

  • Tüm sayfa yaşam döngüsü etkinlikleri aynı hedefe sahip değildir. pagehide ve pageshow window tarihinde, visibilitychange, freeze ve resume document tarihinde, focus ve blur ise ilgili 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ı anlamak hem de bunları kodda nasıl gözlemleyeceğinizi bilmek önemlidir. Çünkü yapmanız gereken (ve yapmamanız) gereken çalışma, büyük ölçüde sayfanızın durumuna 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ının sayfayı yeniden yüklenene kadar sayfayla tekrar etkileşime geçmemesi mümkündür.

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ı koruyun ve gönderilmemiş tüm analiz verilerini gönderin.

Ayrıca, kullanıcı arayüzü güncellemeleri yapmayı da durdurmanız (çünkü bunlar kullanıcı tarafından görülmez) ve kullanıcının arka planda çalışmasını istemediği görevleri durdurmanı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, sayfa gizli durumundan donduruldu durumuna geçtiğinde, tüm zamanlayıcıları durdurmanız veya dondurulması durumunda aynı kaynaktaki diğer açık sekmeleri ya da tarayıcının sayfayı geri-ileri önbelleğe yerleştirme yeteneğini etkileyebilecek tüm bağlantıları koparmanız gerektiği anlamına gelir.

Ö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 sonlandırıldı durumuna geçtiğinde genellikle herhangi bir işlem yapmanız gerekmez.

Kullanıcı işleminin sonucu olarak kaldırılan sayfalar, sonlandırıldı durumuna girmeden önce her zaman gizli durumundan geçer.Bu nedenle, oturum sonlandırma mantığının (ör. devam eden uygulama durumu ve analizlere raporlama) uygulanması gereken gizli durumudur.

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 tavsiyeleri uygulamanın en kolay yolu PageLifecycle.js'i kullanmaktır.

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

Aşağıdaki olaylardan mümkün olduğunca kaçınılmalıdır.

Kaldırma 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, bir 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, yalnızca kayıtlı bir unload etkinlik işleyicisinin (onunload veya addEventListener() aracılığıyla) varlığı, tarayıcıların daha hızlı geri ve ileri yüklemeler için sayfaları geri-ileri önbelleğe yerleştirmesini engelleyebilir.

Tüm modern tarayıcılarda, olası sayfa yükleme işlemlerini (diğer bir deyişle sonlandırıldı durumu) tespit etmek için unload etkinliği yerine her zaman pagehide etkinliğinin kullanılması ö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. Bununla birlikte, bazı tarayıcılar bir sayfayı geri-ileri önbelleğe yerleştirmeye çalışırken beforeunload etkinliğini önlem olarak tetiklemez. Bu, etkinliğin bir 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 tek fark, beforeunload öğelerinin meşru kullanımlarının 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?

Page Lifecycle API, durumları tek ve karşılıklı olarak dışlayıcı olacak şekilde tanımlar. Bir sayfa etkin, pasif veya gizli durumda yüklenebildiğinden ve yükleme tamamlanmadan önce durumları değişebildiğinden, hatta sonlandırılabileceğinden, bu paradigma içinde ayrı bir yükleme durumu mantıklı 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ı olmadığı sürece atılmaz:

  • Ses çalma
  • WebRTC'yi kullanma
  • Tablo başlığını veya simgesini güncelleme
  • Uyarılar gösteriliyor
  • 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 söz konusu 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. Bir unload etkinlik işleyici eklemenin bu optimizasyonun mümkün olması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'ye veri yazıyor ve okuma ve yazmalardan oluşan karmaşık bir işlem gerçekleştirmiyorsa görev sıraları askıya alınmadan önce commit() yöntemi 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 Depolamasını kullanın: Oturum Depolaması eşzamanlıdır ve sayfa silme işlemlerinde kalıcıdır.
  • Hizmet çalışanınızdaki IndexedDB'yi kullanma: Bir hizmet çalışanı, sayfa sonlandırıldıktan veya silindikten sonra IndexedDB'de veri depolayabilir. 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 donmuş ve atılmış durumlarda nasıl davrandığını test etmek için chrome://discards adresini ziyaret ederek açık sekmelerinizi dondurabilir veya silebilirsiniz.

Chrome Silinen Kullanıcı Arayüzü
Chrome'un Kullanılmayan Verileri Silme Kullanıcı Arayüzü

Bu sayede, sayfanızı freeze ve resume etkinliklerinin yanı sıra sayfalar atıldıktan 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ğı kullanacağı anlamına gelir. Bu da kullanıcılar için bir avantajdır.