Our website uses JS to do partial page hydration to avoid downloading the entire page when navigating within the website. We have been getting reports from Safari browser users that when they click a nav link, they loose all the content (but the header and footer are still there).
All pages have a full static html version (for when they are landed on) and a json file with the content specific to that page.
Our JS script intercepts internal links, fetches the appropriate JSON file then parses the JSON data inserting the appropriate content in its correct spot. We are using the older style XMLHttpRequest rather than fetch to assist older technology. The system works on all the browsers we have access to (mostly Windows and Android based).
The reports from folks seem to be older versions 14 & 15, not the latest. But our customers are not always computer savvy, so haven't been able to get any detailed info.
Our Javascript is below. The process gets called as part of a page wide event propagation script on all A links:
// what is left should be used for page hydration
else {
// determine target page name, then convert to json file name
const tpath = url.pathname;
const pgpath = tpath.replace('.htm', '.json');
const pgurl = bspgurl + pgpath;
// trigger page fetch and hydration
getNewPage(pgurl, tpath);
}
The getNewPage:
// fetch json from server, hydrate page with new content
function getNewPage(url, tpath) {
const xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// scroll to top of page
window.scroll({
top: 0,
left: 0,
behavior: 'instant',
});
// insert new page content
const myArr = JSON.parse(this.responseText);
putNewPage(myArr);
// update browser history
saveToHstry(myArr, tpath);
}
};
xmlhttp.open('GET', url, true);
xmlhttp.send();
}
The putNewPage
// hydrate page with new content
function putNewPage(data) {
const m = document.getElementsByTagName('meta');
const l = document.getElementsByTagName('link');
const p = document.getElementsByTagName('input');
for (let i = 0; i < data.length; i++) {
switch (data[i].fncn) {
case 'body':
var bdy = document.getElementsByTagName('body');
bdy[0].setAttribute('id', data[i].cntnt);
pgType = data[i].cntnt;
break;
case 'bkgnd':
document.body.className = '';
document.body.classList.add(data[i].cntnt);
break;
case 'title':
document.title = data[i].cntnt;
break;
case 'metan':
for (var j = 0; j < m.length; j++) {
if (m[j].getAttribute('name') === data[i].trgt) {
m[j].setAttribute('content', data[i].cntnt);
}
}
break;
case 'metap':
for (var j = 0; j < m.length; j++) {
if (m[j].getAttribute('property') === data[i].trgt) {
m[j].setAttribute('content', data[i].cntnt);
}
}
break;
case 'link':
for (let k = 0; k < l.length; k++) {
if (l[k].getAttribute('rel') === data[i].trgt) {
l[k].setAttribute('href', data[i].cntnt);
}
}
break;
case 'id':
$(data[i].trgt).innerHTML = data[i].cntnt;
break;
case 'input':
for (let f = 0; f < p.length; f++) {
if (p[f].getAttribute('name') === data[i].trgt) {
p[f].setAttribute('value', data[i].cntnt);
}
}
break;
case 'js':
window[data[i].trgt] = data[i].cntnt;
break;
}
}
}
The website pages are all pre-rendered and saved on a CDN.
As requested a sample of the hydration json file. The page layout has 10 divs, of which some pages have content is all ten, other pages only a couple of divs. The feedback we get seems to indicate that the content is stripped out as expected, but not replaced.
[
{
"fncn": "body",
"trgt": "body",
"cntnt": "gen"
},
{
"fncn": "bkgnd",
"trgt": "bkgnd",
"cntnt": "jigsaw"
},
{
"fncn": "title",
"trgt": "title",
"cntnt": "Travel Agent booking information"
},
{
"fncn": "metan",
"trgt": "description",
"cntnt": "Information for travel agencies wanting to seel Pedalers tours"
},
{
"fncn": "metan",
"trgt": "image",
"cntnt": "https:\/\/pedalers.travel\/img\/ppg-logo-vrt.png"
},
{
"fncn": "metap",
"trgt": "og:title",
"cntnt": "Travel Agent booking information"
},
{
"fncn": "metap",
"trgt": "og:description",
"cntnt": "Information for travel agencies wanting to seel Pedalers tours"
},
{
"fncn": "metap",
"trgt": "og:image",
"cntnt": "https:\/\/pedalers.travel\/img\/ppg-logo-vrt.png"
},
{
"fncn": "metap",
"trgt": "og:url",
"cntnt": "https:\/\/pedalers.travel\/travel-agency.htm"
},
{
"fncn": "metan",
"trgt": "theme-color",
"cntnt": "#212121"
},
{
"fncn": "link",
"trgt": "canonical",
"cntnt": "https:\/\/pedalers.travel\/travel-agency.htm"
},
{
"fncn": "id",
"trgt": "div1",
"cntnt": "<div class=\"nosplsh nsblk\">\r\n <h1>Welcome Travel Agents<\/h1>\r\n <p class=\"smlhdr\">Pedalers is happy to work with Travel Professionals<\/p>\r\n<\/div>"
},
{
"fncn": "id",
"trgt": "div2",
"cntnt": "<div class=\"text twothirds\">\r\n<h2>Book With Pedalers\r\n\r\n<\/h2><p>Thanks for visiting our website in search of great adventure vacations for your clients. Pedalers works together with our Travel Industry partners, offering a multi-tiered compensation plan for travel agencies that market and specialize in adventure travel. For complete details, please fill out our Travel Agency Registration Form. We will be back in touch promptly.<\/p>\r\n<p><a href=\"https:\/\/secure.pedalers.travel\/tvl-agency-registration.php\" class=\"btn bgrn\">Agency Sign Up<\/a><\/p>\r\n<\/div>"
},
{
"fncn": "id",
"trgt": "div3",
"cntnt": ""
},
{
"fncn": "id",
"trgt": "div4",
"cntnt": ""
},
{
"fncn": "id",
"trgt": "div5",
"cntnt": ""
},
{
"fncn": "id",
"trgt": "div6",
"cntnt": ""
},
{
"fncn": "id",
"trgt": "div7",
"cntnt": ""
},
{
"fncn": "id",
"trgt": "div8",
"cntnt": ""
},
{
"fncn": "id",
"trgt": "div9",
"cntnt": ""
},
{
"fncn": "id",
"trgt": "div10",
"cntnt": ""
},
{
"fncn": "input",
"trgt": "source",
"cntnt": "travel-agency.htm"
},
{
"fncn": "js",
"trgt": "tourid",
"cntnt": "0"
},
{
"fncn": "js",
"trgt": "pageid",
"cntnt": "69"
},
{
"fncn": "js",
"trgt": "country",
"cntnt": "none"
}
]