I’m maintaining a legacy web application that emulates Single Page Application (SPA) behavior using a custom JavaScript function called loadOnPage
. This function dynamically loads external pages and replaces the element’s content with the id "content", allowing us to switch between pages without reloading the entire page.
Here is a simplified version of the loadOnPage
function:
async function loadOnPage(page, options = {}) {
// Default options
options = {
contentDiv: "content",
saveHistory: true,
...options
};
const { contentDiv, saveHistory } = options;
// Prepare FormData for POST request
const fd = new FormData();
fd.append("PAGINA", page);
try {
// Fetch page content via AJAX
const response = await axios.post("/lop.php", fd);
if (response.data.status !== 200) {
throw new Error(`Failed to load page: ${response.data.status}`);
}
// Replace content and execute scripts
document.getElementById(contentDiv).innerHTML = response.data.detail.content;
execAllScriptTags(contentDiv);
// Update history state
if (saveHistory) {
saveWindowHistory({ page, options });
}
} catch (error) {
console.error(error);
return false;
}
}
// Helper to execute scripts within loaded content
function execAllScriptTags(containerId) {
const container = document.getElementById(containerId);
const scripts = container.querySelectorAll("script");
scripts.forEach((script) => {
const newScript = document.createElement("script");
if (script.src) {
newScript.src = script.src;
} else {
newScript.textContent = script.textContent;
}
script.parentNode.replaceChild(newScript, script);
});
}
// Function to save history state
function saveWindowHistory(params = {}) {
const { page } = params;
window.history.pushState(params, "", `/${page}/`);
}
// Event listener for page load to handle browser refresh
window.addEventListener("load", function () {
if (window.history.state) {
reloadWithStateHistory();
}
});
// Function to reload content based on history state
function reloadWithStateHistory() {
const { state } = window.history;
if (state) {
const { page, options } = state;
return loadOnPage(page, { ...options, saveHistory: false });
}
window.location.reload();
}
The Problem:
When a user refreshes the page using the browser’s reload button, the page loses access to the scripts and functions that were dynamically loaded via loadOnPage
. This results in broken functionality because those scripts are essential for the page to work correctly.
What I’ve Tried:
- Storing State: Using
sessionStorage
or cookies to store the page state, but this doesn’t solve the issue of missing scripts and functions after a reload. - Dynamic Script Loading on Reload: Attempted to inject scripts dynamically during page load based on the current URL or history state, but this approach is complex and hard to maintain.
- Including All Scripts Globally: Including all possible scripts in the initial page load is not feasible devido a efeitos colaterais indesejados e problemas de desempenho.
Constraints:
- No Modern Frameworks: Due to project constraints, I cannot use frameworks like React or Angular.
- Legacy System: Significant architectural changes are not possible.
- Deep Linking: The application needs to support deep linking for bookmarking and direct access to specific pages.
- Page-Specific Scripts: Loaded pages may include scripts that are only relevant to that page and may have side effects.
My Question:
Given these constraints, how can I ensure that when a user refreshes the page, all necessary scripts and functions are reloaded so that the page functions correctly, just as if it had been loaded via loadOnPage
?
Additional Information:
- We use
window.history.pushState
to manage navigation history. - The
execAllScriptTags
function executes scripts within the dynamically loaded content. - The issue specifically arises because scripts loaded dynamically are not persistent across browser refreshes.
I would greatly appreciate any guidance or solutions on how to handle the reloading of necessary scripts and functions upon a browser refresh in this legacy system.
You need to sign in to view this answers
Leave feedback about this