Sapper: 500: <component> is not a valid SSR component

Created on 29 Jun 2019  路  12Comments  路  Source: sveltejs/sapper

When a component is imported from node_modules, Sapper shows a 500 page for about 400ms before displaying the content. After that, both the page and imported component display and work correctly.

This happens on Chrome, Firefox, and Safari with both Rollup and Webpack, but it does not happen on a regular Svelte app.

See this example repo

Note: The package.json of the imported component has a svelte field, and resolve.mainFields in webpack.config.js is set to include svelte.

Most helpful comment

In the case of your repro - If you move svelte-toolbox from a dependency to a devdependency, everything seems fine. See https://github.com/sveltejs/sapper-template#using-external-components

All 12 comments

Not a bug.

This happens because svelte-toolbox where you are importing the component from, doesn't expose SSR compatible components. I had a quick look at them and I don't know why, but you should ask the author to support SSR.

If you view source on the page you are seeing "break" the error is right there:

<UIButton> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules

Error: <UIButton> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules
    at validate_component (webpack:///./node_modules/svelte/internal/index.mjs?:1215:15)
    at Object (webpack:///./src/routes/index.svelte?:28:78)
    at Object.$$render (webpack:///./node_modules/svelte/internal/index.mjs?:1238:22)
    at Object.default (webpack:///./src/node_modules/@sapper/internal/App.svelte?:33:417)
    at Object (webpack:///./src/routes/_layout.svelte?:23:38)
    at Object.$$render (webpack:///./node_modules/svelte/internal/index.mjs?:1238:22)
    at Object (webpack:///./src/node_modules/@sapper/internal/App.svelte?:31:152)
    at $$render (webpack:///./node_modules/svelte/internal/index.mjs?:1238:22)
    at Object.render (webpack:///./node_modules/svelte/internal/index.mjs?:1246:26)
    at handle_page (webpack:///./src/node_modules/@sapper/server.mjs?:2393:93)

@antony, how is it then, that a regular Svelte app does not throw such an error?

https://svelte.dev/repl/c1d2319031a04bdd81dffc9501300ded?version=3.6.2

@Vehmloewff Svelte doesn't use SSR. It's just a client framework.

Svelte does use SSR. If you compile with the option generate: 'ssr', this results in a component with a different API - https://svelte.dev/docs#Server-side_component_API - and this is what Sapper uses. If a package exposes the original component sources via the svelte key in its package.json (which this package appears to), there's nothing special it needs to do to also support SSR beyond just not using stuff like window in code that might be run on the server.

Apologies - I meant that it didn't use SSR by default, which is why the error is not occuring when the component is imported into a regular Svelte application.

I hadn't realised @Vehmloewff that you were the author of svelte-toolbox - in that case, you're in a good place to fix it - the link posted above will detail the changes required for SSR (Sapper) support. I'd look in the Ripple.svelte class first, as it looks like there are some DOM specific bits which might not work in node.

In the case of your repro - If you move svelte-toolbox from a dependency to a devdependency, everything seems fine. See https://github.com/sveltejs/sapper-template#using-external-components

Thanks @Conduitry and @antony . Moving svelte-toolbox to a devDependency fixed the error.

Moving to devDependency worked, but why?

Because of this.

In my case, I've had crashes using the ResizeObserver component.
While adding it as a dev dependency sort of worked, there was still a flash of a server-side error during initial rendering.

The solution for this problem can actually be found in the sapper docs and initializes the component dynamically in onMount (which isn't called for SSR). Here's the gist:

<svelte:component this={ResizeObserver} on:resize={onPanelResize}/>
````
``` javascript
import {onMount} from 'svelte';
let ResizeObserver;

onMount(async () => {
        const module = await import('svelte-resize-observer');
        ResizeObserver = module.default;
    });

Hints:

  • Don't forget the onMount import from svelte
  • Don't forget to await the dynamic import 馃槈

@Dan1ve Thank you so much for you solution, took me so much time to find the solution.

I ran into this with svelte-mui and found the solution (in the docs of all places):

import { Button, Checkbox } from 'svelte-mui/src';

Need to import from src dir.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

keyvan-m-sadeghi picture keyvan-m-sadeghi  路  4Comments

Rich-Harris picture Rich-Harris  路  3Comments

BMorearty picture BMorearty  路  3Comments

mylastore picture mylastore  路  3Comments

SARFEX picture SARFEX  路  3Comments