.storybook/webpack.config.js
const path = require('path');
const fs = require('fs');
// Export a function. Accept the base config as the only param.
module.exports = async ({ config, mode }) => {
// `mode` 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.
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
});
config.module.rules.push({
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {name: 'assets/[name].[hash:8].[ext]'},
},
],
});
config.module.rules.push({
test: /\.vue$/,
use: [
{
loader: "vue-svg-inline-loader",
options: { /* ... */ }
}
]
});
config.module.rules.push({
test: /\.svg$/,
loader: 'vue-svg-loader',
options: {name: 'assets/[name].[hash:8].[ext]'},
});
config.resolve.alias['@'] = path.resolve('src')
// Return the altered config
return { ...config, node: { fs: 'empty' } };
};
index.vue
<template>
<div>
<IconTest/>
</div>
</template>
<script>
import IconTest from "@/assets/svg/test-icon.svg"
export default {
components:{
IconTest
}
}
</script>
error:
Automention: Hey @backbone87 @elevatebart @pksunkara, you've been tagged! Can you give a hand here?
@gsaada Run storybook with --debug-webpack
webpack to see the entire webpack config. It's almost certainly the case that the rules you're adding are conflicting with existing rules added by storybook. The solution is probably to remove those conflicting rules.
@shilman Thank you for your response.
Here's the output after I add this flag.
As you can see there are 2 configs. I don't see any conflict.
{ name: 'manager',
mode: 'development',
bail: false,
devtool: 'none',
entry: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/server/common/polyfills.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/.storybook/addons.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/client/manager/index.js'
],
output: { path:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/public',
filename: '[name
].[chunkhash
].bundle.js',
publicPath: ''
},
cache: {},
plugins: [ DllReferencePlugin {
options: { context:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/node_modules',
manifest:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dll/storybook_ui-manifest.json'
}
},
HtmlWebpackPlugin {
options: { template:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/server/templates/index.ejs',
templateContent: false,
templateParameters: [Function: templateParameters
],
filename: 'index.html',
hash: false,
inject: false,
compile: true,
favicon: false,
minify: undefined,
cache: true,
showErrors: true,
chunks: 'all',
excludeChunks: [],
chunksSortMode: 'none',
meta: {},
title: 'Webpack App',
xhtml: false,
alwaysWriteToDisk: true
},
childCompilerHash: undefined,
childCompilationOutputName: undefined,
assetJson: undefined,
hash: undefined,
version: 4
},
DefinePlugin {
definitions: { 'process.env': { NODE_ENV: '"development"',
NODE_PATH: '""',
PUBLIC_URL: '""',
VUE_APP_SERVER_URL: '"http://localhost:4000"',
VUE_APP_GOOGLE_ANALYTICS_ID: '"UA-110665184-4"'
}
}
},
CaseSensitivePathsPlugin { options: {}, pathCache: {}, fsOperations: 0, primed: false
},
DefinePlugin {
definitions: { 'process.env.VUE_APP_SERVER_URL': '"http://localhost:4000"',
'process.env.VUE_APP_GOOGLE_ANALYTICS_ID': '"UA-110665184-4"'
}
}
],
module: { rules: [
{ test: /\.(mjs|jsx?)$/,
use: [
{ loader: 'babel-loader',
options: { cacheDirectory:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/.cache/storybook',
presets: [
[ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/preset-env/lib/index.js',
{ shippedProposals: true, useBuiltIns: 'usage'
}
]
],
plugins: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/plugin-proposal-object-rest-spread/lib/index.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/plugin-proposal-class-properties/lib/index.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js',
[ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/babel-plugin-emotion/dist/babel-plugin-emotion.cjs.js',
{ sourceMap: true, autoLabel: true
}
],
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/babel-plugin-macros/dist/index.js'
]
}
}
],
include: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app'
],
exclude: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules'
]
}
]
},
resolve: { extensions: [ '.mjs', '.js', '.jsx', '.json'
],
modules: [ 'node_modules'
],
alias: { '@emotion/core':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@emotion/core',
'@emotion/styled':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@emotion/styled',
'@storybook/addons':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/addons',
'@storybook/channels':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/channels',
'@storybook/components':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/components',
'@storybook/core-events':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core-events',
'@storybook/router':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/router',
'@storybook/theming':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/theming',
'@storybook/ui':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/ui',
'core-js':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/core-js',
'emotion-theming':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/emotion-theming',
'prop-types':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/prop-types',
react:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/react',
'react-dom':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/react-dom'
}
},
recordsPath:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/.cache/storybook/records.json',
optimization: { splitChunks: { chunks: 'all'
}, runtimeChunk: true
}
}
**info => Loading custom webpack config (full-control mode).
Preview webpack config**
{ mode: 'development',
bail: false,
devtool: '#cheap-module-source-map',
entry: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/server/common/polyfills.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/server/preview/globals.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/.storybook/config.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/webpack-hot-middleware/client.js?reload=true'
],
output: { path:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/public',
filename: '[name
].[hash
].bundle.js',
publicPath: ''
},
plugins: [ HtmlWebpackPlugin {
options: { template:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@storybook/core/dist/server/templates/index.ejs',
templateContent: false,
templateParameters: [Function: templateParameters
],
filename: 'iframe.html',
hash: false,
inject: false,
compile: true,
favicon: false,
minify: undefined,
cache: true,
showErrors: true,
chunks: 'all',
excludeChunks: [],
chunksSortMode: 'none',
meta: {},
title: 'Webpack App',
xhtml: false,
alwaysWriteToDisk: true
},
childCompilerHash: undefined,
childCompilationOutputName: undefined,
assetJson: undefined,
hash: undefined,
version: 4
},
DefinePlugin {
definitions: { 'process.env': { NODE_ENV: '"development"',
NODE_PATH: '""',
PUBLIC_URL: '"."',
VUE_APP_SERVER_URL: '"http://localhost:4000"',
VUE_APP_GOOGLE_ANALYTICS_ID: '"UA-110665184-4"'
}
}
},
WatchMissingNodeModulesPlugin {
nodeModulesPath:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules'
},
HotModuleReplacementPlugin {
options: {},
multiStep: undefined,
fullBuildTimeout: 200,
requestTimeout: 10000
},
CaseSensitivePathsPlugin { options: {}, pathCache: {}, fsOperations: 0, primed: false
},
ProgressPlugin {
profile: false,
handler: undefined,
modulesCount: 500,
showEntries: false,
showModules: true,
showActiveModules: true
},
DefinePlugin {
definitions: { 'process.env.VUE_APP_SERVER_URL': '"http://localhost:4000"',
'process.env.VUE_APP_GOOGLE_ANALYTICS_ID': '"UA-110665184-4"'
}
},
VueLoaderPlugin {}
],
module: { rules: [
{ test: /\.(mjs|jsx?)$/,
use: [
{ loader: 'babel-loader',
options: { cacheDirectory:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/.cache/storybook',
presets: [
[ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/preset-env/lib/index.js',
{ shippedProposals: true, useBuiltIns: 'usage'
}
],
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/babel-preset-vue/dist/babel-preset-vue.cjs.js'
],
plugins: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/plugin-proposal-object-rest-spread/lib/index.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/plugin-proposal-class-properties/lib/index.js',
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js',
[ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/babel-plugin-emotion/dist/babel-plugin-emotion.cjs.js',
{ sourceMap: true, autoLabel: true
}
],
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/babel-plugin-macros/dist/index.js'
]
}
}
],
include: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app'
],
exclude: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules'
]
},
{ test: /\.md$/,
use: [
{ loader:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/raw-loader/index.js'
}
]
},
{ test: /\.vue$/,
loader:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/vue-loader/lib/index.js',
options: {}
},
{ test: /\.css$/,
use: [ '/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/style-loader/index.js',
{ loader:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/css-loader/dist/cjs.js',
options: { importLoaders: 1
}
},
{ loader:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/postcss-loader/src/index.js',
options: { ident: 'postcss', postcss: {}, plugins: [Function: plugins
]
}
}
]
},
{ test:
/\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
loader:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/file-loader/dist/cjs.js',
query: { name: 'static/media/[name
].[hash: 8
].[ext
]'
}
},
{ test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
loader:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/url-loader/dist/cjs.js',
query: { limit: 10000, name: 'static/media/[name
].[hash: 8
].[ext
]'
}
},
{ test: /\.scss$/,
use: [ 'style-loader', 'css-loader', 'sass-loader'
]
},
{ test: /\.(png|jpg|gif)$/,
use: [
{ loader: 'file-loader',
options: { name: 'assets/[name
].[hash: 8
].[ext
]'
}
}
]
},
{ test: /\.vue$/,
use: [
{ loader: 'vue-svg-inline-loader', options: {}
}
]
},
{ test: /\.svg$/,
loader: 'vue-svg-loader',
options: { name: 'assets/[name
].[hash: 8
].[ext
]'
}
}
]
},
resolve: { extensions: [ '.mjs', '.js', '.jsx', '.json', '.vue'
],
modules: [ 'node_modules'
],
alias: { 'core-js':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/core-js',
react:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/react',
'react-dom':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/react-dom',
'vue$':
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/vue/dist/vue.esm.js',
'@': '/mnt/c/Users/saada/Development/novos-client-ow-app/app/src'
}
},
optimization: { splitChunks: { chunks: 'all'
},
runtimeChunk: true,
minimizer: [ TerserPlugin {
options: { test: /\.m?js(\?.*)?$/i,
chunkFilter: [Function: chunkFilter
],
warningsFilter: [Function: warningsFilter
],
extractComments: false,
sourceMap: true,
cache: true,
cacheKeys: [Function: cacheKeys
],
parallel: true,
include: undefined,
exclude: undefined,
minify: undefined,
terserOptions: { output: { comments: /^\**!|@preserve|@license|@cc_on/i
},
mangle: false,
keep_fnames: true
}
}
}
]
},
performance: { hints: false
},
node: { fs: 'empty'
}
}
@gsaada I see a conflict:
{ test:
/\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
loader:
'/mnt/c/Users/saada/Development/novos-client-ow-app/app/node_modules/file-loader/dist/cjs.js',
query: { name: 'static/media/[name
].[hash: 8
].[ext
]'
}
},
I had a similar problem, the reason as shilman commented is because storybook by default in its webpack configuration is using file-loader for the svgs. So it founds a conflict with the vue-svg-loader.
What I did in my case and it works is to remove from the regex the svg extension and then as you did push the new rule of svg with the vue-svg-loader.
config.module.rules = config.module.rules.map(rule => {
{
if (String(rule.test) === String(/\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/)) {
return {
...rule,
test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
};
}
return rule;
}
});
Thank you @devtoni !
Works!
Thanks @devtoni !
I was running into this trying to use svg-inline-loader
.
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!
Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!
@devtoni's workaround worked for me too, with one additional change.
As of Storybook v6.9.0
, I had to add pdf
to the test regex that was being replaced. The updated code that worked for me is:
config.module.rules = config.module.rules.map(rule => {
if (String(rule.test) === String(/\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/)) {
return {
...rule,
test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/,
};
}
return rule;
});
I'm having issues with this! Look at my webpack.config.js
const path = require("path");
module.exports = ({ config }) => {
config.module.rules = config.module.rules.map(rule => {
if (
String(rule.test) === String(/\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/)
) {
return {
...rule,
test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/
};
}
return rule;
});
config.module.rules.push({
test: /\.scss$/,
use: [
"vue-style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
data: `
@import '~bulma/sass/utilities/initial-variables';
@import "@/assets/sass/partials/_variables.scss";
@import '~bulma/sass/utilities/functions';
@import '~bulma/sass/utilities/derived-variables';
@import '~bulma/sass/utilities/mixins';
`
}
}
]
});
config.module.rules.push({
test: /\.(svg)(\?.*)?$/,
oneOf: [
{
resourceQuery: /inline/,
use: [
{
loader: "vue-svg-loader",
options: {
svgo: {
plugins: [
{ cleanupIDs: false },
{ removeComments: true },
{ removeDimensions: true },
{ removeViewBox: false }
]
}
}
}
]
},
{
loader: "file-loader",
options: {
name: "assets/imgs/[name].[hash:8].[ext]"
}
}
],
use: [
{
loader: "babel-loader"
}
]
});
config.resolve.alias = {
...config.resolve.alias,
"@": path.resolve(__dirname, "../src")
};
return config;
};
and when I serve storybook it doesn't print any error in console
but when I try to open in on browser:
Solved my issue with this configuration:
config.module.rules.push({
test: /\.(svg)(\?.*)?$/,
use: "babel-loader",
oneOf: [
{
resourceQuery: /inline/,
use: [
{
loader: "vue-svg-loader",
options: {
svgo: {
plugins: [
{ removeDoctype: true },
{ removeComments: true },
{ removeDimensions: true },
{ cleanupIDs: false },
{ removeViewBox: false }
]
}
}
}
]
},
{
loader: "file-loader",
options: {
name: "assets/imgs/[name].[hash:8].[ext]"
}
}
],
exclude: /(node_modules)/
});
Thanks @danthareja that worked
https://github.com/storybookjs/vue-cli-plugin-storybook/issues/69#issuecomment-668171815
This config solved the issue for me:
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; }
Original post: https://stackoverflow.com/questions/56971513/storybook-does-not-load-svgs-in-components-of-vue-project
Thanks @ecarrera that worked for me as well. Been struggling with this all day!
@ndelangen Does other frameworks have this same issue of svg not working?
Most helpful comment
@devtoni's workaround worked for me too, with one additional change.
As of Storybook
v6.9.0
, I had to addpdf
to the test regex that was being replaced. The updated code that worked for me is: