Storybook: Packing CSS images

Created on 4 Apr 2016  路  16Comments  路  Source: storybookjs/storybook

When there is an image or a font embedded in the CSS, it is not loaded in the storybook. I tried adding

{ test: /\.(png|jpe?g)(\?.*)?$/, loader: 'url?limit=8182' },
{ test: /\.(svg|ttf|woff|eot)(\?.*)?$/, loader: 'file' }

but this only solves the resolution of the file, yet it is not loade from the correct URL. For example this fails for icon files in semantic ui and bootstrap:

GET http://localhost:9001/themes/default/assets/fonts/icons.ttf  404
bug

Most helpful comment

@tomitrescak @purplecones there could be more than one static directories. You can pass them to storybook -s as a comma separated list. So you can do,

start-storybook -p 9001 -s ./assets,/path/to/themes/directory

picked this info from #229

All 16 comments

Do you why is this? What's the normal webpack config we used when doing this?
Then we can see how to do something on this.

I am pretty new to webpack. So, any help would be great.

Unfotunatelly I'm not a webpack master. @exon, would you be able to shed some light on this please? What is needed to be done to serve static assets from webpack?

Hi @tomitrescak I just had the same issue, I fixed it by specifying a static directory. So you can run

start-storybook -p 6977 -s ./dist

in this example ./dist is the output dir that webpack will put the files, so my webpack output config looks like this:

  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/'
  },

and I changed my package.json scripts block to

  "scripts": {
    "start": "node server.js",
    "storybook": "start-storybook -p 6977 -s ./dist"
  },

See here https://github.com/kadirahq/react-storybook/blob/master/docs/api.md#static-directory

@stewartduffy that is great! Woulf you be please so kind and post the whole webpack configuration file? Thanks!!

Hi @tomitrescak sorry about the delayed response.

So I currently have 2 webpack configs - one at the root dir & one in .storybook:

.storybook/webpack.config.js

const path = require('path');

module.exports = {
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel', // 'babel-loader' is also a legal name to reference
        query: {
          presets: ['es2015']
        },
        include: path.resolve(__dirname, '../')
      },
      {
        test: /\.css?$/,
        loaders: [ 'style', 'raw' ],
        include: path.resolve(__dirname, '../')
      },
      {
        test: /\.scss$/,
        loaders: ["style", "css", "sass"],
        include: [
          path.resolve(__dirname, '../client/'),
          path.resolve(__dirname, '../components/')
        ],
        exclude: path.resolve(__dirname, '../dist/')
      }
    ]
  }
}

And my root webpack.config.js

var path = require('path')
var webpack = require('webpack')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var autoprefixer = require('autoprefixer')

module.exports = {
  devtool: 'cheap-module-eval-source-map',
  entry: [
    './index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/'
  },
  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new ExtractTextPlugin('styles.css')
  ],
  module: {
    loaders: [
      {
        test: /\.js$/,
        loaders: [ 'babel' ],
        exclude: /node_modules/,
        include: __dirname
      },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel', // 'babel-loader' is also a legal name to reference
        query: {
          presets: ['es2015']
        },
        include: path.resolve(__dirname, '../')
      },
      {
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader!sass-loader!postcss-loader'),
        include: __dirname
      },
      {
        test: /\.(jpe?g|jpg|gif|png|woff|woff2|eot|ttf|svg)$/,
        loaders: [
          'url?limit=10000',
          'img'
        ],
        include: __dirname
      }
    ]
  },
  postcss: function () {
    return [autoprefixer]
  }
}

The reason for 2 configs is at the time, storybook didn't allow for anything in .storybook/webpack.config.js other than loaders. So I had webpack --watch running on my root dir & then ran storybook. I know this was a slightly hacky solution, but I think the changes in PR #64 will fix this. Will update today & see how it goes.

Did this help?

@tomitrescak The following config is working fine for me to load fonts and images. Might be helpful.

const path            = require('path');

module.exports = {
  module: {
    loaders: [
      {
        test   : /\.scss$/,
        loaders: ["style", "css", "sass"],
        include: path.resolve(__dirname, '../')
      },
      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: "url-loader?limit=10000&mimetype=application/font-woff"
      },
      {
        test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: "file-loader"
      }
    ]
  }
};

Works for me as well, thanks guys! Amazing stuff.

Guys, sorry to ask this here, but you seem to have much better understanding of webpack than me. I have a problem when storybook is not loading icons.woff and icons.tts from semantic ui. The framework is trying to load them from "themes/default/assets" directory. How can I mount assets to storybooks webpack so that they are then served from the correct url? Maybe webapck can even parce css and serve these files automatically? Not sure here ....

@tomitrescak were you able to load the fonts that come with semantic-ui with storybook? I'm having issue with the fonts and icons that semantic ui uses. See image.

react_storybook

The only way to go is to copy icons and all other required file to the asset directory which you configure when you run storybook. Copy the files into the "default" directory (see where sui is trying to load it from). Then configure loaders as above. And you are done.

@tomitrescak @purplecones there could be more than one static directories. You can pass them to storybook -s as a comma separated list. So you can do,

start-storybook -p 9001 -s ./assets,/path/to/themes/directory

picked this info from #229

@roonyh I have this

"storybook": "start-storybook -p 9001 -s ./node_modules/semantic-ui-css/themes/default/assets/fonts/"

but it still does not load the assets

GET http://localhost:9001/themes/default/assets/fonts/icons.woff2 
:9001/themes/default/assets/fonts/icons.woff:1
GET http://localhost:9001/themes/default/assets/fonts/icons.woff 
:9001/themes/default/assets/fonts/icons.ttf:1
GET http://localhost:9001/themes/default/assets/fonts/icons.ttf 

@tomitrescak I also wasn't able to get the fonts to load by copying them to the 'default' folder in the semantic-ui-css module

@purplecones That config will make the fonts available at root. At url http://localhost:9001/icons.woff2

What you probably should do is giving -s the path to the themes directory. So try,

"storybook": "start-storybook -p 9001 -s ./node_modules/semantic-ui-css"

This will make them available at http://localhost:9001/themes/default/assets/fonts/icons.woff2

@roonyh that did it. Thanks for that insight!

Also just for future references, you can also put the * to catch-all. For example if */assets is the argument, it will make all directories with the name assets.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dnlsandiego picture dnlsandiego  路  3Comments

xogeny picture xogeny  路  3Comments

Jonovono picture Jonovono  路  3Comments

miljan-aleksic picture miljan-aleksic  路  3Comments

ZigGreen picture ZigGreen  路  3Comments