How to do code splitting using Svelte without Sapper

前端 未结 2 700
梦毁少年i
梦毁少年i 2020-12-30 10:24

How do you do code splitting with Svelte?

(I see that you could do it using Sapper, but I don´t want to take a dependency on a node backend)

2条回答
  •  悲哀的现实
    2020-12-30 11:09

    Code splitting is actually a fancy name for dynamic imports. Here's how to do it with Rollup (you'll also get killer tree-shaking in the process!).

    Reminder on dynamic imports:

    // "normal" static ES import
    //
    // - statically analytisable
    // - must be called at top level
    // - will be greedily resolved (and most often inlined) by your bundler
    //
    import Foo from './Foo.svelte'
    
    // dynamic import
    //
    // - called like a function
    // - returns a promise
    // - default export is accessible on key `default` of the result
    // - will be bundled into its own chunk by your bundler (hence code splitting)
    //
    import('./Foo.svelte').then(module => {
      const cmp = module.default
      console.log(module.myNamedExport)
    })
    

    Note that dynamic imports are a native ES feature, like normal imports. This means they are supported natively by non-outdated browsers.

    Rollup has been supporting "code splitting from dynamic imports" for a while (see docs).

    So, if you want code splitting in your project, it's mainly a matter of configuring Rollup so that it chunks dynamic imports (another option would be to resolve and inline them, which would not result in code splitting).

    Here are the steps to do this, starting from Svelte's official template.

    1. change output.format to 'es'
    2. change output.file to output.dir (e.g. 'public/build')
    3. change the

      First, we need to change the src from bundle.js (which was our old output.file) to the new entry point of our application. Since our entry point in the Rollup config (input) is src/main.js, the main entry point of our app will be written to main.js (configurable with Rollup's entryFileNames option).

      Since our code is now full of ES import statements (because we're using output.format='esm'), we also need to change the type of script from script (the default) to module by adding the type="module" attribute to our script tag.

      That's it for modern browsers, you now have fully working code splitting support!

      Actually split your application

      Code splitting support is not enough to get actual code splitting. It just makes it possible. You still need to separate dynamic chunks from the rest (main) of your application.

      You do this by writing dynamic imports in your code. For example:

      import('./Foo.svelte')
        .then(module => module.default)
        .then(Foo => { /* do something with Foo */ })
        .catch(err => console.error(err))
      

      This will result in Rollup creating a Foo-[hash].js chunk (configurable with chunkFileNames option), and possibly another chunk for dependencies of Foo.svelte that are shared with other components.

      In the browser, this file will only get loaded when the import('./Foo.svelte') statement is encountered in your code (lazy loading).

      (Notice, in the waterfall, how Foo and Cmp -- a common dep -- get loaded long after the page load, indicated by the vertical red bar.)

      Legacy browsers

      Edge (before recently becoming Chrome) does not support dynamic imports. Normal ES imports, yes, but dynamic import(...) no. That's usually why you have to include some polyfill for outdated browsers.

      One solution, like in the rollup-starter-code-splitting example, is to use a third party module loader (e.g. SytemJS) in the browser.

      Another, probably simpler, solution available these days is to use the dimport package. It polyfills support for ES imports and dynamic imports as needed by the host browser.

      In order to use it, we're replacing our

      And voilà. Full fledged code splitting. (Simpler than you thought, isn't it?)

      Complete example

      Here's a complete example implementing all the different bits covered in this answer. You might be particularly interested in this commit.

      Attention! Please notice that the example lives on the example-code-splitting branch of the repository, not master. You'll need to checkout the right branch if you clone the repo!

      Example usage:

      # install
      npx degit rixo/svelte-template-hot#example-code-splitting svelte-app
      cd svelte-app
      yarn # or npm install
      
      # dev
      yarn dev
      
      # build
      yarn build
      # serve build
      yarn start
      

提交回复
热议问题