Storybook: Use pre-processors (like sass/scss, stylus, etc) with VueJs sfc in storybooks (extending webpack with loaders)

Created on 16 Feb 2018  Â·  4Comments  Â·  Source: storybookjs/storybook

Issue details

I would like to use pre-processors _(mainly scss)_ with VueJs Single File Components.

_Extending the Button.vue (of the Kitchen Sink)_

<style lang="scss">
  .button {
    border: 3px solid;
    padding: 10px 20px;
    background-color: white;
    outline: none;

    &.--rounded {
      border-radius: 5px;
    }
  }
</style>

Doing the following steps, causes stories to be empty.

Steps to reproduce

1. Install sass-loader & node-sass:

According the vue-loader documentation, you need to install the npm packages sass-loader & node-sass:

npm install sass-loader node-sass --save-dev

2. Extend the webpack.config.js by Including the ‘loader’ in the ‘module’:
_Using the Full control mode + default_

const path = require('path');
const webpack = require('webpack');

module.exports = (storybookBaseConfig, configType, defaultConfig) => {
  // configType has a value of 'DEVELOPMENT' or 'PRODUCTION'
  // You can change the configuration based on that.
  // 'PRODUCTION' is used when building the static version of storybook.

// ------------------------------------ ADDED START ------------------------------------ 
  // Extend it as described in the vue-loader documentation
  defaultConfig.module.rules.push({
    test: /\.vue$/,
    include: path.resolve(__dirname, '../src'),
    loader: 'vue-loader',
    options: {
      loaders: {
        scss: 'vue-style-loader!css-loader!sass-loader', // <style lang="scss">
        sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax' // <style lang="sass">
      }
    }
  });
// ------------------------------------ ADDED END ------------------------------------ 

  // Make whatever fine-grained changes you need
  defaultConfig.plugins.push(
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      chunks: ['preview'],
      minChunks: function (module) {
        // this assumes your vendor imports exist in the node_modules directory
        return module.context && module.context.indexOf("node_modules") !== -1;
      },
    })
  );
  // config.resolve.extensions.push('.vue');

  // Return the altered config
  return defaultConfig;
};

3. Running the Storybook:

npm run storybook
> [email protected] storybook C:\vue-kitchen-sink
> start-storybook -p 9009 -s public

info @storybook/vue v3.4.0-alpha.8
info
info => Loading static files from: C:\vue-kitchen-sink\public .
=> Loading custom .babelrc
=> Loading custom addons config.
=> Loading custom webpack config (full-control mode).
webpack built f69a7575bbf3851ad9f1 in 7347ms
info Storybook started on => http://localhost:9009/
info

No errors. But stories are empty.

Please specify which version of Storybook and optionally any affected addons that you're running

  • @storybook/vue 3.1.13
  • @storybook/vue ^3.4.0-alpha.8

Affected platforms

  • Affected on everywhere platform
  • Webpack config might be the issue i guess

Screenshots / Screencast / Code Snippets (Optional)

_Below I'll just post the code of the files that are involved.
Basically there are no major changes, except the block in the webpack.config.js.
Everything is based on the vue-kitchen-sink provided by the storybook package, which worked as expected before the changes had been made._

Button.vue

<template>
  <div>
    <button class="button" :style="{color: color, borderColor: color}" @click="handleClick" :class="{'button--rounded': rounded}"><slot></slot>!</button>
  </div>
</template>

<script>
  export default {
    props: {
      rounded: Boolean,
      handleClick: {
        default: () => () => null
      },
      color: {
        default: '#42b983'
      }
    }
  }
</script>

<style lang="scss">
  .button {
    border: 3px solid;
    padding: 10px 20px;
    background-color: white;
    outline: none;

    &.--rounded {
      border-radius: 5px;
    }
  }
</style>

package.json

{
  "name": "vue-example",
  "version": "3.4.0-alpha.8",
  "private": true,
  "scripts": {
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
    "build-storybook": "build-storybook -s public",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "storybook": "start-storybook -p 9009 -s public"
  },
  "dependencies": {
    "vue": "^2.5.13",
    "vuex": "^3.0.0"
  },
  "devDependencies": {
    "@storybook/addon-actions": "^3.4.0-alpha.8",
    "@storybook/addon-centered": "^3.4.0-alpha.8",
    "@storybook/addon-knobs": "^3.4.0-alpha.8",
    "@storybook/addon-links": "^3.4.0-alpha.8",
    "@storybook/addon-notes": "^3.4.0-alpha.8",
    "@storybook/addon-storyshots": "^3.4.0-alpha.8",
    "@storybook/addon-viewport": "^3.4.0-alpha.8",
    "@storybook/addons": "^3.4.0-alpha.8",
    "@storybook/vue": "^3.4.0-alpha.8",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.0",
    "babel-preset-vue": "^2.0.1",
    "cross-env": "^5.1.3",
    "css-loader": "^0.28.9",
    "file-loader": "^1.1.6",
    "node-sass": "^4.7.2",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.20.1",
    "vue-hot-reload-api": "^2.2.4",
    "vue-loader": "^13.7.1",
    "vue-style-loader": "^3.1.2",
    "vue-template-compiler": "^2.5.13",
    "webpack": "^3.11.0",
    "webpack-dev-server": "^2.11.1"
  }
}

webpack.config.js

const path = require('path');
const webpack = require('webpack');

module.exports = (storybookBaseConfig, configType, defaultConfig) => {
  // configType has a value of 'DEVELOPMENT' or 'PRODUCTION'
  // You can change the configuration based on that.
  // 'PRODUCTION' is used when building the static version of storybook.

  defaultConfig.module.rules.push({
    test: /\.vue$/,
    include: path.resolve(__dirname, '../src'),
    loader: 'vue-loader',
    options: {
      loaders: {
        scss: 'vue-style-loader!css-loader!sass-loader', // <style lang="scss">
        sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax' // <style lang="sass">
      }
    }
  });

  // Make whatever fine-grained changes you need
  defaultConfig.plugins.push(
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      chunks: ['preview'],
      minChunks: function (module) {
        // this assumes your vendor imports exist in the node_modules directory
        return module.context && module.context.indexOf("node_modules") !== -1;
      },
    })
  );
  // config.resolve.extensions.push('.vue');

  // Return the altered config
  return defaultConfig;
};
vue compatibility with other tools

Most helpful comment

still have the same issue in 4.0.0 or 4.0.4 for storybook/vue

All 4 comments

I suspect that this is actually a configuration issue. We're using vue, scss, and storybooks at work and it works fine.

Vue loader will handle all calling the loader automatically for you. All you should have to do is install sass-loader and node-sass.

It's definitely a configuration issue, no doubt, but just installing sass-loader and node-sass seems not to be enough.

Are you using scss in your vue components at work? (within style-tag in the FooComponent.vue)

My steps to test scss in vue components:

git clone https://github.com/storybooks/storybook.git .
cd examples/vue-kitchen-sink/
npm install sass-loader node-sass --save-dev
npm install
npm run storybook

editing ./src/stories/Button.vue

1. Changing style to something sassy:

<style>
  .button {
    border: 3px solid;
    padding: 10px 20px;
    background-color: white;
    outline: none;

    &.--rounded {
      border-radius: 5px;
    }
  }
</style>

2. Apply the changes to the template:

<template>
  <button 
    class="button"
    :style="{color: color, borderColor: color}"
    @click="handleClick"
    :class="{'button--rounded': rounded}" <!-- change to button-rounded -->
  >
    <slot></slot>!
  </button>
</template>

Previewing the Rounded Button in the storybook shows the class has been added to the button, but the nested styles, fx. button--rounded, are not provided.

That's why I tried to override the webpack config in my first example above, according the vue-loader documentation, which leads to empty stories. ¯_(ツ)_/¯

If styles in vue sfc works for you, i would appreciate a snippet of your config(s) and package.json, if that is possible.

Embarrassing!

@zephraph it's absolutely true, that you only have to install sass-loader and node-sass...
I was using ampersand-syntax the wrong way, which I didn't notice. 👎

Don't do: &.--rounded { it is just &--rounded { without a dot. Really sorry for this fail.

still have the same issue in 4.0.0 or 4.0.4 for storybook/vue

Was this page helpful?
0 / 5 - 0 ratings