The 3S - Svelte, Sass and StoryBook

droidmakk

Afroze Kabeer Khan. M

Posted on January 7, 2020

The 3S - Svelte, Sass and StoryBook

I started to work on some project which I thought would help me to freelance and showcase my work. I've been working in React for years as of now. But two months before I was introduced to a framework called "svelte". Which had context, event bindings and the best is no Virtual DOMs.

So I thought why don't we implement the project using Svelte after all adapt and evolve is the best way we could deliver the best of solutions to clients. With this in my mind. I usually have a component library that showcases all of my components.

To Encourage reusability and document the UI. I Used "Storybook".

The Usual way I used the sveltejs template and bootstrapped the project.
npx degit sveltejs/template my-supercool-app

I wanted to add sass to my project. As to use a proper implementation I had to configure in three places as I will be using sass inline.

  • rollup
  • vscode
  • storybook

Below is a simple svelte component using sass,

<script type="text/javscript" >
    export const title;
<script>
<style type="text/scss" lang="scss" >
    div{
        display: flex;
        button {
            margin:auto;
        }
    }
</style>
<div>
    <button>{title}</button>
</div>
Enter fullscreen mode Exit fullscreen mode

Configure Rollup

Your cloned template uses rollup to bundle your app. So to configure it we need to install a few plugins to preprocess sass in your source.
Luckily svelte gives you a plugin svelte-preprocess which pre-process sass syntax also does more than that.

First let's install the plugin npm i -D svelte-preprocess autoprefixer
Then add it into rollup.config.js file

import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import autoPreprocess from 'svelte-preprocess';
import { terser } from 'rollup-plugin-terser';

const production = !process.env.ROLLUP_WATCH;

// Your Preprocess which compiles source code to sass
const preprocess = autoPreprocess({ 
    scss: { includePaths: ['src'] },
    postcss: {
        plugins: [ require('autoprefixer') ],
    },
});

export default {
    input: 'src/main.js',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/build/bundle.js'
    },
    plugins: [
        svelte({
            dev: !production,
            css: css => {
                css.write('public/build/bundle.css');
            },
            // adding the preprocess into svelte loader
            preprocess
        }),
        resolve({
            browser: true,
            dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/')
        }),
        commonjs(),
        !production && serve(),
        !production && livereload('public'),
        production && terser()
    ],
    watch: {
        clearScreen: false
    }
};

function serve() {
    let started = false;

    return {
        writeBundle() {
            if (!started) {
                started = true;

                require('child_process').spawn('npm', ['run', 'start', '--', '--log.format','dev'], {
                    stdio: ['ignore', 'inherit', 'inherit'],
                    shell: true
                });
            }
        }
    };
}

Enter fullscreen mode Exit fullscreen mode

Looking at the specific coding part in the above config. Includes sass in the src directory and use an autoprefixer for browser dependency.

const preprocess = autoPreprocess({ 
    scss: { includePaths: ['src'] },
    postcss: {
        plugins: [ require('autoprefixer') ],
    },
});
Enter fullscreen mode Exit fullscreen mode

Configure VS Code

If you're using vscode it'll start reporting your CSS as errors and the confusion starts.

  • For this to work open your settings.
  • Search for "svelte"
  • set your nodejs path in option Svelte -> Language-server: Runtime

Use below image for reference,
svelte node sass

Then install node-sass npm i -D node-sass

Then create a file svelte.config.js in your root directory. Add the following contents.

const sass = require('node-sass');

module.exports = {
    preprocess: {
        style: async ({ content, attributes }) => {
            if (attributes.type !== 'text/scss') {
                return;
            }

            const result = await sass.renderSync({
                data: content,
                sourceMap: 'style.css.map',
                omitSourceMapUrl: true,
            });

            return {
                code: result.css.toString('utf8'),
                map: result.map.toString('utf8'),
            };
        },
    },
};
Enter fullscreen mode Exit fullscreen mode

The Above code says that we want to process sass code using node-sass.

Configure Storybook

Assuming, you would've followed the default steps and add storybook to your project.

Now in .storybook folder create a file webpack.config.js to override default config with our customizations.

// import the preprocess from svelte config
const stylepreprocess = require('../svelte.config');

module.exports = async ({ config, mode }) => {
    let j;
    // Find svelteloader from the webpack config
    const svelteloader = config.module.rules.find((r, i) => {
        if (r.loader && r.loader.includes('svelte-loader')) {
            j = i;
            return true;
        }
    });

    // safely inject preprocess into the config
    config.module.rules[j] = {
        ...svelteloader,
        options: {
            ...svelteloader.options,
            style: stylepreprocess.preprocess.style
        }
    }

    // return the overridden config
    return config;
}
Enter fullscreen mode Exit fullscreen mode

In the above code, we've overridden the svelte-loader options with our own preprocess.

Try running npm run storybook, This should work.

Hopefully, this will help you better set up the development environment.
Happy Coding 👩‍💻👨‍💻

The Sample implementation will be added soon.

💖 💪 🙅 🚩
droidmakk
Afroze Kabeer Khan. M

Posted on January 7, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related