Ryan
Ryan

Reputation: 20116

Webpack how to compile all my scss file without generating the useless same-name js file

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

Answers (1)

jblew
jblew

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

Related Questions