Cannot import stylesheets from node_modules withou

2019-07-11 02:57发布

I'm trying to create a simple web app with material-components-vue and vue-cli with webpack, however, I found out that I cannot import stylesheets from node_modules without a preceding ~.

I have tried several webpack/vue-cli configs, and ended up with a config in vue.config.js passing loader options.

My vue.config.js looks like this:

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

So I expect to be able to import stuff like so:

@import 'normalize/normalize'

(assuming I have a directory called normalize in my node_modules which contains a file normalize.scss)

However, webpack throws an error, saying it cannot find the module.
But, this does work:

@import '~normalize/normalize'

This wouldn't be a problem if all @imports were written by me, but because I use a third-party module which has @imports inside them, webpack fails to compile.

EDIT 1:

As @Styx asked to

Share more configs, please

and

show the output of vue inspect --rule scss, and the whole file with this problematic import

Here it is:

My problematic file is pretty empty:

<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>

My output from vue inspect --rule scss is located here

All other configs are as generated by vue init webpack <name>

EDIT 2: Exact steps to reproduce this issue:

  1. Initialize a vue-webpack app:
vue init webpack .
  1. Vue build: Runtime + Compiler (Default)
  2. Vue-router: no
  3. Package manager: npm

  4. Then, install sass-loader

npm i -D sass-loader node-sass
  1. Create a file vue.config.js and populate it with the following:
module.exports = {
    css: {
      loaderOptions: {
        sass: {
          includePaths: [
              './node_modules', //here I include node_modules
            ]
        },
      }
    }
  }
  1. After that, install a module containing scss/sass (E.g. for material-components-web, npm i material-components-web)

  2. Then, create an import to a stylesheet located in node_modules, like so:

@import '@material/button/mdc-button'; //mdc-button comes with material-components-web
  1. Finally, start the dev server:
npm run dev
  1. It will throw the following error:
 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

By the way, in the first example I wanted to import material-components-vue/dist/foo/styles, but here I import @material/foo.

1条回答
劳资没心,怎么记你
2楼-- · 2019-07-11 03:30

In this configuration your vue.config.js is ignored. This file is used by @vue/cli-service, but you're using webpack-dev-server instead. Thus, your sass-loader doesn't receive this includePaths option.

You can either use modern vue create <app-name> command, or if you want to modify existing project:

  1. Open build/utils.js file.

  2. Find return ... in exports.cssLoaders function:

    return {
      ...
      sass: generateLoaders('sass', { indentedSyntax: true }),
      scss: generateLoaders('sass'),
      ...
    }
    
  3. Modify it like this:

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

查看更多
登录 后发表回答