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

Browser Support

  • Chrome: 68.
  • Edge: 79.
  • Firefox: not supported.
  • Safari: not supported.

Günümüzdeki modern tarayıcılar, sistem kaynakları kısıtlandığında sayfaları bazen askıya alır veya tamamen siler. Tarayıcılar gelecekte bunu proaktif olarak yapmak ve böylece daha az güç ve bellek tüketmek istiyor. 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ızda kullanıp kullanmamanız gerektiğini öğrenmek için API'ye göz atın.

Arka plan

Uygulama yaşam döngüsü, modern işletim sistemlerinin kaynakları yönetmek için kullandığı temel yöntemlerden biridir. 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 düzenleyip yeniden dağıtabilir.

Web'de geçmişte böyle bir yaşam döngüsü yoktu ve uygulamalar süresiz olarak kullanılmaya devam edebiliyordu. Çok sayıda web sayfası çalışırken bellek, CPU, pil ve ağ gibi kritik sistem kaynakları aşırı kullanılabilir ve bu durum, son kullanıcı deneyiminin kötü olmasına yol açar.

Web platformunda uzun süredir yaşam döngüsü durumlarıyla ilgili olaylar (ör. load, unload ve visibilitychange) olsa da bu olaylar 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 kaynak konusunda daha bilinçli olması) için tarayıcıların sistem kaynaklarını proaktif olarak geri alıp yeniden tahsis etmesi gerekir.

Aslında günümüzdeki tarayıcılar, arka plan sekmelerindeki sayfalar için kaynakları korumak üzere aktif önlemler alıyor. Birçok tarayıcı (özellikle Chrome), genel kaynak kullanımını azaltmak için bu önlemleri daha da artırmak istiyor.

Sorun, geliştiricilerin bu tür sistem kaynaklı müdahalelere hazırlanma veya bunların gerçekleştiğini bilme olanağının olmamasıdır. Bu nedenle, tarayıcıların ihtiyatlı olması veya web sayfalarının bozulma riskini göze alması gerekir.

Sayfa Yaşam Döngüsü API'si bu sorunu çözmek için:

  • Web'de yaşam döngüsü durumları kavramını tanıtma ve standartlaştırma
  • Tarayıcıların, gizli veya etkin olmayan sekmeler tarafından tüketilebilecek kaynakları sınırlamasına olanak tanıyan yeni, sistem tarafından başlatılan durumlar tanımlama.
  • Web geliştiricilerin, sistem tarafından başlatılan bu yeni durumlara geçişlere ve bu durumlardan geçişlere 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 sonuç olarak tüm web kullanıcılarına fayda sağlar.

Bu yayının geri kalanında yeni sayfa yaşam döngüsü özellikleri tanıtılacak ve bunların mevcut tüm web platformu durumları ve etkinlikleriyle nasıl ilişkili olduğu ele alınacak. Ayrıca, geliştiricilerin her durumda yapması (ve yapmaması) gereken iş türleriyle ilgili öneriler ve en iyi uygulamalar da sunar.

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

Tüm sayfa yaşam döngüsü durumları ayrı ve birbirini dışlayıcıdır. 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 durumla ilgili geliştirici önerilerine bakın).

Sayfa yaşam döngüsü durumlarını ve aralarındaki geçişleri işaret eden etkinlikleri açıklamanın belki de en kolay yolu bir diyagram kullanmaktır:

Bu belgede açıklanan durum ve etkinlik akışının görsel 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çıklanmaktadır. Ayrıca, öncesinde ve sonrasında olabilecek 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ünür ve giriş odağına sahip olan sayfalar etkin durumdadır.

Olası önceki durumlar:
passive (focus etkinliği üzerinden)
frozen (resume etkinliği ve ardından pageshow etkinliği üzerinden)

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

Pasif

Bir sayfa görünürse ve giriş odağı yoksa pasif durumdadır.

Olası önceki durumlar:
etkin (blur etkinliği aracılığıyla)
gizli ( visibilitychange etkinliği aracılığıyla)
dondurulmuş (resume etkinliği ve 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

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

Olası önceki durumlar:
passive ( visibilitychange etkinliği aracılığıyla)
frozen (resume etkinliği ve ardından pageshow etkinliği aracılığıyla)

Olası sonraki durumlar:
passive ( visibilitychange etkinliği aracılığıyla)
frozen (freeze etkinliği aracılığıyla)
discarded (hiçbir etkinlik tetiklenmedi)
terminated (hiçbir etkinlik tetiklenmedi)

Dondurulmuş

Tarayıcı, dondurulmuş durumdayken sayfanın görev kuyruklarındaki dondurulabilir görevlerin yürütülmesini sayfa dondurulma durumundan çıkana kadar askıya alır. Bu nedenle, JavaScript zamanlayıcıları ve getirme geri çağırmaları gibi işlemler çalışmaz. Zaten çalışan görevler (en önemlisi freeze geri çağırma) tamamlanabilir ancak yapabilecekleri ve ne kadar süre çalışabilecekleri sınırlı olabilir.

Tarayıcılar, CPU/pil/veri kullanımını korumak için sayfaları dondurur. Ayrıca, tam sayfa yeniden yükleme ihtiyacını ortadan kaldırarak daha hızlı geri/ileri gezinmeyi sağlamak için de sayfaları dondurur.

Olası önceki durumlar:
hidden (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)
kaldırıldı (etkinlik tetiklenmedi)

Sona erdirildi

Bir sayfa, tarayıcı tarafından bellekten kaldırılmaya ve temizlenmeye başladıktan sonra sonlandırılmış durumdadır. Hayır Yeni görevler bu durumda başlatılamaz ve devam eden görevler çok uzun süre çalışırsa sonlandırılabilir.

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

Olası sonraki durumlar:
YOK

Silindi

Bir sayfa, kaynaklardan tasarruf etmek için tarayıcı tarafından kaldırıldığında silinmiş durumdadır. Bu durumda hiçbir görev, etkinlik geri çağırması veya JavaScript çalıştırılamaz. Çünkü silme işlemi genellikle kaynak kısıtlamaları altında gerçekleşir ve bu durumda yeni işlemler başlatmak mümkün değildir.

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

Olası önceki durumlar:
gizli (hiçbir etkinlik tetiklenmedi)
dondurulmuş (hiçbir etkinlik tetiklenmedi)

Olası sonraki durumlar:
YOK

Etkinlikler

Tarayıcılar birçok etkinlik gönderir ancak bunların yalnızca küçük bir kısmı sayfa yaşam döngüsü durumunda olası bir değişikliği işaret eder. Aşağıdaki tabloda, yaşam döngüsüyle ilgili tüm etkinlikler özetlenmekte ve hangi durumlara geçiş yapabilecekleri listelenmektedir.

Ad Ayrıntılar
focus

Bir DOM öğesine odaklanıldı.

Not: Bir focus etkinliği, durum değişikliğini zorunlu olarak işaretlemez. Yalnızca sayfa daha önce giriş odağına sahip değilse durum değişikliği sinyali verir.

Olası önceki durumlar:
passive

Olası mevcut durumlar:
active

blur

Bir DOM öğesi odağını kaybetti.

Not: Bir blur etkinliği, durum değişikliğini zorunlu olarak işaretlemez. Yalnızca sayfa artık giriş odağına sahip değilse (ör. sayfa, odağı bir öğeden diğerine yeni değiştirmediyse) durum değişikliği sinyali verir.

Olası önceki durumlar:
active

Olası mevcut durumlar:
passive

visibilitychange

Belgenin visibilityState değeri değişti. Bu durum, kullanıcı yeni bir sayfaya gittiğinde, sekmeler arasında geçiş yaptığında, bir sekmeyi kapattığında, tarayıcıyı küçülttüğünde veya kapattığında ya da mobil işletim sistemlerinde uygulamalar arasında geçiş yaptığında meydana gelebilir.

Olası önceki durumlar:
passive
hidden

Olası mevcut durumlar:
passive
hidden

freeze *

Sayfa dondurulmuş olabilir. Sayfanın görev kuyruklarındaki dondurulabilir görevler başlatılmaz.

Olası önceki durumlar:
hidden

Olası mevcut durumlar:
frozen

resume *

Tarayıcı, dondurulmuş bir sayfayı devam ettirdi.

Olası önceki durumlar:
frozen (dondurulmuş)

Olası mevcut durumlar:
active (if followed by the pageshow event)
passive (if followed by the pageshow event)
hidden

pageshow

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

Bu, yepyeni bir sayfa yüklemesi 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ş (Bir resume etkinliği de tetiklenmiş olur.)

Olası mevcut durumlar:
active
passive
hidden

pagehide

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

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

Olası önceki durumlar:
hidden

Olası mevcut durumlar:
frozen (event.persisted doğru, freeze etkinliği takip eder)
terminated (event.persisted yanlış, unload etkinliği takip eder)

beforeunload

Pencere, doküman ve kaynakları kaldırılmak üzere. Doküman hâlâ görünür durumdadır ve etkinlik bu noktada hâlâ 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ılmalıdır. Bu kod, bazı durumlarda performansı olumsuz etkileyebileceğinden sayfaya koşulsuz olarak eklenmemelidir. Ayrıntılar için eski API'ler bölümüne bakın.

Olası önceki durumlar:
hidden

Olası mevcut durumlar:
terminated

unload

Sayfa kaldırılıyor.

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

Olası önceki durumlar:
hidden

Olası mevcut durumlar:
terminated

* 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 başlatılmayan, sistem tarafından başlatılan iki durum gösterilmektedir: dondurulmuş ve silinmiş. Daha önce de belirtildiği gibi, günümüzdeki tarayıcılar zaman zaman gizli sekmeleri dondurup atıyor (kendi takdirlerine bağlı olarak) ancak geliştiricilerin bu durumun ne zaman gerçekleştiğini bilmesinin bir yolu yok.

Chrome 68'de geliştiriciler artık document üzerinde freeze ve resume etkinliklerini dinleyerek gizli bir sekmenin ne zaman dondurulduğunu ve çö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 artık masaüstü Chrome'da bir wasDiscarded özelliği içeriyor (Android desteği bu sorunda takip ediliyor). Bir sayfanın gizli sekmedeyken atılıp atılmadığını belirlemek için bu özelliğin değerini sayfa yükleme sırasında inceleyebilirsiniz (Atılan sayfaların tekrar kullanılabilmesi için yeniden yüklenmesi gerektiğini unutmayın).

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

freeze ve resume etkinliklerinde yapılması gereken önemli şeyler ve sayfaların atılmasına nasıl hazırlanılacağı ile ilgili tavsiyeler için her durumla ilgili geliştirici önerilerine bakın.

Sonraki birkaç bölümde, bu yeni özelliklerin mevcut web platformu durumlarına ve etkinliklerine nasıl uyum sağladığına dair genel bir bakış sunulmaktadır.

Kodda sayfa yaşam döngüsü durumlarını gözlemleme

Etkin, pasif ve gizli durumlarında, mevcut web platformu API'lerinden geçerli sayfa yaşam döngüsü durumunu belirleyen JavaScript kodu çalıştırmak mümkündür.

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

Diğer yandan, durum değiştiği için dondurulmuş ve sonlandırılmış durumlar yalnızca kendi etkinlik dinleyicilerinde (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 PageLifecycle 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 üç işlem yapar:

  • getState() işlevini kullanarak başlangıç durumunu ayarlar.
  • 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 bir sonraki durumu ileterek logStateChange() işlevini çağırır.

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

  • Tüm sayfa yaşam döngüsü etkinliklerinin hedefi aynı değildir. pagehide ve pageshow, window üzerinde tetiklenir; visibilitychange, freeze ve resume, document üzerinde tetiklenir; focus ve blur ise kendi DOM öğelerinde tetiklenir.
  • Bu etkinliklerin çoğu kabarcıklanmaz. Bu nedenle, yakalamayan etkinlik işleyicileri ortak bir üst öğeye eklemek ve hepsini gözlemlemek mümkün değildir.
  • Yakalamanın gerçekleştiği aşama, hedef veya kabarcık aşamalarından önce yürütülür. Bu nedenle, burada dinleyiciler eklemek, diğer kodların bunları iptal etmesinden önce çalışmasını sağlar.

Her eyalet için geliştirici önerileri

Geliştiriciler olarak, yapmanız (ve yapmamanız) gereken işin türü büyük ölçüde sayfanızın bulunduğu duruma bağlı olduğundan, hem sayfa yaşam döngüsü durumlarını anlamak hem de bunları kodda nasıl gözlemleyeceğinizi bilmek önemlidir.

Örneğin, sayfa gizli durumdaysa kullanıcıya geçici bir bildirim göstermek açıkça mantıklı değildir. Bu örnek oldukça açık olsa da o kadar açık olmayan ve sıralanmaya değer başka öneriler de vardır.

Eyalet Geliştirici önerileri
Active

Etkin durum, kullanıcı için en kritik zamandır ve bu nedenle sayfanızın kullanıcı girişine yanıt vermesi için en önemli zamandır.

Ana iş parçacığını engelleyebilecek tüm kullanıcı arayüzü dışı çalışmalar, boşta kalma dönemlerine ertelenmeli veya bir web çalışanına aktarılmalıdır.

Passive

Pasif durumda kullanıcı sayfayla etkileşimde bulunmaz ancak sayfayı görmeye devam edebilir. Bu nedenle, kullanıcı arayüzü güncellemeleri ve animasyonlar sorunsuz olmaya devam etmelidir ancak bu güncellemelerin zamanlaması daha az önemlidir.

Sayfa etkin durumundan pasif duruma geçtiğinde kaydedilmemiş uygulama durumunu kalıcı hale getirmek için iyi bir zamandır.

Hidden

Sayfa pasif durumdan gizli duruma geçtiğinde, yeniden yüklenene kadar kullanıcıyla tekrar etkileşime girmeyebilir.

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

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

Ayrıca, kullanıcı tarafından görülmeyecekleri için kullanıcı arayüzü güncellemeleri yapmayı bırakmalı ve kullanıcının arka planda çalışmasını istemeyeceği tüm görevleri durdurmalısınız.

Frozen

Dondurulmuş durumda, dondurulabilir görevler, sayfa dondurulması kaldırılana kadar görev kuyruklarında askıya alınır.Bu işlem hiç gerçekleşmeyebilir (ör. sayfa atılırsa).

Bu nedenle, sayfa gizli durumundan dondurulmuş durumuna geçtiğinde, dondurulmuş haldeyken aynı kaynakta açık olan diğer sekmeleri etkileyebilecek veya tarayıcının sayfayı geri/ileri önbelleğine yerleştirme özelliğini etkileyebilecek tüm zamanlayıcıları durdurmanız ya da bağlantıları kapatmanız gerekir.

Özellikle şunları yapmanız önemlidir:

  • Açık olan tüm IndexedDB bağlantılarını kapatın.
  • Açık BroadcastChannel bağlantılarını kapatın.
  • Etkin WebRTC bağlantılarını kapatın.
  • Ağ yoklamalarını durdurun veya açık Web Socket bağlantılarını kapatın.
  • Bekletilen tüm Web Locks'u serbest bırakın.

Ayrıca, sayfa atılıp daha sonra yeniden yüklendiğinde geri yüklenmesini istediğiniz tüm dinamik görünüm durumunu (ör. sonsuz liste görünümünde kaydırma konumu) sessionStorage (veya commit() aracılığıyla IndexedDB) içinde kalıcı hale getirmelisiniz.

Sayfa dondurulmuş durumdan gizli duruma geçerse, kapattığınız bağlantıları yeniden açabilir veya sayfa ilk dondurulduğunda durdurduğunuz tüm yoklamaları yeniden başlatabilirsiniz.

Terminated

Bir sayfa sonlandırılmış duruma geçtiğinde genellikle herhangi bir işlem yapmanız gerekmez.

Kullanıcı işlemi sonucunda yüklemesi kaldırılan sayfalar, sonlandırılmış durumuna girmeden önce her zaman gizli durumundan geçtiğinden oturum sonlandırma mantığının (ör. uygulama durumunu kalıcı hale getirme ve Analytics'e raporlama) gizli durumunda gerçekleştirilmesi gerekir.

Ayrıca (Gizli durumla ilgili öneriler bölümünde 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ın farkında olması çok önemlidir.Bu nedenle, sonlandırma etkinliklerine (ör. beforeunload, pagehide ve unload) bağlı olan geliştiriciler veri kaybediyor olabilir.

Discarded

Silinen durum, bir sayfa silinirken geliştiriciler tarafından gözlemlenemez. Bunun nedeni, sayfaların genellikle kaynak kısıtlamaları nedeniyle atılması ve bir sayfayı yalnızca atma etkinliğine yanıt olarak komut dosyasının çalışmasına izin vermek için dondurmanın çözülmesinin çoğu durumda mümkün olmamasıdır.

Bu nedenle, gizli durumundan dondurulmuş durumuna geçişte değişikliğin silinme olasılığına karşı hazırlıklı olmanız gerekir. Ardından, document.wasDiscarded işaretini kontrol ederek silinen bir sayfanın geri yüklenmesine sayfa yükleme sırasında tepki verebilirsiniz.

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

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

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

Unload etkinliği

Birçok geliştirici, unload etkinliğini garantili bir geri çağırma olarak ele alır ve durumu kaydetmek, analiz verilerini göndermek için oturum sonu sinyali olarak kullanır. Ancak bunu yapmak, özellikle mobil cihazlarda son derece güvenilmezdir. unload etkinliği, mobil cihazlarda sekme değiştiriciden bir sekmeyi kapatma veya uygulama değiştiriciden tarayıcı uygulamasını kapatma gibi birçok normal kaldırma durumunda tetiklenmez.

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

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

Tüm modern tarayıcılarda, olası sayfa kaldırmalarını (diğer adıyla sonlandırılmış durumu) algılamak için her zaman unload etkinliği yerine pagehide etkinliğinin kullanılması önerilir. Internet Explorer 10 ve önceki sürümlerini desteklemeniz gerekiyorsa pagehide etkinliğini özellik algılama yöntemiyle tespit etmeli ve yalnızca tarayıcı pagehide'yı desteklemiyorsa 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ği, unload etkinliğine benzer bir soruna sahiptir. Geçmişte, beforeunload etkinliğinin varlığı sayfaların geri/ileri önbelleği için uygun olmasını engelleyebiliyordu. Modern tarayıcılarda bu kısıtlama yoktur. Ancak bazı tarayıcılar, önlem olarak bir sayfayı geri/ileri önbelleğine yerleştirmeye çalışırken beforeunload etkinliğini tetiklemez. Bu nedenle, etkinlik oturum sonu sinyali olarak güvenilir değildir. Ayrıca, Chrome da dahil olmak üzere bazı tarayıcılar, beforeunload etkinliğinin tetiklenmesine izin vermeden önce sayfada kullanıcı etkileşimi olmasını gerektirir. Bu da etkinliğin güvenilirliğini daha da etkiler.

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

beforeunload kullanmak için geçerli nedenler olduğundan, yalnızca kullanıcıların kaydedilmemiş değişiklikleri olduğunda beforeunload dinleyicileri eklemeniz ve kaydedildikten hemen sonra kaldırmanız önerilir.

Başka bir deyişle, aşağıdaki gibi yapmayın (çünkü bu, koşulsuz olarak bir beforeunload dinleyicisi ekler):

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

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

Bunun yerine şunu yapın (çünkü yalnızca gerektiğinde beforeunload işleyicisini ekler ve gerekmediğinde kaldırır):

const beforeUnloadListener = (event) => {
  event.preventDefault();

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

// A function that adds a `beforeunload` listener if there are unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

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

SSS

Neden "yükleniyor" durumu yok?

Page Lifecycle API, durumları ayrı ve birbirini dışlayan şekilde tanımlar. Bir sayfa etkin, pasif veya gizli durumda yüklenebildiği ve yükleme işlemi tamamlanmadan önce durum değiştirebildiği, hatta sonlandırıldığı için bu paradigmada ayrı bir yükleme durumu mantıklı değildir.

Sayfam gizlendiğinde önemli bir iş yapıyor. Dondurulmasını veya atılmasını nasıl önleyebilirim?

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

Chrome'un bir sayfayı atmasının riskli olacağı durumlar da vardır. Örneğin, sayfada gönderilmemiş kullanıcı girişi içeren bir form varsa veya sayfa yüklenirken uyarı veren bir beforeunload işleyicisi varsa.

Şu an için Chrome, sayfaları atarken temkinli davranacak ve yalnızca kullanıcıları etkilemeyeceğinden emin olduğunda sayfaları atacak. Ö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 oynatma
  • WebRTC kullanma
  • Tablo başlığını veya favicon'u 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 hakkında bilgi edinmek üzere Chrome'daki Heuristics for Freezing & Discarding (Dondurma ve Silme Sezgileri) başlıklı makaleyi inceleyin.

Geri-ileri önbellek nedir?

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

Kullanıcı bir sayfadan ayrıldığında bu tarayıcılar, kullanıcının geri veya ileri düğmelerini kullanarak geri dönmesi durumunda hızlıca devam edebilmesi için söz konusu sayfanın bir sürümünü dondurur. unload Etkinlik işleyici eklemenin bu optimizasyonun yapılmasını engellediğini unutmayın.

Bu dondurma, CPU/pil tasarrufu için tarayıcıların yaptığı dondurma işlemiyle işlevsel olarak aynıdır. Bu nedenle, dondurulmuş yaşam döngüsü durumunun bir parçası olarak kabul edilir.

Dondurulmuş veya sonlandırılmış durumlarda eşzamansız API'leri çalıştıramıyorsam verileri IndexedDB'ye nasıl kaydedebilirim?

Dondurulmuş ve sonlandırılmış durumlarda, bir sayfanın görev kuyruklarındaki dondurulabilir görevler askıya alınır. Bu nedenle, eşzamansız ve geri çağırmaya dayalı API'ler güvenilir bir şekilde kullanılamaz.

Çoğu IndexedDB API'si geri çağırmaya dayalı olsa da commit() yöntemi, IDBTransaction arayüzünde, bekleyen isteklerden gelen etkinliklerin gönderilmesini beklemeden etkin bir işlemde commit sürecini başlatmanın bir yolunu sunar. Bu, freeze veya visibilitychange etkinlik işleyicisinde verileri IndexedDB veritabanına kaydetmek için güvenilir bir yol sağlar. Bunun nedeni, ayrı bir görevde sıraya alınmak yerine işlemenin hemen çalıştırılmasıdır.

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

Uygulamanızın dondurulmuş ve atılmış durumlarda nasıl davrandığını test etmek için chrome://discards adresini ziyaret ederek açık sekmelerinizden herhangi birini dondurabilir veya atabilirsiniz.

Chrome Discards UI
Chrome Discards kullanıcı arayüzü

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

Özet

Kullanıcılarının cihazlarındaki sistem kaynaklarına saygı duymak 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 çok önemlidir.

Yeni Page Lifecycle API'lerini uygulamaya başlayan geliştirici sayısı arttıkça tarayıcıların kullanılmayan sayfaları dondurması ve atması daha güvenli hale gelecektir. Bu sayede tarayıcılar daha az bellek, CPU, pil ve ağ kaynağı kullanır. Bu da kullanıcılar için avantajlıdır.