svelte-webpack-demo Svelte Themes

Svelte Webpack Demo

Incremental Svelte with Webpack integration as an example.

Svelte Webpack Demo

See it live here

Add svelte globally

module.exports = {
    ...
    entry: {
        svelte: {
            import: './node_modules/svelte/src/index-client.js',
            library: {
                name: 'svelte',
                type: 'global'
            }
        }
        ...
    },
    ...
};

Setup loader

Add the svelte-loader

module.exports = {
    ...
    module: {
        rules: [
            {
                test: /\.(svelte|svelte\.js)$/,
                use: 'svelte-loader'
            },
            {
                // required to prevent errors from Svelte on Webpack 5+, omit on Webpack 4
                test: /node_modules\/svelte\/.*\.mjs$/,
                resolve: {
                    fullySpecified: false
                }
            }
        ]
    },
    resolve: {
        extensions: ['.json', '.js', '.jsx', '.svelte'],
        conditionNames: ['svelte']
    }
    ...
}

Create component and entrypoint

In src/Counter.svelte, let's define the following:

<script>
    export let count = 0;

    console.log("Counter loaded!");

    export function handleClick() {
        count += 1;
        return count;
    }

    export const getCount = () => count;
</script>

<button class="counter btn btn-primary" on:click={handleClick}>
    clicks: {count}
</button>

And, we'll have the bundler make us a .js distributable:

module.exports = {
    ...
    entry:{
        Counter: {
            import: './src/Counter.svelte',
            library: {
                name: 'Counter',
                type: 'global'
            }
        }
    }
    ...
}

Change webpack optimizations

Since we have multiple entry points that will overlap (e.g., svelte internals in this case), we will use a single runtime. The runtime in Webpack takes care of loading for us.

module.exports = {
    ...
    optimization: {
        runtimeChunk: 'single'
    },
    ...
};

If you skip this step, you will get an obscure error along the lines of: Uncaught TypeError: Cannot read properties of undefined (reading 'call')

Load bundles

<script src="dist/runtime.js"></script>
<script src="dist/svelte.js"></script>
<script src="dist/Counter.js"></script>

Mount component

After the scripts above, add:

<script>
    const container = document.getElementById('counter-container')
    const counter = svelte.mount(Counter,
        {
            target: container,
            props: {
                count: 1
            }
        }
    );
</script>

Notice, we initialized the count to 1 by providing it as a property.

Profit

The steps outlined here are usable for other bundlers too. The setup difficulty is less burdensome the technical debt and maintenance headache of glue logic.

Top categories

Loading Svelte Themes