[JavaScript] history.replaceState zonder URL te wijzigen

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
Ik heb een webpagina waarop de gebruiker aanpassingen kan maken zonder dat de pagina herladen wordt. De aanpassingen worden achter de schermen doorgestuurd naar de server en opgeslagen in de database. Het probleem is dat wanneer de gebruiker naar een andere pagina gaat en vervolgens de browser back button gebruikt, de oude versie van de pagina getoond wordt zonder de aanpassingen die hij gemaakt heeft (zoals de pagina van de server geladen werd).

Een naieve manier om dit op te lossen lijkt location.reload() op te roepen bij een pageshow event, maar dan krijgt de gebruiker eerst de oude versie van de pagina te zien totdat javascript geladen is. Dit ziet er niet echt mooi uit dus.

Een elegantere oplossing die ik me kan bedenken is gebruik maken van history.replaceState. Het probleem met deze aanpak is dat de URL tekens veranderd moet worden, of de browser blijft de oude versie tonen (nieuwe URL = cache miss). Een random querystring parameter genereren bij de URL van history.replaceState zou dit probleem oplossen, maar dit blijft een hack.

Mijn probleem kort samengevat: hoe kan ik maken dat history.replaceState werkt zonder de URL te wijzigen en indien dit (waarschijnlijk) niet gaat, welke alternatieven zijn er die ik over het hoofd zie?

Acties:
  • 0 Henk 'm!

  • yowkah
  • Registratie: Juni 2016
  • Laatst online: 30-05 11:28
Zou je de wijzigingen eventueel op kunnen nemen in localstorage en dan pas door kunnen sturen naar de database? Dat zou de "staat" van de pagina recreëren bij een nieuw bezoek of vorig bezoek. Eventueel kan je het "ophalen" van data uit local storage dan kunnen laten afhangen van de referal page of van een hash in de URL bij eerste bezoek.

Acties:
  • 0 Henk 'm!

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

Kun je niet bij pageload alle bewerkbare data via ajax ophalen? Op het moment dat een user dan de back-button gebruikt zal er bij pageload actuele data opgehaald worden?

Hoeder van het Noord-Meierijse dialect


Acties:
  • +1 Henk 'm!

  • Kontsnorretje
  • Registratie: Augustus 2011
  • Laatst online: 14-06-2024
Ik weet niet hoeveel invloed je hebt op de headers die over de lijn gestuurd worden... Maar daar zou je de oplossing ook kunnen zoeken. Met een Cache-control header kan je dit ook beïnvloeden:

Cache-Control: private, must-revalidate, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0

Dat is m.i. de non-hack oplossing, en zoals het hoort.

Om nog een hacky method aan te bieden:
Een onpageshow event toevoegen. Hierin doe je ongeveer het volgende:
code:
1
2
3
4
5
6
7
8
9
10
window.onpageshow = function (event) {
    //Als hij uit de cache komt
    if (event.persisted) {
        //Hier een functie die de nieuwe data van de server haalt; 
        //updatePageWithNewData();
        //Of een reload, maar dat wil je juist niet.
        //window.location = window.location; // Because I can :D

    }
};


Succes met je oplossing :)

Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
Excuses voor de late reactie, om een of andere reden kwamen er geen meldingen van nieuwe reacties.

Maar goed, wat de veranderde content herladen met AJAX betreft, is dit niet mogelijk omdat ik omwille van SEO redenen de content direct bij pageload beschikbaar wil hebben.

Alle veranderingen in localStorage bijhouden, is te veel knoeiwerk en een te grote verandering aan mijn applicatie, dus liever niet.

Ondertussen ben ik echter zelf op een oplossing gekomen; zoals Kontsnorretje reeds zei, is het me zelf te binnen geschoten dat er nog altijd iets als HTTP caching bestaat :)

Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 12-07 22:24
egonolieux schreef op vrijdag 13 oktober 2017 @ 17:56:
Een elegantere oplossing die ik me kan bedenken is gebruik maken van history.replaceState. Het probleem met deze aanpak is dat de URL tekens veranderd moet worden, of de browser blijft de oude versie tonen (nieuwe URL = cache miss).
Als je replaceState() uitvoert met een state object X en vervolgens nog eens met een state object Y en je komt later terug op die pagina in de historie, dan vindt er gewoon een popstate event plaats met de Y state die je als laatste er in gezet hebt.

Ook als je de URL niet zou hebben veranderd. Die kun je gewoon hetzelfde houden. Sterker nog: de URL parameter is compleet optioneel. Als je die niet specificeert betekent dat letterlijk "vervang de state, maar hou de URL hetzelfde".


Mocht het zo zijn dat een pagina herladen wordt vanaf de server i.p.v. uit de history-cache te komen, dan zal de hele pagina opnieuw opgebouwd worden en dus ook het DOMContentLoaded event uitvoeren. Daarbinnen kun je vervolgens alsnog History.state inspecteren om de bijhorende state op te halen en door te voeren. DOMContentLoaded vuurt doorgaans direct voor of na de eerste paint operatie. Je gebruikers zullen dus hoogstens een kleine flits zien.

[ Voor 37% gewijzigd door R4gnax op 18-10-2017 20:21 ]


Acties:
  • 0 Henk 'm!

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

egonolieux schreef op dinsdag 17 oktober 2017 @ 22:30:
Maar goed, wat de veranderde content herladen met AJAX betreft, is dit niet mogelijk omdat ik omwille van SEO redenen de content direct bij pageload beschikbaar wil hebben.
Daar kan ik me wel in vinden, toch vind ik ook dat - qua user experience - AJAX wel een van de meest robuuste oplossingen is. Je zou dus ook het probleem om kunnen draaien. Nu heb je een SEO-friendly site waarbij je op zoek bent naar een manier om users de goede content te serveren. Je kun dus ook uitgaan van een site waarbij je users altijd de goede content serveert maar het probleem van SEO-friendly moet tackelen... Heb je deze blogpost van Google gelezen?

Hoeder van het Noord-Meierijse dialect


Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
R4gnax schreef op woensdag 18 oktober 2017 @ 20:10:
[...]


Als je replaceState() uitvoert met een state object X en vervolgens nog eens met een state object Y en je komt later terug op die pagina in de historie, dan vindt er gewoon een popstate event plaats met de Y state die je als laatste er in gezet hebt.

Ook als je de URL niet zou hebben veranderd. Die kun je gewoon hetzelfde houden. Sterker nog: de URL parameter is compleet optioneel. Als je die niet specificeert betekent dat letterlijk "vervang de state, maar hou de URL hetzelfde".


Mocht het zo zijn dat een pagina herladen wordt vanaf de server i.p.v. uit de history-cache te komen, dan zal de hele pagina opnieuw opgebouwd worden en dus ook het DOMContentLoaded event uitvoeren. Daarbinnen kun je vervolgens alsnog History.state inspecteren om de bijhorende state op te halen en door te voeren. DOMContentLoaded vuurt doorgaans direct voor of na de eerste paint operatie. Je gebruikers zullen dus hoogstens een kleine flits zien.
Klopt wat je zegt over history.replaceState, maar daarmee is de pagina zelf nog niet herladen. Dan zou ik in de popstate event zelf de content moeten herladen/aanpassen met bvb een aantal AJAX calls. Mijn bedoeling was eerder de gehele pagina zelf herladen omdat het aantal verschillende gewijzigde stukken HTML mij iets te groot is om met AJAX te doen.

Wat je met DOMContentLoaded bedoelt, snap ik niet echt. Als de pagina herladen is vanaf de server dan heb ik toch al de meest recente data?
Harrie_ schreef op donderdag 19 oktober 2017 @ 09:12:
[...]


Daar kan ik me wel in vinden, toch vind ik ook dat - qua user experience - AJAX wel een van de meest robuuste oplossingen is. Je zou dus ook het probleem om kunnen draaien. Nu heb je een SEO-friendly site waarbij je op zoek bent naar een manier om users de goede content te serveren. Je kun dus ook uitgaan van een site waarbij je users altijd de goede content serveert maar het probleem van SEO-friendly moet tackelen... Heb je deze blogpost van Google gelezen?
Let er wel op dat er "generally able to" staat in die blogpost van google. Zolang er geen zekere manier is om door JS gegenereerde content te indexeren, reder ik nog altijd het liefst de gehele pagina op voorhand. Je hebt natuurlijk met node.js genoeg tools/frameworks die je SPA kan server-side renderen voor SEO, maar dat is niet echt van toepassing voor mij aangezien het hier om een PHP site gaat.

Aangezien ik zelf de HTTP headers kan aanpassen blijft "no-store" de beste, en waarschijnlijk zelfs de meest performante oplossing. Ik zou een stuk of 10 delen van de pagina met AJAX moeten herladen, dus om performant te blijven zou ik deze 10 stukken HTML in JSON moeten encoden binnen eenzelfde request. Dan is het natuurlijk veel makkelijker de pagina rechtstreeks te herladen.

[ Voor 36% gewijzigd door egonolieux op 20-10-2017 05:46 ]


Acties:
  • 0 Henk 'm!

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

egonolieux schreef op vrijdag 20 oktober 2017 @ 05:34:
[...]
Let er wel op dat er "generally able to" staat in die blogpost van google. Zolang er geen zekere manier is om door JS gegenereerde content te indexeren, reder ik nog altijd het liefst de gehele pagina op voorhand. Je hebt natuurlijk met node.js genoeg tools/frameworks die je SPA kan server-side renderen voor SEO, maar dat is niet echt van toepassing voor mij aangezien het hier om een PHP site gaat.
Mag ik dan vragen om wat voor data / website / webapplicatie dit gaat? In mijn ervaring is de data die je door een user wil laten editen doorgaans vaak niet heel relevant als het op SEO aankomt?

Hoeder van het Noord-Meierijse dialect


Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
Harrie_ schreef op vrijdag 20 oktober 2017 @ 09:03:
[...]


Mag ik dan vragen om wat voor data / website / webapplicatie dit gaat? In mijn ervaring is de data die je door een user wil laten editen doorgaans vaak niet heel relevant als het op SEO aankomt?
De template in kwestie wordt aangepast naargelang een gebruiker is aangemeld of niet. Ik zou natuurlijk zo kunnen maken dat bij niet-aangemelde gebruikers de pagina volledig geladen wordt en dat aangemelde gebruikers delen met AJAX laden, maar vanuit het perspectief van mijn website is dit veel geknoei.
Pagina: 1