Webpacker: Webpacker SASS/SCSS loader conflicts with libs that use dart sass like vuetify

Created on 15 Aug 2019  ยท  27Comments  ยท  Source: rails/webpacker

How do I remove the default sass/scss-loader if it exists ? it conflicts with my own config . see : https://github.com/vuejs/vue-loader/issues/1580

Can I use .delete(key) ?

style loaders

Most helpful comment

@davidfabreguette :
1) install the sass, the vuetify and the vuetify-loader packages.
2) you should have a config directory in the root of your project to configure webpacker which includes some files , like:

config/webpack
โ”œโ”€โ”€ development.js
โ”œโ”€โ”€ environment.js
โ”œโ”€โ”€ production.js
โ””โ”€โ”€ test.js

Then, in environment.js , something like :

const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { config } = require('@rails/webpacker')

// We need to remove the webpacker preconfigured CSS loader as it conflicts with our own SASS config
environment.loaders.delete('css')

environment.loaders.append('i18n-yml', {
  test: /i18n\/\S+\.yml$/i,
  use: [
    'json-loader',
    'yaml-loader'
  ]
})

environment.loaders.append('vue', {
  test: /\.vue(\.erb)?$/,
  use: [{
    loader: 'vue-loader',
    options: {
      preLoaders: {
        i18n: 'yaml-loader'
      },
      loaders: {
        i18n: '@kazupon/vue-i18n-loader'
      }
    }
  }]
})

environment.loaders.append('sass', {
  test: /\.sass$/,
  use: [
    config.extract_css === false
      ? 'vue-style-loader'
      : MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        sourceMap: true,
        importLoaders: 2
      }
    },
    {
      loader: 'sass-loader',
      options: {
        sourceMap: true,
        implementation: require('sass'),
        fiber: require('fibers'),
        data: `@import "app/javascript/manager/styles/main.scss"`,
        indentedSyntax: true
      }
    }
  ]
})

environment.loaders.append('scss', {
  test: /\.scss$/,
  use: [
    config.extract_css === false
      ? 'vue-style-loader'
      : MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        sourceMap: true,
        importLoaders: 2
      }
    },
    {
      loader: 'postcss-loader',
      options: {
        sourceMap: true
      }
    },
    {
      loader: 'sass-loader',
      options: {
        sourceMap: true,
        implementation: require('sass'),
        fiber: require('fibers'),
        data: `@import "app/javascript/manager/styles/main.scss";`
      }
    }
  ]
})

environment.plugins.append('MiniCssExtractPlugin', new MiniCssExtractPlugin({
  filename: 'css/[name]-[contenthash:8].css',
  chunkFilename: 'css/[name]-[contenthash:8].chunk.css'
}))
environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin())
environment.plugins.prepend('VuetifyLoaderPlugin', new VuetifyLoaderPlugin())

module.exports = environment

This should be enough to make Vuetify work ( a - la - carte setup ) .
by the way "main.scss" should include only variable definitions and overrides for Vuetify. For other global styles use app.scss or some other wrapper component.

All 27 comments

Seems that I can remove them with

environment.loaders.delete('sass')
environment.loaders.delete('moduleSass')
environment.loaders.delete('moduleCss')
environment.loaders.delete('css')

especially 'css' was causing the compilation issue.

In order to help debug, could you please post as much as you can of:

  • ./package.json
  • ./config/webpack/environment.js
  • ./config/webpacker.yml
  • ./app/javascript/packs/application.js
  • ./app/javascript/manager/components/gateway/form.sass
  • The code where you import VNavigationDrawer.sass
  • the full error message (even the parts you wouldnโ€™t think is relevant)

@jakeniemiec My issue was solved by deleting the loader for 'css'. That's all. I don't understand why webpacker includes a plain css loader but for vue applications using vue-style-loader (new version 15+) a plain css loader conflicts with the sass loader.

Depending on what vuetify release you have, it may not be compatible with webpacker: https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0

I don't understand why webpacker includes a plain css loader but for vue applications using vue-style-loader

It just looks like vuetify and webpacker are just trying to occupy the same conflicting roles (style compiling).

I think it's not a vuetify issue but a vue-loader issue. I commented out vuetify, used the configuration proposed by Vue-loader (which is core) and the compiling didn't work.

I think you should definitely mention this for Vue applications. Also the api of the webpacker config..
I had to dig through the source code to find the 'delete' method. Wasn't able to find this in the documentation..

I think it's not a vuetify issue

It requires the Dart version of the scss compiler. The error you posted is what you get when you have the node version (required by webpacker): https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0

I think you should definitely mention this for Vue applications. Also the api of the webpacker config..I had to dig through the source code to find the 'delete' method. Wasn't able to find this in the documentation.

Wholeheartedly agree.

Ah yes, that is true. The guys at vuetify mentioned it. Do you see a clearer way to solve this dependency conflict without deleting the css loader of webpacker? Or that's the cleanest solution?

A lot of devs (including myself) drop/customize webpacker when the stack gets too complex. In this case, vuetify says "Do not install node-sass", however, this is unavoidable since it is baked into webpacker.

I can't really give a more complete answer since I am nowhere close to an expert on Vue.

Is it possible to drop webpacker completely with a rails app?

I am going thought the same issue.

Use my code above and add it to your environment.js file
https://github.com/rails/webpacker/issues/2235#issuecomment-521694209

Keep having the same trouble... :(

I added the required dependencies from vuetify guide (https://vuetifyjs.com/en/customization/a-la-carte).
yarn add sass sass-loader fibers deepmerge -D

setup vuetify-loader at environment.js using this:

const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin') environment.plugins.prepend('VuetifyLoaderPlugin', new VuetifyLoaderPlugin())

environment.loaders.delete('sass')
environment.loaders.delete('moduleSass')
environment.loaders.delete('moduleCss')
environment.loaders.delete('css')

environment.loaders.append('scss', {
test: /.scss$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
// data: @import "app/javascript/src/styles/main.scss";
}
}
]
})

environment.loaders.append('sass', {
test: /.sass$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
indentedSyntax: true
}
}
]
})

i didn't included stylesheet_pack_tag in my layout. but even when I add it run to the same problem.

Is it possible to drop webpacker completely with a rails app?

@gkatsanos @p1Machado Some issues talk about this like https://github.com/rails/webpacker/pull/1916

Ideally, you would keep most of webpackER as-is, but be able to load a static vanilla webpack config without needing to worry about configuring webpacker.

Right now I managed to stop the warnings about sass. I guess it worked, but couldn`t check it out yet,
I trying to use vue components globally registred in my rails views and keep getting unregistered errors. I bet that a la carte config from Vuetify might not be recognizing that I used the component...

still trying...

Edit:
I had to register the component myself in order for it to work...

I will use manual imports by now.

Thank you @gkatsanos .
I am still interested in discuss a enhancement for this setup if you want.

@jakeNiemiec My issue was solved by deleting the loader for 'css'. That's all. I don't understand why webpacker includes a plain css loader but for vue applications using vue-style-loader (new version 15+) a plain css loader conflicts with the sass loader.

Hi @jakeNiemiec, did you manage to make dart sass work with rails webpacker ? I'm trying to configure webpacker with vuetify sass variables. I'm stuck with :

@import '../../styles/styles.sass'
       ^
      Can't find stylesheet to import.
  โ•ท
1 โ”‚ @import "~@/sass/main.scss"

It seems like sass doesn't find path to vuetify sass file imports.

Here's my /sass/main.scss :

@import '~vuetify/src/styles/styles.sass';

following Vuetify setup https://vuetifyjs.com/en/customization/sass-variables#setup

Any chance you got same problem with third party sass modules ?

@davidfabreguette : did you include a data option to your SASS/SCSS webpack loader for this?
by the way the ../../ relative paths can be problematic, make sure your path is correct.

@gkatsanos - Any chance you could share your final setup you got this to work with? I'm trying similar approaches you outlined, but haven't been able to get it to work yet.

Hi @jakeNiemiec, did you manage to make dart sass work with rails webpacker?

I am not sure how webpacker should handle this. It seems that you can have one or the other but not both. This is the problem that peerDependencies was supposed to solve in the JS ecosystem. Webpacker shouldn't care which SCSS lib you want to use.

In the end, it pushes me to work more on better support for overriding the default config. I want to keep this issue open since the problem will be ongoing.

@rstawarz what exactly are you trying to achieve and where are you blocked? As I wrote above the best thing to do if you're trying to setup webpacker with a Vue application is to delete the built-in loaders and write your own, using environment.loaders.delete('css') . To get more insight, navigate in the source of Webpacker (its in node_modules) and check their loaders section.

@davidfabreguette :
1) install the sass, the vuetify and the vuetify-loader packages.
2) you should have a config directory in the root of your project to configure webpacker which includes some files , like:

config/webpack
โ”œโ”€โ”€ development.js
โ”œโ”€โ”€ environment.js
โ”œโ”€โ”€ production.js
โ””โ”€โ”€ test.js

Then, in environment.js , something like :

const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { config } = require('@rails/webpacker')

// We need to remove the webpacker preconfigured CSS loader as it conflicts with our own SASS config
environment.loaders.delete('css')

environment.loaders.append('i18n-yml', {
  test: /i18n\/\S+\.yml$/i,
  use: [
    'json-loader',
    'yaml-loader'
  ]
})

environment.loaders.append('vue', {
  test: /\.vue(\.erb)?$/,
  use: [{
    loader: 'vue-loader',
    options: {
      preLoaders: {
        i18n: 'yaml-loader'
      },
      loaders: {
        i18n: '@kazupon/vue-i18n-loader'
      }
    }
  }]
})

environment.loaders.append('sass', {
  test: /\.sass$/,
  use: [
    config.extract_css === false
      ? 'vue-style-loader'
      : MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        sourceMap: true,
        importLoaders: 2
      }
    },
    {
      loader: 'sass-loader',
      options: {
        sourceMap: true,
        implementation: require('sass'),
        fiber: require('fibers'),
        data: `@import "app/javascript/manager/styles/main.scss"`,
        indentedSyntax: true
      }
    }
  ]
})

environment.loaders.append('scss', {
  test: /\.scss$/,
  use: [
    config.extract_css === false
      ? 'vue-style-loader'
      : MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        sourceMap: true,
        importLoaders: 2
      }
    },
    {
      loader: 'postcss-loader',
      options: {
        sourceMap: true
      }
    },
    {
      loader: 'sass-loader',
      options: {
        sourceMap: true,
        implementation: require('sass'),
        fiber: require('fibers'),
        data: `@import "app/javascript/manager/styles/main.scss";`
      }
    }
  ]
})

environment.plugins.append('MiniCssExtractPlugin', new MiniCssExtractPlugin({
  filename: 'css/[name]-[contenthash:8].css',
  chunkFilename: 'css/[name]-[contenthash:8].chunk.css'
}))
environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin())
environment.plugins.prepend('VuetifyLoaderPlugin', new VuetifyLoaderPlugin())

module.exports = environment

This should be enough to make Vuetify work ( a - la - carte setup ) .
by the way "main.scss" should include only variable definitions and overrides for Vuetify. For other global styles use app.scss or some other wrapper component.

Thanks @gkatsanos for the tip, I'll give it a try and get back ! (sorry I missed your answer !)

For those using sass-loader@^8.0.0 change:
From

{
      loader: 'sass-loader',
      options: {
        sourceMap: true,
        implementation: require('sass'),
        fiber: require('fibers'),
        data: `@import "app/javascript/manager/styles/main.scss"`,
        indentedSyntax: true
      }
}

To

{
      loader: "sass-loader",
      options: {
        sourceMap: true,
        implementation: require("sass"),
        sassOptions: {
          fiber: require("fibers"),
          data: `@import "app/javascript/manager/styles/main.scss"`,
          indentedSyntax: true
        }
      }
}

The solution described in this article worked for me to replace node-sass with dart-sass:

// Get the actual sass-loader config
const sassLoader = environment.loaders.get('sass')
const sassLoaderConfig = sassLoader.use.find(function(element) {
  return element.loader == 'sass-loader'
})

// Use Dart-implementation of Sass (default is node-sass)
const options = sassLoaderConfig.options
options.implementation = require('sass')

Anyone knows how to achieve this in a project without webpacker ? I dont have environment.js
this is my setup https://stackoverflow.com/questions/64143692/vuetify-without-vue-cli-sass-scss-conflict

Was this page helpful?
0 / 5 - 0 ratings

Related issues

itay-grudev picture itay-grudev  ยท  3Comments

amandapouget picture amandapouget  ยท  3Comments

eriknygren picture eriknygren  ยท  3Comments

suhomlineugene picture suhomlineugene  ยท  3Comments

suhomozgy-andrey picture suhomozgy-andrey  ยท  3Comments