Search code examples
javascriptfetch

After fetch HTML from other page and append the script with "type='module'" it works just one time and then stops


I'm using "fetch" to load dynamically a html page content that has his own script, it works fine, but the pages need to have "script type='module'" since they import functions from other pages. The thing is when the type='module' is set, it load the script just one time after that it stops to work.

Here is the complete code in the codesandbox

Anyway here is my structure folder

📜index.html
📜main.js

📦functions
 ┗ 📜someFunc.js

📦pages
 ┣ 📜home.html
 ┣ 📜home.js
 ┣ 📜page_1.html
 ┣ 📜page_1.js
 ┣ 📜page_2.html
 ┗ 📜page_2.js

In the main.js I have the fetch function like this:

//Event click of the main menu
let nav = document.querySelector("#main_nav");
nav.querySelectorAll("a").forEach((aElement) => {
  aElement.addEventListener("click", (e) => {
    //Each element "a" have the attribute "data-path='name_of_file'"
    loadHTML(e.target.dataset.path);
  });
});

//Funciton that loads the content from other pages using "fetch"
function loadHTML(htmlPath) {
  fetch(`pages/${htmlPath}.html`)
    .then((res) => res.text())
    .then((html) => {
      let page_content = document.querySelector("#page_content");
      page_content.innerHTML = html;
      let script = document.createElement("script");
      script.src = `pages/${htmlPath}.js`;
      //set the type='module' in the script when the page is "page_1"
      if (htmlPath === "page_1") {
        script.type = "module";
      }
      page_content.appendChild(script);
    });
}

This is my main menu:

    <nav id="main_nav">
      <li><a href="#" data-path="home">Home</a></li>
      <li></li>
      <li><a href="#" data-path="page_1">Page 1</a></li>
      <li></li>
      <li><a href="#" data-path="page_2">Page 2</a></li>
      <li></li>
    </nav>

Thanks to anyone who take the time.

Update... I tried to use the dynamically import but it doesn't work either codesandbox

import("../functions/someFunc.js")
  .then((someFunc) => {
    someFunc.displayConsoleMSG("test");
  })
  .catch((err) => {
    console.log(err);
  });

Solution

  • One solution is to replace the <script> tag creation with a call to dynamic import:

          import(`./pages/${htmlPath}.js`).then((module) => {
            module.onload();
          });
    

    For this to work, you'll need to define a function in your .js files (above, I've named it onload) that you call upon page switching, instead of relying on side-effects from the code loading process.

    Here's a working CodeSandbox.