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)
I'm grateful for any feedback which could guide me to a working solution here 馃槄.
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.
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>
Example.vue.<div id="app">
<example-component/>
</div>
<script src="app.js"></script>
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>
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
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