Reputation: 61
I would like to use scss in my component file (Home.vue) and in a separate file (style.scss) at the same time. Webpack generate default.css from style.scss - I use MiniCssExtractPlugin and vue-style-loader.
I prepare webpack.config.js but it seems incorrect becouce when I change <style lang="scss" scoped>
to <style lang="css" scoped>
everything works fine otherwise it doesn't. <style lang="scss" scoped>
do nothing - no error, no effects.
How to change webpack.config.js to works MiniCssExtractPlugin and vue-style-loader at the same time?
webpack.config.js
var path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const isDevelopment = process.env.NODE_ENV
console.log("Dev status: " + (isDevelopment == 'development' ? 'Development' : 'Production'), isDevelopment);
module.exports = {
mode: isDevelopment,
entry: {
'vwp': ['./src/vue/welcome.js'],
'default': './src/scss/style.scss'
},
output: {
path: path.resolve(process.cwd(), 'public/assets/js'),
filename: '[name].js'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
)
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new CleanWebpackPlugin({
dangerouslyAllowCleanPatternsOutsideProject: true,
cleanOnceBeforeBuildPatterns: ['../css/*', '../js/*'],
cleanAfterEveryBuildPatterns: ['defautl.js'],
dry: false
}),
new MiniCssExtractPlugin({
filename: isDevelopment == 'development' ? '../css/[name].css' : '../css/[name].[hash].css',
chunkFilename: isDevelopment == 'development' ? '../css/[id].css' : '../css/[id].[hash].css'
}),
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['defautl.js']
}),
]
}
welcome.js
import Vue from 'vue'
import Home from './Home.vue'
Vue.config.productionTip = false
new Vue({
el: '#vwp',
components: { Home },
template: '<Home />'
})
Vue.config.devtools = true
Home.vue
<template>
<div>hello text</div>
</template>
<script>
export default {
name: "Home"
};
</script>
<style lang="scss" scoped>
* {
color: lime;
}
</style>
Upvotes: 6
Views: 4815
Reputation: 61
The problem is that WebPack refuses to work if there is a regular expression match in the rules. I think it somehow marks the processed files. This is true at least for this situation.
But WebPack is a very powerful tool. Instead of a regular expression in the rule parameter, it can take a function with two parameters (filename and entry).
After that, I determined that vue-loader splits the component file into three files:
<component name>.vue.js
<component name>.vue
and finally<component name>.vue.css
(or .scss
)Note: The SASS extension depends on the lang parameter of the style tag.
Next, it was necessary to separate these two cases with logic in the function. My implementation is seen in the example.
rules: [
{
test: function(filename, entry){
if(/\.s[ac]ss$/.test(filename)){
if(/\.vue\.s[ac]ss$/.test(filename)){
return false;
}
return true;
}
return false;
},
use: [
{
loader: MiniCssExtractPlugin.loader,
options:{
}
}, 'css-loader', 'sass-loader']
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
}
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: (filename, entry) => {
return /\.vue\.s[ac]ss/.test(filename);
},
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
]
Upvotes: 4
Reputation: 130
No need for a testing function. You can use a negative lookbehind (?<!...)
in your RegEx:
rules: [
// SASS and CSS files from Vue Single File Components:
{
test: /\.vue\.(s?[ac]ss)$/,
use: ['vue-style-loader', 'css-loader', 'sass-loader']
},
// SASS and CSS files (standalone):
{
test: /(?<!\.vue)\.(s?[ac]ss)$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
}
]
Upvotes: 5