LoginSignup
8
3

More than 3 years have passed since last update.

【Vue/Storybook】SVGがStorybookに表示されない問題を解決する

Last updated at Posted at 2019-07-28

はじめに

Storybook with Vue上でSVGを表示するのに失敗していたので解決策をメモします。
SVGはvue-svg-loaderを使ってバンドルしています。

結論だけみたい方は以下リンクだけみてください。
解決策です

環境

Vue: 2.6.10
Storybook: 5.1.9
vue-svg-loader: 0.12.0

表示できない

設定アイコンを表示するコンポーネントを用意します。

<template>
  <setting-svg />
</template>

<script lang="ts">
import Vue from "vue";
import SettingSvg from "@/assets/img/svg/setting.svg";

export default Vue.extend({
  name: "SettingIcon",
  components: {
    SettingSvg
  }
});
</script>

Storybookを準備します。

import { storiesOf } from "@storybook/vue";
import SettingIcon from "./SettingIcon.vue";

storiesOf("Icon", module).add("設定アイコン", () => ({
  components: { SettingIcon },
  template: "<setting-icon />"
}));

これでアイコンを表示する用意ができました。
Storybookを起動します。

$ start-storybook

エラーは出ません。うまくいったと思いStorybookを表示します。

スクリーンショット 2019-07-28 23.21.39.png

何も表示されません。辛いです。
Storybookの webpack.config.js を確認します。

const path = require("path");
const rootPath = path.resolve(__dirname, "../src");

module.exports = async ({ config, mode }) => {
  config.resolve.alias["@"] = rootPath;
  config.resolve.alias["~"] = rootPath;

  config.module.rules.push({
    test: /\.s?css$/,
    loaders: ["style-loader", "css-loader", "sass-loader"]
  });

  config.module.rules.push({
    test: /\.svg(\?.*)?$/,
    loaders: ["vue-svg-loader"]
  });

  return config;
};

config.module.rules のSVG部分を出力してみます。

[
  {
    test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
    loader: '/Users/numatakeisuke/working/project/memory-album/node_modules/file-loader/dist/cjs.js',
    query: { name: 'static/media/[name].[hash:8].[ext]' }
  },
  { test: /\.svg(\?.*)?$/, loaders: [ 'vue-svg-loader' ] }
]

SVGにデフォルトで file-loader が当たっていることがわかります。
png などは残しておきたいので、 svg だけローダーの設定を変えます。

解決策

webpack.config.js を修正します。
SVGを file-loader の対象から外しています。

const path = require("path");
const rootPath = path.resolve(__dirname, "../src");

module.exports = async ({ config, mode }) => {
  config.resolve.alias["@"] = rootPath;
  config.resolve.alias["~"] = rootPath;

  config.module.rules = config.module.rules.map(rule => {
    if (rule.test.toString().includes("svg")) {
      const test = rule.test
        .toString()
        .replace("svg|", "")
        .replace(/\//g, "");
      return { ...rule, test: new RegExp(test) };
    } else {
      return rule;
    }
  });

  config.module.rules.push({
    test: /\.s?css$/,
    loaders: ["style-loader", "css-loader", "sass-loader"]
  });

  config.module.rules.push({
    test: /\.svg(\?.*)?$/,
    loaders: ["vue-svg-loader"]
  });

  return config;
};

Storybookを再起動すると無事に表示されました。

参考

8
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3