The 3S - Svelte, Sass and StoryBook
Tags: html, frontend, css, webdev
Published: 2020-01-07 20:36:37

---
title: The 3S - Svelte, Sass and StoryBook
published: true
description: Setting up the sass in svelte with storybook
tags: #html #frontend #css #webdev
---

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,
```html
<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>
```
### Configure Rollup
Your cloned template uses [rollup](https://rollupjs.org/) 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](https://npmjs.org/package/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
```js
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
				});
			}
		}
	};
}

```
Looking at the specific coding part in the above config. Includes sass in the src directory and use an autoprefixer for browser dependency.
```js
const preprocess = autoPreprocess({ 
	scss: { includePaths: ['src'] },
	postcss: {
		plugins: [ require('autoprefixer') ],
	},
});
```

### 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](https://i.imgur.com/sPQBuR1.png)

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

Then create a file `svelte.config.js` in your root directory. Add the following contents.
```js
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'),
            };
        },
    },
};
```

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


### Configure Storybook

Assuming, you would've followed the default [steps](https://storybook.js.org/docs/guides/guide-svelte/) and add storybook to your project.

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

```js
// 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;
}
```

In the above code, we've overridden the [svelte-loader](https://npmjs.com/package/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.