Laravel-mix: CSS Modules in Vue SFC no longer supported? (v4)

Created on 15 Jan 2019  路  7Comments  路  Source: JeffreyWay/laravel-mix

  • Laravel Mix Version: 4.0.14
  • Node Version: 8.11.4
  • NPM Version: 5.6.0
  • OS: MacOS Mojave (10.14.2)

Description:

After upgrading Laravel Mix from v2 to v4 it seems CSS Modules in Vue Single File Components is no longer supported (<style module>).

The migration Guide for vue-loader mentions that CSS modules now has to be explicitly configured in the css-loader.

I've got CSS modules to work with the following config addition:

mix.webpackConfig({
    module: {
        rules: [
            {
                test: /\.css$/,
                loaders: [
                    'style-loader',
                    { loader: 'css-loader', options: { importLoaders: 1, modules: true } },
                    {
                        loader: 'postcss-loader',
                        options: {},
                    },
                ],
            },
        ],
    },
});

However, all styles are now converted to CSS modules (doesn't matter if <style> or <style module>; some third-party components which just use normal CSS classes, no longer work correctly and break our project).

To fix this, the migration guide mentions, that I would have to add a oneOf-rule with a resourceQuery to my webpack config. However this doesn't seem to work with Laravel Mix (see "Build Error").

mix.webpackConfig({
    module: {
        rules: [
            {
                test: /\.css$/,
                oneOf: [
                    {
                        resourceQuery: /module/,
                        use: [
                            'vue-style-loader',
                            {
                                loader: 'css-loader',
                                options: {
                                    modules: true,
                                    localIdentName: '[local]_[hash:base64:5]'
                                }
                            }
                        ]
                    },
                    {
                        use: [
                            'style-loader',
                            { loader: 'css-loader', options: { importLoaders: 1, modules: false } },
                        ]
                    }
                ]
            }
        ]
    }
});


馃摑 Build Error


./laravel-mix-test/node_modules/webpack-cli/bin/cli.js:235
                throw err;
                ^

TypeError: Cannot read property 'find' of undefined
    at updateCssLoader.rule (./laravel-mix-test/node_modules/laravel-mix/src/components/Vue.js:43:26)
    at Vue.updateCssLoader (./laravel-mix-test/node_modules/laravel-mix/src/components/Vue.js:91:21)
    at Vue.updateCssLoaders (./laravel-mix-test/node_modules/laravel-mix/src/components/Vue.js:42:14)
    at Vue.webpackConfig (./laravel-mix-test/node_modules/laravel-mix/src/components/Vue.js:32:14)
    at JavaScript.webpackConfig (./laravel-mix-test/node_modules/laravel-mix/src/components/JavaScript.js:90:22)
    at Mix.listen.config (./laravel-mix-test/node_modules/laravel-mix/src/components/ComponentFactory.js:75:54)
    at events.(anonymous function).forEach.handler (./laravel-mix-test/node_modules/laravel-mix/src/Dispatcher.js:34:47)
    at Array.forEach ()
    at Dispatcher.fire (./laravel-mix-test/node_modules/laravel-mix/src/Dispatcher.js:34:28)
    at Mix.dispatch (./laravel-mix-test/node_modules/laravel-mix/src/Mix.js:119:25)
    at WebpackConfig.build (./laravel-mix-test/node_modules/laravel-mix/src/builder/WebpackConfig.js:28:13)
    at Object. (./laravel-mix-test/node_modules/laravel-mix/setup/webpack.config.js:29:38)
    at Module._compile (./laravel-mix-test/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (./laravel-mix-test/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
    at WEBPACK_OPTIONS (./laravel-mix-test/node_modules/webpack-cli/bin/convert-argv.js:115:13)
    at requireConfig (./laravel-mix-test/node_modules/webpack-cli/bin/convert-argv.js:117:6)
    at ./laravel-mix-test/node_modules/webpack-cli/bin/convert-argv.js:124:17
    at Array.forEach ()
    at module.exports (./laravel-mix-test/node_modules/webpack-cli/bin/convert-argv.js:122:15)
    at yargs.parse (./laravel-mix-test/node_modules/webpack-cli/bin/cli.js:232:39)
    at Object.parse (./laravel-mix-test/node_modules/yargs/yargs.js:567:18)
    at ./laravel-mix-test/node_modules/webpack-cli/bin/cli.js:210:8
    at Object. (./laravel-mix-test/node_modules/webpack-cli/bin/cli.js:500:3)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object. (./laravel-mix-test/node_modules/webpack/bin/webpack.js:155:2)

My main question here is:

  1. Was this intentional? (Probably not, otherwise I would have been mentioned in the Changelog)
  2. Can out-of-the-box support for CSS modules be added back to Laravel Mix?

I'm grateful for any feedback which could guide me to a working solution here 馃槄.

Steps To Reproduce:

I've created a repository with an example app here. Checkout the master branch and open dist/index.html in a browser to see a working example. Checkout the example-mix-4-branch and open dist/index.html to see a failing example.

  1. Add a Vue SFC (Example.vue).
<template>
    <div :class="$style.wrapper">
        <h1 :class="$style.heading">Lorem Ipsum</h1>
    </div>
</template>

<script>
export default {}
</script>

<style module>
    .wrapper {
        background: #ff5500;
    }

    .heading {
        font-family: sans-serif;
        text-align: center;
    }
</style>

  1. Create a new JavaScript build including Example.vue.
  2. Load Vue App in a Browser.
<div id="app">
    <example-component/>
</div>
<script src="app.js"></script>
  1. CSS rules will not be applied to HTML and will not be transformed by CSS modules.

Expected:

<style type="text/css">
.-ufM6DxE_95mQtnu5IFRP_0{
    background:#f50
}
._34zk31mJ7skKgVY0MlKzim_0{
    font-family: sans-serif;
    text-align: center
}
</style>

<div class="-ufM6DxE_95mQtnu5IFRP_0">
    <h1 class="_34zk31mJ7skKgVY0MlKzim_0">Lorem Ipsum</h1>
</div>

Result:

<style type="text/css">
.wrapper {
    background: #ff5500;
}
.heading {
    font-family: sans-serif;
    text-align: center;
}
</style>

<div>
    <h1>Lorem Ipsum</h1>
</div>

stale

Most helpful comment

@oroalej @DavidVaness @stefanzweifel

I have since run into this issue again, and it appears that even with my previous solution, some component styles would be converted into using css modules even if they don't. I have however solved this by extending laravel mix and I use something like this - https://gist.github.com/mirago/56c8f97f9728652b2d822a411c7aa40c

All 7 comments

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Hello @stefanzweifel, not sure if you have solved this, but I have just run into this issue. Looking at the vue loader docs here, we need to modify their example a little bit to work with laravel mix.

This is what works for me:

  .webpackConfig({
    module: {
      rules: [
        {
          test: /\.css$/,
          loaders: [
            {
              loader: 'css-loader',
              options: {
                modules: true,
                localIdentName: '[local]_[hash:base64:8]',
              },
            },
          ],
        },
      ],
    },
  });

@mirago I couldn't fix this yet.

Will give it a try with your code snippet. thanks!

@mirago Is the solution you provide also applicable for <style module lang="scss">?

@mirago Is the solution you provide also applicable for <style module lang="scss">?

I have the same issue and can confirm this solution works for css only. Still searching for a working suggestion to use:
<style module lang="scss">

@oroalej @DavidVaness @stefanzweifel

I have since run into this issue again, and it appears that even with my previous solution, some component styles would be converted into using css modules even if they don't. I have however solved this by extending laravel mix and I use something like this - https://gist.github.com/mirago/56c8f97f9728652b2d822a411c7aa40c

i got<style module lang="scss"> to work with scss in this way:

.webpackConfig({
    module: {
      rules: [
        {
          test: /\.scss$/,
          exclude: [
            '/path/resources/sass/app.scss',
          ],
          loaders: [
            {
              loader: 'css-loader',
              options: {
                modules: true,
                localIdentName: '[local]_[hash:base64:5]',
              },
            },
            {
              loader: 'sass-loader',
              options: {
                precision: 8,
                outputStyle: 'expanded',
              },
            },
          ],
        },
      ],
    },
  })

Your version looks cleaner though! thank you

Was this page helpful?
0 / 5 - 0 ratings