Dan Knights
Dan Knights

Reputation: 8368

Uncaught Error: 'target' is a required option - Svelte

I'm building an NPM package for Svelte. With this package I export a couple of simple components:

import SLink from './SLink.svelte';
import SView from './SView.svelte';

export { SLink, SView };

This is before bundling them to a minified version using rollup.

Rollup config:

module.exports = {
    input: 'src/router/index.ts',
    output: {
        file: pkg.main,
        format: 'umd',
        name: 'Router',
        sourcemap: true,
    },
    plugins: [
        svelte({
            format: 'umd',
            preprocess: sveltePreprocess(),
        }),
        resolve(),
        typescript(),
        terser(),
    ],
};

package.json (minus unnecessary info):

{
    "name": "svelte-dk-router",
    "version": "0.1.29",
    "main": "dist/router.umd.min.js",
    "scripts": {
        "lib": "rollup -c lib.config.js",
    },
    "peerDependencies": {
        "svelte": "^3.0.0"
    },
    "files": [
        "dist/router.umd.min.js"
    ],
}

When I publish the package and test it, I get this error:

Uncaught Error: 'target' is a required option
    at new SvelteComponentDev (index.mjs:1642)
    at new Home (App.svelte:5)
    at Z (router.umd.min.js:1)
    at N (router.umd.min.js:1)
    at new t.SView (router.umd.min.js:1)
    at create_fragment (App.svelte:5)
    at init (index.mjs:1476)
    at new App (App.svelte:5)
    at main.js:7
    at main.js:9

Which seems to be something to do with mounting the component as target is used to mount:

const app = new App({ target: document.body })

The odd thing is, SLink on it's own works fine, mounts as it should etc., it's just SView that doesn't work.

SLink:

<script lang="ts">
    import { writableRoute, changeRoute } from '../logic';

    export let name: string = undefined,
        path: string = undefined,
        query: Record<string, string> = undefined,
        params: Record<string, string> = undefined;

    let routerActive: boolean;

    writableRoute.subscribe(newRoute => {
        if (newRoute.path === '*') return;
        const matches = (path && path.match(newRoute.regex)) || newRoute.name === name;
        routerActive = matches ? true : false;
    });
</script>

<div
    on:click={() => changeRoute({ name, path, query, params })}
    class={routerActive ? 'router-active' : ''}>
    <slot />
</div>

SView:

<script lang="ts">
    import { writableRoute } from '../logic';

    let component: any;

    writableRoute.subscribe(newRoute => (component = newRoute ? newRoute.component : null));
</script>

<svelte:component this={component} />

I've tried the components uncompiled, as per these docs, but then the imports don't work.

Anyone have any idea how I can work around this issue?

Upvotes: 9

Views: 5421

Answers (3)

jjnguy
jjnguy

Reputation: 138884

I recently ran into this problem. I was setting up a new page and forgot the defer keyword on the script. I had:

<script src="/app/public/build/bundle.js"></script>

and it needed to be

<script defer src="/app/public/build/bundle.js"></script>

Notice the missing defer.

Upvotes: 8

babakfp
babakfp

Reputation: 334

I don't know about your issue but I was getting the same error message for this reason: In the template.html file located in the src folder, I removed the element that has the #sapper ID and replaced the %sapper.html% code inside the body tag. The next thing to do was to change the render target to the document.body, in the client.js file located in the src folder. I forgot to do this step and this was causing that error message.

Upvotes: 0

rixo
rixo

Reputation: 25001

All components in a Svelte tree need to be compiled with the same Svelte compiler (i.e. same node_modules/svelte) all at once. This includes components from external libs like what you are trying to achieve. This is what is explained in the docs you've linked.

The main field of the package.json will expose the compiled components, for usage in a non Svelte app.

You also need a svelte field to expose the uncompiled version of the components, for consumption by a Svelte app. You can still export multiple Svelte components from a .js file.

package.json

{
    "name": "svelte-dk-router",
    "version": "0.1.29",
    "main": "dist/router.umd.min.js",

    "svelte": "src/index.js",

    "scripts": {
        "lib": "rollup -c lib.config.js",
    },
    "peerDependencies": {
        "svelte": "^3.0.0"
    },
    "files": [
        "dist/router.umd.min.js"
    ],
}

src/index.js

import SLink from './SLink.svelte';
import SView from './SView.svelte';

export { SLink, SView };

rollup-plugin-svelte will pick up the svelte field in your lib's package.json, so that import of Svelte components resolve correctly.

Upvotes: 3

Related Questions