Reputation: 20116
I use webpack ^5.65.0.
I want to compile all my scss file into css but I have to use multiple import
in my entry index.js
like
import './index.scss';
import './test.scss'
...
I do not want to use import in the index.js
file and think it can be done by webpack settings(I am not sure).
My webpack.config.js
module.exports = {
devtool: 'eval-cheap-module-source-map',
mode: isDev ? 'development' : 'production',
entry: {
index: './src/index.js',
login: './src/login.js',
test:'./test.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash:6].js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.jsx?$/,
use: ['cache-loader','babel-loader'],
include: [path.resolve(__dirname, 'src')]
},
{
test: /\.(sc|sa|c)ss/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
include: [path.resolve(__dirname, 'src')]
}
]
}
}
I have no idea, then add a test.js
to put all the scss import
in it and add it to the entry.But the output will also has a test.xxxxxx.js
file in the dist
folder and I do not want it though.
So,what is the right way to meet my requirement.
Is it possible to just compile all scss
file without import
in the entry js
file and do not generate the same-name js file in output folder?
Upvotes: 3
Views: 3742
Reputation: 545
I assume that you want to automatically build all *.scss
files that are in ./src
is that right?
Thankfully webpack.config.js is a js file so you can generate the config programmatically.
Expanding @biodiscus answer to automatically fetch the files:
// => webpack.config.js
const path = require("path");
const fs = require("fs");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const scssFiles = fs.readdirSync("./src").filter(function (file) {
return file.match(/.*\.scss$/);
});
const scssEntries = scssFiles.map((filename) => {
const filenameWithoutExtension = filename.replace(/\.[^/.]+$/, "");
const entryName = `style_` + filenameWithoutExtension;
return { [entryName]: "./src/" + filename };
});
module.exports = {
entry: {
index: "./src/index.js",
login: './src/login.js',
test:'./test.js'
...Object.assign({}, ...scssEntries),
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
},
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{ // a loader loads file with matching extension no matter
// if it is listed in entry: or imported inside js
test: /\.(sc|sa|c)ss/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
include: [path.resolve(__dirname, "src")],
},
],
},
};
So the changes are: First, get names of all scss files:
const scssFiles = fs.readdirSync("./src").filter(function (file) {
return file.match(/.*\.scss$/);
});
const scssEntries = scssFiles.map((filename) => {
const filenameWithoutExtension = filename.replace(/\.[^/.]+$/, "");
const entryName = `style_` + filenameWithoutExtension;
return { [entryName]: "./src/" + filename };
});
Second, append them to the list of entries:
entry: {
index: "./src/index.js",
login: './src/login.js',
test:'./test.js'
...Object.assign({}, ...scssEntries),
},
and third, this is important:
output: {
filename: "[name].js", // <-- use template for named output
path: path.resolve(__dirname, "dist"),
},
Also, notice how I prepended the entry names with style_
. Otherwise index.js
and index.scss
would have both same entry name resulting in only one being built.
Upvotes: 2