How to fix "Function called outside component initialization" with Svelte
Recently, a sapper-based project went over the limit for the size of the built image sent to the cloud platform we were using. To reduce it I knew the easiest first step would be to make sure only runtime dependencies were in dependencies
in our package.json
by moving everything else to devDependencies
.
Svelte is a devDependency by default in the sapper template, but when I purged dependencies using yarn workspaces focus --all --production
, @urql/svelte
threw an error:
Error: Cannot find module 'svelte/store'
Require stack:
- ./node_modules/@urql/svelte/dist/urql-svelte.js
- ./__sapper__/build/server/server-782caa63.js
- ./__sapper__/build/server/server.js
- ./__sapper__/build/index.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
But when I moved svelte
to a dependency I got an error saying Function called outside component initialization
. This is documented on the now-defunct sapper issue tracker in issue #592 with the suggested fix being to put svelte
back as a devDependency
. So I was stuck between two different errors.
I discovered a workaround, though. All I had to do was open up and change rollup.config.js
. The default export has a key for the server, and inside server there is a key for external modules. These are the modules that should be imported from node_modules. By default the template contains this code:
external: Object.keys(pkg.dependencies).concat(require('module').builtinModules),
In short, this finds all the non-dev dependencies and tells rollup they are external. By changing it to filter out svelte, we can let rollup continue to import the locally built svelte runtime.
external: Object.keys(pkg.dependencies)
.filter((packageName) => packageName !== 'svelte')
.concat(require('module').builtinModules),
And this works while still allowing @urql/svelte
to import it after purging of the dev dependencies.
Not perfect, but a workaround that works.