Reputation: 159
I am trying to extract different scss entries to separate css bundle files
My folder structure goes something like:
red.scss and blue.scss are importing other (same) .scss files
index.js doesnt import any .scss
i want my output to be:
i used minicssextractplugin, to do the job, but all i got was:
Used many tutorials but most of them are compatible with webpack 4. Used optimization, splitChunks, cacheGroups etc All kind of different entry cases
My dependencies are:
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
"@babel/preset-env": "^7.12.11",
"babel-loader": "^8.2.2",
"babel-polyfill": "^6.26.0",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^5.0.1",
"file-loader": "^6.2.0",
"mini-css-extract-plugin": "^1.3.3",
"node-sass": "^5.0.0",
"sass-loader": "^10.1.0",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^5.11.0",
"webpack-cli": "^4.2.0"
},
I cant copy my webpack.config.js in here, getting error about format Here are some parts:
entry: {
red: path.resolve(__dirname, 'src/themes/red/'),
blue: path.resolve(__dirname, 'src/themes/blue/'),
},
//devtool: 'source-map',
//entry: './src/index.js',
//entry: ['./src/index.js', './src/css/index.scss'],
//entry: {
// //default: './src/default.js',
// blue: './src/themes/blue',
// red: './src/themes/red'
//},
//entry: {
// //index: './src/index.js',
// //main: './src/index.js',
// //styles: ['./src/themes/red.scss', './src/themes/default.scss', './src/themes/blue.scss']
// default: ['./src/default.js', './src/themes/default.scss'],
// red: ['./src/red.js', './src/themes/red.scss'],
// blue: ['./src/blue.js', './src/themes/blue.scss'],
//},
output: {
path: path.resolve(__dirname, 'wwwroot/dist'),
filename: '[name].js'
//sourceMapFilename: '[name].js.map'
},
optimization: {
splitChunks: {
cacheGroups: {
redStyles: {
name: 'styles_red',
test: (m, c, entry = 'red') =>
m.constructor.name === 'CssModule' &&
recursiveIssuer(m, c) === entry,
chunks: 'all',
enforce: true,
},
blueStyles: {
name: 'styles_blue',
test: (m, c, entry = 'blue') =>
m.constructor.name === 'CssModule' &&
recursiveIssuer(m, c) === entry,
chunks: 'all',
enforce: true,
},
},
},
},
module: {
rules: [
{
test: /\.s[c|a]ss$/,
include: path.resolve(__dirname, 'src'),
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
]
},
//{
// test: /\.js$/,
// include: path.resolve(__dirname, 'src'),
// loader: 'babel-loader',
// options: {
// presets: ["@babel/preset-env"],
// plugins: ['@babel/plugin-proposal-object-rest-spread']
// }
//},
{
test: /\.(png|jpg)$/,
include: path.resolve(__dirname, 'src'),
use: {
loader: "file-loader"
}
}
]
}
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
//new FixStyleOnlyEntriesPlugin(),
new MiniCssExtractPlugin({
filename: "[name].css",
}),
//new MiniCssExtractPlugin({
// filename: "[name].css",
// //chunkFilename: "[name].css"
//})
//new MiniCssExtractPlugin({
// filename: '[name].css'
//}),
//defaultTheme,
//redTheme,
//blueTheme
]
Upvotes: 2
Views: 916
Reputation: 61
(copy of my answer)
my case: webpack 5 + multipage application + themes.css via entry points
solution: https://github.com/webdiscus/webpack-remove-empty-scripts
this plugins don't work with webpack 5 entry points or with MiniCssExtractPlugin:
webpack-fix-style-only-entries, webpack-extraneous-file-cleanup-plugin, webpack-remove-empty-js-chunks-plugin, webpack-delete-no-js-entries-plugin.
my webpack.config.js
:
const fs = require('fs');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');
const isProd = process.env.NODE_ENV === 'production';
const isDev = !isProd;
const PAGES = ['app', 'help'];
const getThemes = (themePath, alias) => {
let themes = {};
const longPath = './' + alias + '/' + themePath;
fs.readdirSync(longPath).forEach(function(fileName) {
const fileNameWithPath = path.join(themePath, fileName);
const fileNameWithLongPath = path.join(longPath, fileName);
const stat = fs.lstatSync(fileNameWithLongPath);
if (stat.isDirectory()) return;
if (!/\.scss$/.test(fileName)) return;
const nameWithoutExt = path.basename(fileName, '.scss');
themes[nameWithoutExt] = ['./' + fileNameWithPath];
});
console.log(themes);
return themes;
};
const themes = getThemes('scss/themes', 'src');
const getFilename = (filename, ext) => {
let name = filename == 'index' ? 'bundle' : filename;
const isTheme = (ext == 'css' && name.startsWith('theme')) ? true : false;
const needHash = (isDev || isTheme) ? false : true;
return needHash ? name +`.[fullhash].` + ext : name+'.'+ext;
};
const getCSSDirname = filename => {
const isTheme = filename.startsWith('theme');
return !isTheme? '/css/' : '/css/theme/';
};
const getHTMLWebpackPlugins = arr => {
// this function config multipages names and add to html-pages
// inside <head> tag our themes via tag <link rel="stylesheet" href="....css" ...>
// and return array of HTMLWebpackPlugins
};
module.exports = {
// ... //
entry: {
// mutipage:
app: ['./index.js', './scss/app.scss'],
help: ['./help.js', './scss/help.scss'],
// multitheme:
...themes,
},
optimization: {
removeEmptyChunks: true, // not work!!!
},
// ... //
plugins: [
// ... //
...getHTMLWebpackPlugins(PAGES),
new RemoveEmptyScriptsPlugin({
ignore: PAGES,
enabled: isDev === false,
}),
new MiniCssExtractPlugin({
filename: pathdata => {
return getCSSDirname(pathdata.chunk.name) + getFilename(pathdata.chunk.name, 'css');
},
chunkFilename: isDev ? '[id].css' : '[id].[contenthash].css',
}),
],
};
my src files:
[src]:
- index.js
- index.html
- help.js
- help.html
- [scss]:
- - app.scss
- - help.scss
- - [themes]:
- - - light.scss
- - - dark.scss
- - - blue.scss
after build:
[dist]:
- app.js
- index.html
- help$hash.js
- help$hash.html
- [css]:
- - app$hash.css
- - help$.css
- - [themes]:
- - - light.css
- - - dark.css
- - - blue.css
Upvotes: 1