Stylesheets from node_modules cannot be imported without using the tilde (~) character

Struggling to develop a basic web app using material-components-vue alongside vue-cli and webpack, I encountered an issue with importing stylesheets from node_modules without prefixing them with ~.

After experimenting with various webpack/vue-cli configurations, I finally settled on configuring vue.config.js to pass loader options.

This is how my vue.config.js looks:

module.exports = {
    css: {
      loaderOptions: {
        sass: {
          includePaths: [
              './node_modules', //including node_modules path here
            ]
        },
      }
    }
  }

With this configuration in place, I expected to be able to import styles like so:

@import 'normalize/normalize'

(assuming there is a directory named normalize within my node_modules folder containing a file named normalize.scss)

However, webpack throws an error stating that it cannot locate the module.
Interestingly, this version works:

@import '~normalize/normalize'

The challenge arises when dealing with third-party modules that contain their own @import statements, resulting in webpack compilation failures.

EDIT 1:

In response to a query by @Styx:

Please share additional configurations

and

Show the output of vue inspect --rule scss, along with the entire file featuring this problematic import

Here is the content of my problematic file which is quite minimal:

<template>
  <div id="app">
    <m-button>Hello</m-button>
  </div>
</template>

<script>
import Vue from 'vue'
import Button from 'material-components-vue/dist/button'
Vue.use(Button)

export default {
  name: 'App',
  components: {
}
</script>

<style lang="scss">
@import "~material-components-vue/dist/button/styles"; //this works
@import "material-components-vue/dist/button/styles"; //but this does not
</style>

The result from vue inspect --rule scss can be viewed here

All other configurations are as per the defaults generated by vue init webpack <name>

EDIT 2: Step-by-step guide to reproduce this issue:

  1. Initialize a vue-webpack app:
vue init webpack .
  1. Choose Vue build: Runtime + Compiler (Default)
  2. Do not include Vue-router
  3. Select npm as the package manager
  4. Install sass-loader:

npm i -D sass-loader node-sass
  1. Create a file named vue.config.js and add the following code:
module.exports = {
    css: {
      loaderOptions: {
        sass: {
          includePaths: [
              './node_modules', //adding node_modules path here
            ]
        },
      }
    }
  }
  1. Next, install a module that includes scss/sass files (For instance, for material-components-web, run npm i material-components-web)

  2. Then, import a stylesheet from node_modules like so:

@import '@material/button/mdc-button'; //mdc-button is part of material-components-web
  1. Finally, launch the development server:
npm run dev
  1. An error will be thrown as follows:
 ERROR  Failed to compile with 1 errors                                                                        11:36:35 AM

 error  in ./src/App.vue

Module build failed: 
@import '@material/button/mdc-button';
^
      File to import not found or unreadable: @material/button/mdc-button.
      in /home/maxim/projects/holiday.js/stackoverflow/src/App.vue (line 18, column 1)

 @ ./node_modules/vue-style-loader!./node_modules/css-loader?{"sourceMap":true}!./node_modules/vue-loader/lib/style-compil
er?{"vue":true,"id":"data-v-7ba5bd90","scoped":false,"hasInlineConfig":false}!./node_modules/sass-loader/lib/loader.js?{"s
ourceMap":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/App.vue 4:14-359 13:3-17:5 14:22-367
 @ ./src/App.vue
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js

Note that in the initial example, I attempted to import

material-components-vue/dist/foo/styles
, while in this case, I imported @material/foo.

Answer №1

Your vue.config.js is not being used in this setup. Since you are using webpack-dev-server instead of @vue/cli-service, the sass-loader is missing the includePaths option.

To fix this, you can either create a new project using the modern vue create <app-name> command, or make changes to your existing project:

  1. Open the build/utils.js file.

  2. Look for the return ... statement inside the exports.cssLoaders function:

    return {
      ...
      sass: generateLoaders('sass', { indentedSyntax: true }),
      scss: generateLoaders('sass'),
      ...
    }
    
  3. Update it as follows:

    const includePaths = [path.resolve(__dirname, '..', 'node_modules')];
    return {
      ...
      sass: generateLoaders('sass', { indentedSyntax: true, includePaths }),
      scss: generateLoaders('sass', { includePaths }),
      ...
    }
    
  4. Delete the unused vue.config.js file.

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

Automatically integrating Nivo Lightbox into your website

I incorporated Nivo Lightbox into my website, seamlessly integrating all images with the plugin using the following code: <div class="portfolio-item"> <div class="portfolio-thumb "> <a class="lightbox" data-lightbox-type="ajax" title="Strat ...

Next.js is constantly fetching data with React Query

Within my Next.js project, I incorporated a query client into a page component, utilizing getServerSideProps for server-side rendering. The structure of the page is as follows: const Index = ({ configData }) => { const { t } = useTranslation(); cons ...

Display modal within a React list

I need to display a list of items with an edit button for each item, which should trigger a modal showing the details of that specific item. Initially, I had a single modal component in the parent element and passing the visible values to the parent state ...

Position an HTML canvas at the very top of the webpage

Can someone help me figure out how to align a canvas element to the very top (0, 0) of a webpage? I attempted using margin: 0; padding: 0px;, but it didn't work. There always seems to be some white space at the top that I can't eliminate. ...

What is the purpose of including a function in an AngularJS dependency array?

When it comes to injecting dependencies, the process involves the following steps: inject(["$scope", "$compile", function ($scope, $compile) { ... }]); The syntax used here may seem strange. Placing the function inside the array might appear counter-in ...

Enhanced Search and Replace Techniques in HTML using jQuery and JavaScript

Although I have some experience with jQuery and Javascript, I am by no means an expert. I have been struggling to find a way to achieve my goal using minimal resources. Maybe you can assist me: This is what I am trying to accomplish: I would like to use ...

Experiencing difficulties with updating populated inputs that are connected to fetched data as they are not reflecting changes when modified

I am currently facing challenges with handling text fields in my web application. I need to retrieve data from the database, populate it in the appropriate fields, allow users to edit the information, and save any changes made. However, I have encountered ...

Using Page.ResolveClientUrl in JavaScript or jQuery allows for easy resolution of client

I find myself in a predicament where I need to choose between using an HTML page instead of a .aspx page for performance reasons. Currently, I am using an aspx page solely because of the CSS and javascript file paths like: <script type="text/javascript ...

Error 404: This page seems to have gone missing. Django and react-router

Struggling to integrate reactjs and react-router (1.x) with my Django project. I'm finding it challenging to make everything work together seamlessly. For more details, you can check out the project on GitHub: https://github.com/liondancer/django-che ...

Establishing a connection between a Google spreadsheet to create and automatically update calendar events

I'm currently working on connecting my Google Sheet to a calendar so that it can automatically generate calendar events and keep them updated based on changes made in the sheet. The Google Sheet I'm using tracks new building opening dates and con ...

When activating a bootstrap class button, I must ensure the reply-box remains hidden

let replyButton = document.getElementById('reply-button'); let cardBody = document.getElementById('card-body'); let responseBox = document.getElementById('reply-box'); let cancelButton = document.getElementById('btn btn-d ...

Utilizing jQuery time intervals within a jQuery click event: A step-by-step guide

For my dropdown menu project, I am facing an issue where the menu bar is not reappearing after collapsing the dropdown. It seems that the jQuery function responsible for toggling classes within a time interval is not executing properly. Specifically, the " ...

What is the best way to upload an image, pass it to my controller for validation, and finally store it in my database?

I am currently working on a project using Laravel 5.4 and Vue.js. I have a file named AddProduct.vue which contains a form. Everything in the form is working fine except for uploading an image. Can someone guide me on what onchange method I should use to u ...

Strategies for aligning tooltips with the locations of dragged elements

One of my projects involves a simple drag element example inspired by Angular documentation. The example features a button that can be dragged around within a container and comes with a tooltip. <div class="example-boundary"> <div ...

Is it possible to attach the entered URL to an image following the text that has been inputted?

I've coded everything but the jquery part isn't working. Enter URL :<input type="text"> <button id="btn"> continue </button> <div contenteditable="true" id="bod"> Click here to start typing</div> $(document).ready( ...

The tablesorter plugin from Jquery isn't functioning properly on my dynamically loaded ajax table

I am having trouble getting Tablesorter to work with my table. I attempted to use .trigger('update') but it did not have the desired effect for me. Instead, I tried using stupidtable and it worked to some extent, but not perfectly (it did not sor ...

The Model.function method is not a valid function that can be used within a router

Currently facing a challenge with my router setup. I have exported the function as shown in the code snippet below. This is the Model I am using: "use strict"; var mongoose = require('mongoose'); var bcrypt = require("bcryptjs"); var Schema = m ...

Tips on Calculating the Number of Object Properties and Presenting Each Value Individually on a Dynamic Button with Click Event Attached

When it comes to displaying dynamic data with markers on a map, everything works fine up until this point. However, I've encountered some issues that I'm currently stuck on and not sure how to proceed. Dynamic data: { "page": 2, "data" ...

Discover the process of making a unique custom function in Vue JS akin to the created() hook!

What is the best way to develop a plugin that introduces a function called structure, similar to the created() hook, to all components? In addition, I want my plugin to be able to access the return value of structure. export default { structure() { ...

When utilizing jQuery to add a <li> element, it suddenly vanishes

? http://jsfiddle.net/AGinther/Ysq4a/ I'm encountering an issue where, upon submitting input, a list item should be created with the content from the text field. Strangely, it briefly appears on my website but not on the fiddle, and no text is appen ...