我已经使用vue-cli
创建了一个Vue项目,并稍后通过storybook
安装了npm install --save-dev storybook
作为显示我创建的组件的依赖项。
故事书的webpack配置如下:
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应用程序可以正常加载的同时正确加载svg?
编辑:我已经继续使用了file-loader
的webpack,以确保与vue-svg-loader
无关:
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {},
},
],
},
但是我遇到了同样的错误。
尝试应用第一个答案将push()
替换为unshift()
的规则后,出现此错误:Error in parsing SVG: Non-whitespace before first tag
。
Edit2 :
这是我要加载的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>
Edit3 :* projectroot/src/components/banners/Alert.vue
中的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>
答案 0 :(得分:2)
@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;
}
在不更改Webpack配置规则的情况下导入SVG的另一种方法是指定内联加载程序,当某些组件已经在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";
答案 1 :(得分:1)
因为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, '../')
}
)
答案 2 :(得分:0)