Using the incorrect file path in Vue Storybook

Recently, I began experimenting with Vue and encountered an issue related to using aliases for importing files in Storybook:

In my project, there is a SvgIcon component:

<template>
    <div>
        props from the icon: {{this.$props}}
        <svg v-if="icon" class="svg-icon">
            <title v-if="title">{{ title }}</title>
            <use v-bind="{ 'xmlns:xlink':'http://www.w3.org/1999/xlink', 'xlink:href': icon }"></use>
        </svg>
        <img v-else-if="image" :src="image" class="image-icon"/>
    </div>
</template>

<script>
export default {
    name: 'SvgIcon',
    data: function() {
        return {
            icon: null,
            image: null
        }
    },
    props: {
        title: {
            type: String,
            default: ''
        },
        iconFallback: {
            type: String,
            required: false
        },
        iconId: {
            type: String,
            required: true,
            validator(iconName) {
                if (!iconName) {
                    console.warn('icon can not be empty')
                    return false
                }
                return true
            }
        }
    },
    watch: {
        iconId: {
            immediate: true,
            handler(iconId) {
                iconId && import(`@/assets/icons/${iconId}.svg`)
                    .then(svg => {
                        // debugger
                        console.log(this, 'this from SvgIcon')
                        if (Object.prototype.hasOwnProperty.call(svg, 'default')) {
                            this.icon = svg.default
                        } else {
                            this.icon = svg
                        }
                    }).catch(() => {
                        this.image = this.iconFallback && require(`@/assets/icons/${this.iconFallback}.png`)
                    })
            }
        }
    }
}
</script>

<style scoped lang="scss">

svg {
    width: 32px;
    height: 32px;
    vertical-align: middle;

    &.icon-status {
        width: 14px;
        height: 14px;
        min-width: 14px;
        transform: translateY(-6%);
        fill: $light-orange;
    }

    &.icon-size-small {
        width: 14px;
        height: 14px;
    }

    &.icon-size-medium {
        width: 18px;
        height: 18px;
    }

    @include only_mini {
        @include skip_element;
    }
}

</style>

The component imports another file using the @ alias:

import(`@/assets/icons/${iconId}.svg`)

This setup works well on localhost:3000, but when running Storybook on port 6006, it throws the following error:

ERROR in ./src/js/globalComponents/SvgIcon.vue?vue&type=script&lang=js& (./node_modules/babel-loader/lib??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/js/globalComponents/SvgIcon.vue?vue&type=script&lang=js&)
Module not found: Error: Can't resolve '@/assets/icons' in 'src/js/globalComponents'
ERROR in ./src/js/globalComponents/SvgIcon.vue?vue&type=script&lang=js& (./node_modules/babel-loader/lib??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/js/globalComponents/SvgIcon.vue?vue&type=script&lang=js&)
Module not found: Error: Can't resolve '@/assets/icons' in 'src/js/globalComponents'

The alias is defined in vue.config.js at the root of the project:

configureWebpack: {
    resolve: {
        alias: require('./aliases.config').webpack
    },
...
}

This configuration references the file ./aliases.config:

const path = require('path')
function resolveSrc(_path) {
    return path.join(__dirname, _path)
}
const aliases = {
    '@': 'src',
    '@src': 'src'
}
module.exports = {
    webpack: {},
    jest: {}
}
for (const alias in aliases) {
    module.exports.webpack[alias] = resolveSrc(aliases[alias])
    module.exports.jest['^' + alias + '/(.*)$'] =
    '<rootDir>/' + aliases[alias] + '/$1'
}

Additionally, here's the Storybook configuration in .storybook/main.js:

const path = require('path');

module.exports = {
  stories: ['../stories/**/*.stories.js'],
  addons: ['@storybook/addon-actions', '@storybook/addon-links'],
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 
        {
          loader: 'sass-loader',
          options: {
            prependData: `@import "src/project/test/vars.scss"; @import "src/project/common/mixins.scss"; @import "src/styles/styles.scss";`
          }
        }
      ],
      resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js',
          '@': path.dirname(path.resolve(__dirname, "../src")),
        },
      },
      include: path.resolve(__dirname, '../'),
    });

    return config;
  },
};

If anyone can identify where I may be going wrong, your insights would be greatly appreciated.

Answer №1

Encountered a similar issue during the upgrade to Storybook version 5.3.19. I managed to resolve the import errors by simply using

'@': path.resolve(__dirname, '../src'),

No requirement for nesting using path.dirname(), in my opinion.

Below is the updated configuration within .storybook/main.js for Storybook:

module.exports = {
  stories: ['../stories/**/*.stories.js'],
  addons: ['@storybook/addon-actions', '@storybook/addon-links'],

  webpackFinal: async (config, { configType }) => {
    // `configType` can be 'DEVELOPMENT' or 'PRODUCTION'
    // Configuration adjustments can be made based on this value.
    // 'PRODUCTION' used for building static storybook versions.

    // Incorporate Sass loader for Vuetify components
    config.module.rules.push({
      test: /\.s(a|c)ss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
      include: path.resolve(__dirname, '../'),
    });

    config.module.rules.push({
      resolve: {
        alias: {
          '@': path.resolve(__dirname, '../src'),
          vue: 'vue/dist/vue.js',
          'vue$': 'vue/dist/vue.esm.js',  
        },
      },
    });

    return config;
  },
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the process of setting up Jasmine tests for both services and controllers in Angular.js

I have been facing challenges in creating accurate tests for my Angular services and controllers, even though they are functioning correctly. I have searched extensively for a solution to this problem. Below is an example of my controller: angular.module ...

Guide to creating varying component sizes using ReactJS and Styled Components

Is it possible to add variation to my button based on the prop 'size' being set to either 'small' or 'medium'? interface Props { size?: 'medium' | 'small'; } How can I adjust the size of the component us ...

Iterating over the IDs of div elements using jQuery loop

Currently, I am working with a bootstrap accordion and attempting to retrieve the ID and HREF values for each individual accordion using jQuery. Here is the code snippet that I have been utilizing: $('.room-loop').each(function(id){ $('. ...

Dynamic menu item created using Material UI state management

I am facing a challenge in displaying different menu items based on the gender state. Below are the constant values I am working with. const maleArray = ["A", "B", "C", "D"] const femaleArray = ["E", " ...

"Execute asynchronous tasks in Javascript and receive the returned

Currently, I am utilizing JSF ajax within my application and unfortunately, we are unable to make any changes to that. In the process of waiting for user action, I find it necessary to prompt the user before executing the ajax method. Specifically, I need ...

A shortcut for calling functions in Lodash

Looking to execute a series of functions using Lodash? Here's an example: const functions = [ () => console.log('Fn 1'), () => console.log('Fn 2') ]; _(functions).each(fn => fn()); Wondering if there is a Lodash ...

Bringing Vue Components Together in Laravel: A Guide to Component Importation

Recently, I started learning Vue.js and I am looking to understand how to use component. Unfortunately, when I attempted to import my component into another component, it didn't work as expected. The framework I am currently using is Laravel 5.8 and I ...

Angular Controller is not able to retrieve the Route Parameter, resulting in a 404

Currently working on my very first web app using Node.js and AngularJs. I've encountered a roadblock with the following code: var app = angular.module('Martin', ['ngResource','ngRoute']); app.config(['$routeProvide ...

Is there a way to confirm that the content of two files is identical?

Currently, I am utilizing mocha/supertest/should.js for testing a REST Service. When I make a request to GET /files/<hash>, it returns the file as a stream. I am seeking guidance on how to use should.js to assert that the contents of the file are i ...

Problems arising from the implementation of CSS modules in React applications

As a beginner in React, I recently started learning how to utilize CSS modules within my React projects. However, I encountered an error that read: Failed to compile. ./src/components/Header/Header.js Module not found: Can't resolve './Header.mo ...

Removing an item from JSON data using Node.js and Express

Currently, I am attempting to remove an entry from json data. In order to view the data, I utilize the following: app.route('/data/:id') .get((req:Request, res: Response) => { let id = req.params.id; res.status(200).send(projects ...

How to extract part of a string delimited by certain characters within GET parameters?

I have a requirement to modify an iframe src attribute generated dynamically by a BrightCove video player. Specifically, I need to eliminate certain GET parameters such as width and height, so that the width and height of the parent element take precedence ...

Tips on retrieving an array in a different page post ajax transfer

I have an array named student. I am in need of passing this array to another PHP page using the POST method instead of GET, due to its potentially large size. Currently, I am attempting to open a new page called sheet.php and display the contents of the s ...

Angular 10 and Typescript: Variables assigned within the change event become undefined

In my code, I initialize an Algolia input and set an onchange event to it. This initialization takes place in a service. algolia_data; random_var; this.http.post<any>('APIENDPOINT', formData).subscribe(data => { instance = places({ ...

Increasing values are applied to the text field when it is clicked or focused on

I have a grid with 18 rows of text fields, each requiring a unique ID. The bottom row may need ID 1 while the top row could need ID 15, depending on user choices. It doesn't have to be aesthetically pleasing, function is what matters. I plan to use th ...

Is there a way to convert an array into a single comma-separated value using parameters?

Is there a way to parameterize an array as a single name-value pair that is comma separated? I have tried using jQuery $.param, but it creates a parameter for each value in the array instead of just one. Unfortunately, it seems that there is no option or s ...

AngularJS dropdown not reflecting changes when using ng-selected

While working with AngularJS, I have encountered an issue where the first child of the select element remains empty despite my efforts to populate it. Below is the HTML code snippet: <select id="connectTV" aria-label="How many Dish TVs" ng-model="conn ...

Creating an interactive graph in Asp.Net MVC using Razor syntax and jQuery AJAX

Currently, I am working on binding data to a graph using Razor. I am fetching the data through a jQuery ajax call and then planning to bind the resulting data to the graph. Is there a way to incorporate Razor code within the jQuery success function? Also, ...

utilizing various ajax functions

I'm having trouble using additional functions with the "complete:" option in JQuery ajax after the "selectOptionSort" function. Can anyone help me figure out what's wrong? $('#tipos').change(function(){ $("#marcas ...

Achieving a reset for a form is essential for ensuring its

After creating a contact form, I encountered an issue where if a field is left empty or an invalid email address is entered, the form stops sending. Even after attempting to resend the information, the form remains unresponsive. Any suggestions on how to r ...