SustainableWWW Logo
Blog post image

How to use dynamic import in Svelte using Rollup (Code splitting)

There is no doubt that web applications made using Svelte, React and Angular is getting popular, but often the compiled bundles end up getting quite large. Large bundles mean that the visitor needs to download more data to interact with your web application and often it is unnecessary to download data for the whole web application when the visitor only visits the start page. 

Luckily there is a fix for this, and it is called dynamic imports/code splitting. This feature allows us to split up our code into multiple files and only download them once they are required. After code-splitting your web application your user won’t have to download data from other pages or elements unless they are required on the page your visitor is viewing.

How do I use dynamic imports/code split in Svelte? 

Dynamic imports are very powerful, and luckily with Svelte, they are easy to implement. Before making an import dynamic we start by importing traditionally so that you can see the difference.

Traditional import using <svelte:component>

<script lang="ts">
    import Contact from "./Pages/Contact.svelte";
</script>

<svelte:component this={Contact}>

Now let's make it a dynamic import

So, by now we have traditionally imported a component, but honestly, that won't make it a dynamic import. Below is the same script as above but with a dynamic import instead of a traditional one:

<script lang="ts">
    import { onMount } from "svelte";
    import 404 from "./Pages/404.svelte";
    let Contact = null;

  onMount(async () => {
      try {
        Contact = (await import("./Pages/Contact.svelte')).default;
      } catch (e) {
        Contact = 404;
      }
  })
</script>

<svelte:component this={Contact}>

So as you see, now we have changed the component into being imported dynamically instead of the traditional way. We started by importing onMount so that we can create a function that will run when the component is loading. After that, we created a variable called Contact which had the default value of null. The reason we created a default value of null, is because the <svelte:component> won't render when the value of "this" is false.

In the onMount function, we added a try and catch section to allow us to specify what happens if something should go wrong during the dynamic import. Therefore if an error happens we switch the value of the contact page to be the 404 (error) page instead.

You most likely also noticed that we in the examples above made use of the <svelte:component> element. If we had multiple components that we could switch between, then we could either write every component into the DOM or we could change the content of the <svelte:component> instead. Here is an example of how this component is used and how it could be useful to you when dealing with routes in your Svelte application.

Here is the same example as above, just using the components own name instead of the <svelte:component> element:

<script lang="ts">
    import { onMount } from "svelte";
    import 404 from "./Pages/404.svelte";
    let Contact = null;

  onMount(async () => {
      try {
          Contact = (await import("./Pages/Contact.svelte')).default;
      } catch (e) {
          Contact = 404;
      }
  })
</script>

<Contact />

Implement the chunk files into your Svelte web application

Now that we know how we split our components into chunks and dynamically import them, we also need to know how to implement our chunks into our existing Svelte web application. Doing so is easier than you might think.

First, we need to change some settings in our Rollup config to allow us to split our code into chunks. In this example, we will split our node_modules into vendors and components into webapp chunks.

export default {
    input: "src/webapp.js",
    output: {
       sourcemap: true,
       format: "es",
       name: "app",
       dir: "public/build/",
       manualChunks: (moduleName) => {
           if (moduleName.includes("node_modules")) {
               return "vendor"
           }
           if (moduleName.includes("src/Components/")) {
               return "webapp"
           }
      },
  },

Now that we are creating our chunk files correctly we just need to update our HTML to understand it too. We need to tell the browser that we are using EcmaScript and we do that by using the "type='module'" attribute. 

<!-- Before: <script defer src='/build/bundle.js'></script> -->
<script type="module" defer src='/build/webapp.js'></script>

Why code splitting is beneficial for your users

Imagine that your web application has a compiled bundle with a file size of 4-5MB. Every time a user visits your web application they have to download the full bundle before they can start interacting. But if they for example only visit the front page, then all data that isn’t tied to the front page will be wasted and unnecessary. 

When you split your code into chunks, you can divide it so that visitors visiting the front page/start page only will get the data associated with the specific page or element. Instead of a required data download on 4-5MB, your users might only have to download 100-200KB, which is a huge saving. 

If you have 10.000 unique visitors per month without any cached data, and they all only visit your start page, they all save around 4800KB per visit. Then you would have saved your users approximately 45,7GB in total.

Why code splitting is beneficial for your server and the environment

We mentioned in the section before that most web apps are 4-5MB in file size once compiled, which doesn’t sound like a lot, but is much when you put all the numbers together. When you split your code you lower the amount of data your users have to download before seeing the first paint, and that both speeds up your website and is better for the environment. 

Let’s create an example where 80% of your users in a month only visit your Startpage. On your web app, you have a Startpage and 6 additional pages with lots of data and charts. Most of the data come from the 6 additional pages which mean the Startpage would be the smallest. In this example, the 6 additional pages are 4.5MB and the Startpage is 350KB. In total that will be 4.850MB. With 5.000 visitors in a month and no cached files that would be approximately 23.6GB of data. If your visitors only had to load the Startpage it would instead be approximately 1.6GB of data needed to be processed and sent by your server. As you can see by the numbers, the data went down drastically and this improves both the performance of your server and makes it more sustainable than it was before.

Code splitting speeds up your web application and makes it more accessible to people

One topic is to talk about the sustainability of code splitting but something equally important is that you can make your web application more accessible to people. 

When you lower the amount of data that your users need to download and process in their web browsers you speed up the whole experience. Believe it or not, but there are still many places in the world where they use 3G as their fastest connection, and a smaller bundle would make a big difference for them. Sadly we tend to build more CPU-demanding websites as our internet speeds become faster. In general, we should be doing the opposite because smaller websites would load faster at a faster internet connection. Taking into consideration that most peoples get impatient within 2-3 minutes and thereafter choose another website, then we would be doing both them and us (the website owners) a favor by lowering the total file size.

Wrapping up

In this article, we talked about how to use dynamic imports/code splitting in Svelte, and hopefully, by now you have an idea of how to handle it in your web application. 

We also talked about why it is a good idea to be splitting your code and which benefits it brings to the environment, your users, and your server. If you have other ways to look at this topic or have anything to add, then we would love to hear from you. To contact us, please use the form on our contact page which you will find at the top of the website and in the footer.