Vue-cli: VUE CLI with webpack 4 does not support chainWebpack properly

Created on 16 May 2018  路  10Comments  路  Source: vuejs/vue-cli

Version

3.0.0-beta.10

Reproduction link

https://github.com/LanFeusT23/vue-cli-webpack-issue

Steps to reproduce

vue create project
Add a vue.config.js file and tap into some loader options

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('scss')
      .use('sass-loader')
      .tap(options =>
        merge(options, {
          includePaths: [path.resolve(__dirname, 'node_modules')],
        })
      )
  }
}

npm run serve

It will throw an error when trying to tap into the loader options

What is expected?

The options should be a an object with many more properties.

What is actually happening?

the options object only has the following properties:
{ compilerOpitons: { preserveWhitespace: false } }

options.loaders.scss throws an exception because options doesn't have any other properties added.


This worked fine until webpack 4 was released.

Most helpful comment

@yyx990803 , thanks a lot for your answer.
While exploring various cli starter kits, I've encountered multiple challenges with the use of sass libraries.
I wonder if there any reason why loading SASS and LESS dependencies from node_modules is not a default behavior?

As my primary scenario with those is to stand on shoulders of giants (sass libraries and frameworks),
it looks like people optimize starter kits for other scenarios.

Is such default evil in some way?

BTW, for those who seek copy-paste solution:

//vue.config.js
const path = require('path')

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        includePaths: [path.resolve(__dirname, 'node_modules')]
      }
    }
  }
}

All 10 comments

The internal config has changed in beta.10. Use css.loaderOptions instead of tapping the loaders directly.

I'm sorry I'm not sure I follow, where is that css.loaderOptions? Could the docs be updated?

https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md

That seems to be used to pass options to CSS pre-processors, in my case sass-loader for .scss files.

I don't need to update the sass-loader, I want to add "sass-resources-loader" to the vue-loader. The css.loaderOptions doesn't allow me to update the vue loader.

Your reproduce steps was just mutating the sass-loader options. To add a new loader it would be a bit more complicated to explain because the new CSS rules are a bit different after beta.10, so I'd suggest wait for beta.11 which comes with the better vue inspect that outputs hints for tapping internal config.

I just noticed my mistake in the reproduce steps, my apologies

It was meant to be:

chainWebpack: config => {
    config.module
    .rule('vue')
    .use('vue-loader')
    .tap(options => {
        console.log(options);

        var scssResourceLoader = {
            loader: 'sass-resources-loader',
            options: {
                resources: [
                    path.resolve(__dirname, 'src/styles/_colors.scss')
                ]
            }
        };
        options.loaders.scss.push(scssResourceLoader);
        return options;
    });
}

cli-service beta.9 had a requirement on webpack 3.10.0 whereas beta.10 requires webpack 4.

Webpack seems to be what broke, they even have a typo too 'compilerOpitons'. Hopefully it gets resolved soon, being able to use scss variables inside .vue files is essential.

Thanks

There is a vue-loader breaking upgrade as well. See https://vue-loader.vuejs.org/migrating.html

@yyx990803 , thanks a lot for your answer.
While exploring various cli starter kits, I've encountered multiple challenges with the use of sass libraries.
I wonder if there any reason why loading SASS and LESS dependencies from node_modules is not a default behavior?

As my primary scenario with those is to stand on shoulders of giants (sass libraries and frameworks),
it looks like people optimize starter kits for other scenarios.

Is such default evil in some way?

BTW, for those who seek copy-paste solution:

//vue.config.js
const path = require('path')

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        includePaths: [path.resolve(__dirname, 'node_modules')]
      }
    }
  }
}

@andriytyurnikov I'm not sure what your specific problem is. sass-loader by default should be using webpack's resolver for imports and should not need the change you mentioned.

@yyx990803 , well I guess it is related to the fact that libraries themselves do not follow webpack-specific resolver conventions and have own dependencies:

@import "~vue-mdc-adapter/dist/styles"; //tilda prefix for webpack

@import "vue-mdc-adapter/dist/styles"; //usual style in libraries

I would suggest that this is quite common scenario.
Just now I've reproduced the case:
importing with webpack's prefix (without extra config)
@import "~vue-mdc-adapter/dist/styles";
failed on dependency of the library

Module build failed: 
@import "@material/button/mdc-button";
^
      File to import not found or unreadable: @material/button/mdc-button.

As libraries do not follow webpack conventions (webpack author's idea that everyone would use webpack resolver instead of everything else was quite optimistic)

Was this page helpful?
0 / 5 - 0 ratings