Automatically Re-Executing Scripts in ASP.NET Core MVC with Blazor Enhanced Navigation
Lee Timmins
2nd Oct 2025
Comments
In my previous post on executing scripts in an ASP.NET Core MVC app with Blazor enhanced navigation, you had to use a page-script tag to define your custom scripts. But what if you don’t want to manually convert every script on your site?
Here’s a way to automatically handle this by using a MutationObserver and reloading <script> tags whenever they appear in the DOM.
The Script Loader
Add the following to your global JavaScript file (e.g., site.js), making sure it’s included on every page:
function loadScript(script) {
// Create the new script.
const newScript = document.createElement('script');
// Prevent the new script from getting stuck in an infinite loop. Since the mutation observer will monitor for it.
newScript.dataset.ignoreNew = true;
// Add the attributes.
Array.from(script.attributes).forEach(a => newScript.setAttribute(a.name, a.value));
// Set the inner HTML.
newScript.appendChild(document.createTextNode(script.textContent));
// Replace the old script with the new script tag.
script.parentNode.replaceChild(newScript, script);
}
// Create a MutationObserver.
const observer = new MutationObserver(async mutations => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
// Check if the added node is a script tag.
if (node.tagName && node.tagName.toLowerCase() === 'script' && node.dataset.ignoreNew !== 'true')
loadScript(node);
else if (node.nodeType === 1)
node.querySelectorAll('script').forEach(scriptNode => loadScript(scriptNode));
}
}
});
// Start observing changes in the document's body.
observer.observe(document.body, { childList: true, subtree: true });
Example: Standard Script
If you have a script included like this:
<script src="/js/script.js"></script>
And /js/script.js contains:
console.log('Script');
You’ll now see "Script" logged every time you navigate back to a page that references this script — not just on the initial load.
Example: Module Script
Things get trickier when using JavaScript modules:
<script type="module" src="/js/script.js"></script>
Modules are cached by the browser once loaded. This means that navigating back to a page that references your module will not re-execute it — "Script" will only be logged on the initial load.
So, while the MutationObserver technique works for regular scripts, modules require a different approach. If you need modules to re-execute between navigations, you’ll need to fall back to the page-script web component approach.