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>
This is a fork based on style-loader. Similar to style-loader , you can chain it after css-loader to dynamically inject CSS into the document as style tags.
This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
style-loader injects the styling through a style element. The way it does this can be customized. It also implements the Hot Module Replacement interface providing for a pleasant development experience. The matched files can be processed through asset modules by using the type field at a loader definition.
It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps. It builds on top of a new webpack v5 feature and requires webpack 5 to work. Compared to the extract-text-webpack-plugin: To begin, you'll need to install mini-css-extract-plugin:
For development mode (including webpack-dev-server) you can use style-loader, because it injects CSS into the DOM using multiple and works faster. i Do not use together style-loader and mini-css-extract-plugin. ⚠ Names of locals are converted to camelCase.
.css .scss and .sass files are loaded with vue-style-loader in development mode and MiniCSSExtractPlugin.loader in production mode. One tricky point is that sass files are loaded by using two loaders: sass-loader and css-loader.
This plugin should not be used with style-loader in the loaders chain. Here is an example to have both HMR in development and your styles extracted in a file for production builds. (Loaders options left out for clarity, adapt accordingly to your needs.)
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'
]
}
]
}
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']
}
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With