Search code examples
javascriptimportasync-awaitpromisees6-promise

How to lazy load immediate functions


Before i start, i like to point out i am learnging JS, so this may be trivial, but having hard time do lazy load immidiate function https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.js

Example, I have click event that should load the said Swiper-bundle.js and then initiate the Swiper:

var type = 'coverflow';

window.addEventListener("DOMContentLoaded", e => {
  //add click listener to the button
  document.getElementById('swiperbtn').addEventListener('click', e => {

    (async () => {
      const object = await import("https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.js");

      console.log("Swiper-bundle.min.js loaded...");

      var swiper = new Swiper(".mySwiper", {
        effect: "coverflow",
        grabCursor: true,
        centeredSlides: true,
        slidesPerView: "auto",
        coverflowEffect: {
          rotate: 50,
          stretch: 0,
          depth: 100,
          modifier: 1,
          slideShadows: true,
        },
        pagination: {
          el: ".swiper-pagination",
        },
      });

    })();
  });

});
html,
body {
  position: relative;
  height: 100%;
}

body {
  background: #eee;
  font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
  font-size: 14px;
  color: #000;
  margin: 0;
  padding: 0;
}

.swiper {
  width: 100%;
  padding-top: 50px;
  padding-bottom: 50px;
}

.swiper-slide {
  background-position: center;
  background-size: cover;
  width: 300px;
  height: 300px;
}

.swiper-slide img {
  display: block;
  width: 100%;
}
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />
<!-- Link Swiper's CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
<!-- Swiper -->
<h1>Making Swiper Web Component</h1>
<button type="button" id="swiperbtn">Try Swiper</button>
<div id="placehodler">

</div>
<div class="swiper mySwiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-1.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-2.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-3.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-4.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-5.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-6.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-7.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-8.jpg" />
    </div>
    <div class="swiper-slide">
      <img src="https://swiperjs.com/demos/images/nature-9.jpg" />
    </div>
  </div>
  <div class="swiper-pagination"></div>
</div>

When i click on the button, i got error: enter image description here

I see the swiper-bundle.js doesn't have Module export structure but it has immidiate function. How is that made work on import()? Thank you for any help


Solution

  • Dynamic import (ie: import()) should be used for loading ECMAScript Modules (ES modules). In your case, your resource located at the CDN URL isn't an ES module, it's just a regular JavaScript file that creates a variable, which isn't that useful if you want to load your library lazily, and can't be used with import().

    Swiper-js does however host ESM versions of the library, which you can access by changing your URL to import .mjs instead of .js:

    https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.mjs
    

    When importing ES modules they won't impact the global scope (technically they can, but it's bad practice), so in your case the Swiper constructor won't automatically become available once you import your library, you will need to access it from the module object you get back from your import, such as by destructing it like so:

    const { Swiper } = await import(...);
    

    This will bring the Swiper constructor function into the current scope of your code so you can use it.

    window.addEventListener("DOMContentLoaded", e => {
      //add click listener to the button
      document.getElementById('swiperbtn').addEventListener('click', e => {
    
        (async () => {
          const { Swiper } = await import("https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.mjs");
    
          console.log("Swiper-bundle.min.js loaded...");
    
          var swiper = new Swiper(".mySwiper", {
            effect: "coverflow",
            grabCursor: true,
            centeredSlides: true,
            slidesPerView: "auto",
            coverflowEffect: {
              rotate: 50,
              stretch: 0,
              depth: 100,
              modifier: 1,
              slideShadows: true,
            },
            pagination: {
              el: ".swiper-pagination",
            },
          });
    
        })();
      });
    
    });
    html,
    body {
      position: relative;
      height: 100%;
    }
    
    body {
      background: #eee;
      font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
      font-size: 14px;
      color: #000;
      margin: 0;
      padding: 0;
    }
    
    .swiper {
      width: 100%;
      padding-top: 50px;
      padding-bottom: 50px;
    }
    
    .swiper-slide {
      background-position: center;
      background-size: cover;
      width: 300px;
      height: 300px;
    }
    
    .swiper-slide img {
      display: block;
      width: 100%;
    }
    <!-- Link Swiper's CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
    
    <!-- Swiper -->
    <h1>Making Swiper Web Component</h1>
    <button type="button" id="swiperbtn">Try Swiper</button>
    <div id="placehodler">
    
    </div>
    <div class="swiper mySwiper">
      <div class="swiper-wrapper">
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-1.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-2.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-3.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-4.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-5.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-6.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-7.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-8.jpg" />
        </div>
        <div class="swiper-slide">
          <img src="https://swiperjs.com/demos/images/nature-9.jpg" />
        </div>
      </div>
      <div class="swiper-pagination"></div>
    </div>