Search code examples
node.jsyarnpkgsvelterollupjssapper

Sapper/Svelte/Rollup external dependencies best practice?


Smart people!

I’m a bundler-beginner with a bundler slash dependency-question.

  • On yarn dev run I get the error: "Cannot find module '@sveltejs/svelte-scroller'..."
  • I have a sapper/svelte/rollup/yarn-suite
  • the svelte-scroller-plugin

The plugin is by default loaded as an external in rollup.config.js:

{ ..., server: { ..., external: <**package.json-dependencies-arr**> } ... }

And when I use it in a .svelte-component:

import Scroller from '@sveltejs/svelte-scroller';

//...

<Scroller />

...the error slaps my face.

Notes

  • rollup.config.js is unchanged from the template clone

  • If I remove the plugin from the dependencies-arr loaded as externals in rollup.config.js the error goes away.

  • ...which tells me that rollup shouldn't load the dependency as an external (assuming the only goal is to make the specified error vanish).

  • And since svelte-scroller's purpose here is client-interaction-related, I presume it shouldn't be a part of the bundle either way.

  • Of course cyberspace has related issues, but I can't seem to find a clear best practice example on how to handle this.

  • My current workaround is therefore:

     // in rollup.config.js
     import pkg from './package.json';
    
     // filter out those "not external dependencies" 
     const notExternals = ['@sveltejs/svelte-scroller'];
     const externals = Object.keys(pkg.dependencies).filter(plugin =>
         notExternals.some(not => not === plugin) ? false : true
     );
    
     export default {
         // ...,
         server: {
             // ...,
             // bundle filtered externals (along with default built in modules)
             external: externals.concat(require('module').builtinModules),
         },
         // ...
     }
    

And if the error revisits with another dependency, I'll just add it to the notExternals-arr.

Question

  1. Considering the sapper/svelte/rollup-setup, is this approach best practice when handling client-based plugins causing similar errors?

Thanks in advance!

Stack

internal/modules/cjs/loader.js:896
  throw err;
  ^

Error: Cannot find module '@sveltejs/svelte-scroller'
Require stack:

    - /.../__sapper__/dev/server/server.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:893:15)
    at Function.Module._load (internal/modules/cjs/loader.js:743:27)
    at Module.require (internal/modules/cjs/loader.js:965:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/.../__sapper__/dev/server/server.js:8:16)
    at Module._compile (internal/modules/cjs/loader.js:1076:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1097:10)
    at Module.load (internal/modules/cjs/loader.js:941:32)
    at Function.Module._load (internal/modules/cjs/loader.js:782:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/.../__sapper__/dev/server/server.js'
  ]
}

Reproduce if you dare

template

npx degit "sveltejs/sapper-template#rollup" <app-name>

plugin

yarn add @sveltejs/svelte-scroller

import the plugin to a .svelte-component

<script>
   import Scroller from '@sveltejs/svelte-scroller';
</script>

//...

<Scroller />

go

yarn run dev

Solution

  • Because @sveltejs/svelte-scroller is a Svelte component rather than a JS module, it must be processed by the Svelte compiler at build time rather than imported at runtime. In other words, it should be part of your bundle.

    The conventional way to do this, if the contents of dependencies are treated as external, is to add the package to devDependencies instead:

    yarn add -D @sveltejs/svelte-scroller