programing

Storybook이 Vue 프로젝트의 컴포넌트에 SVG를 로드하지 않음

luckcodes 2022. 11. 27. 21:03

Storybook이 Vue 프로젝트의 컴포넌트에 SVG를 로드하지 않음

Vue 프로젝트를 작성했습니다.vue-cli및 설치storybook을 통해 나중에npm install --save-dev storybook내가 만든 컴포넌트를 보여주기 위한 의존관계로 사용할 수 있습니다.

Storybook Web Pack 설정은 다음과 같습니다.

const path = require('path')

module.exports = async ({ config, mode }) => {
  config.module.rules.push(
    {
      test: /\.svg$/,
      use: ['vue-svg-loader']
    },
    {
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'sass-loader',
          options: {
            sourceMap: false,
            data: '@import "./src/assets/styles/main.scss";'
          }
        }
      ],
      include: path.resolve(__dirname, '../')
    }
  )

  return config
}

그리고 이야기index.js다음과 같습니다.

import Vue from 'vue';
import { storiesOf } from '@storybook/vue';
import Alert from '../src/components/buttons/Alert.vue';

storiesOf('Components', module)
  .add('Alert', () => ({
    components: { Alert },
    template: '<Alert />'
  }))

SVG로 구성되는 컴포넌트를 로드하려고 하면 다음과 같이 표시됩니다.

여기에 이미지 설명 입력

컴포넌트 자체는 표시되지만 SVG가 없는 부분은 표시되지 않습니다.

흥미롭게도 Vue의 메인 앱에 컴포넌트를 표시하려고 하면 정상적으로 동작합니다.vue.config다음과 같습니다.

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        data: `@import "./src/assets/styles/main.scss";`
      }
    }
  },
  chainWebpack: config => {
    const svgRule = config.module.rule("svg");

    svgRule.uses.clear();

    svgRule.use("vue-svg-loader").loader("vue-svg-loader");
  }
};

왜?storybook메인 Vue 앱이 가능한 동안 svgs가 제대로 로드되지 않습니까?

편집: 웹 팩을 사용했을 뿐입니다.file-loader그것과는 전혀 관계가 없다는 것을 확실히 하기에는 너무 이르다vue-svg-loader:

{
  test: /\.(png|jpg|gif|svg)$/,
  use: [
    {
      loader: 'file-loader',
      options: {},
    },
  ],
},

같은 에러가 발생하고 있습니다.바꿀 첫 번째 답변을 적용한 후push()을 지배하다unshift()다음 오류가 발생하였습니다.Error in parsing SVG: Non-whitespace before first tag.

편집 2:

로드하려는 SVG 중 하나입니다.

<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="exclamation-triangle" class="svg-inline--fa fa-exclamation-triangle fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"></path></svg>

편집 3: *Alert.vue 위치projectroot/src/components/banners/Alert.vue, Storybook의 Webpack 설정은 다음과 같습니다.projectroot/.storybook/webpack.config.js

<template>
  <div v-if="show" :class="`alert_wrap ${model}`">
    <IconBase>
      <component :is="iconComponent" />
    </IconBase>
    <div class="alert_text">
      <p v-if="title">{{ title }}</p>
      <p>{{ msg }}</p>
    </div>
    <IconBase>
      <TimesIcon @click="show = !show" aria-hidden="Close" />
    </IconBase>
  </div>
</template>

<script>
import IconBase from "../icons/IconBase.vue";
import CautionIcon from "../../assets/icons/exclamation-triangle-solid.svg";
import InfoIcon from "../../assets/icons/info-circle-solid.svg";
import SuccessIcon from "../../assets/icons/check-circle-solid.svg";
import TimesIcon from "../../assets/icons/times-solid.svg";

export default {
  name: "Alert",
  components: {
    CautionIcon,
    InfoIcon,
    SuccessIcon,
    TimesIcon,
    IconBase
  },
  props: {
    msg: {
      type: String,
      required: true
    },
    title: {
      type: String
    },
    model: {
      type: String,
      default: "info",
      validator(type) {
        return ["caution", "info", "success"].includes(type);
      }
    }
  },
  computed: {
    iconComponent() {
      return `${this.model}-icon`;
    }
  },
  data() {
    return {
      show: true
    };
  }
};
</script>

<style scoped lang="scss">
  /* some styles depending on the props passed */
</style>

@liximomo의 답은 거의 맞습니다.삭제해야 합니다.svg에서 줄서다.file-loader규칙 검색 조건은 약간 달라야 합니다.

module.exports = ({ config }) => {

    let rule = config.module.rules.find(r =>
        // it can be another rule with file loader 
        // we should get only svg related
        r.test && r.test.toString().includes('svg') &&
        // file-loader might be resolved to js file path so "endsWith" is not reliable enough
        r.loader && r.loader.includes('file-loader')
    );
    rule.test = /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/;

    config.module.rules.push(
        {
            test: /\.svg$/,
            use: ['vue-svg-loader']
        }
    )

    // ...

    return config;
}

웹 팩 설정 규칙을 변경하지 않고 SVG를 Import하는 또 다른 방법은 인라인 로더를 지정하는 것입니다.인라인 로더는 일부 컴포넌트가 이미 CSS 또는 HTML에서 SVG를 파일 경로로만 사용하고 있을 때 오류를 방지하는 데 유용합니다.예:

// disable all rules with !! and use just vue-svg-loader
import CautionIcon from "!!vue-svg-loader!../../assets/icons/exclamation-triangle-solid.svg";

왜냐면storybook이미 가지고 있다file-loader배출하다svg자산으로서.제외해야 한다svg부터file-loader첫번째.

// exclude svg from existing rule
config.module.rules = config.module.rules.map(rule => {
  if (rule.loader && rule.loader.endsWith('file-loader')) {
    return {
      ...rule,
      test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
    };
  }

  return rule;
});

// now we can add our svg loader
config.module.rules.push(
    {
      test: /\.svg$/,
      use: ['vue-svg-loader']
    },
    {
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'sass-loader',
          options: {
            sourceMap: false,
            data: '@import "./src/assets/styles/main.scss";'
          }
        }
      ],
      include: path.resolve(__dirname, '../')
    }
  )

UTF-8 인코딩을 사용하고 있습니까?

에러

SVG 구문 분석 오류: 첫 번째 태그 앞에 공백이 없습니다.

Byte-Order-Mark(BOM; 바이트 순서 마크)를 사용한 부호화에 관련짓습니다.

Windows 시스템에서 자동으로 utf-8 파일에 추가되는 "Zero width no-break space" 유니코드 문자

16진 에디터로 파일을 조사하면 범인을 알 수 있습니다.

파일을 로드하기 전에 수동으로 인코딩을 "Without BOM"으로 변경하거나 replace("\uffe", "")와 같은 것으로 대체할 수 있습니다.

에디터를 사용하고 있는 경우는, 특정의 「BOM」부호화에 관한 설정이 있는 경우가 있습니다.예를 들어, 메모장++

jsx 옵션을 추가할 코드

 loader: 'file-loader',
      options: {
        jsx: true,
      },

언급URL : https://stackoverflow.com/questions/56971513/storybook-does-not-load-svgs-in-components-of-vue-project