Home > Blockchain >  What causes this failure to compile SCSS to CSS with Webpack?
What causes this failure to compile SCSS to CSS with Webpack?

Time:04-23

I am working on a project that needs CSS and JavaScript code to be compiled in distinct files.

I have a JavaScript source file - <root>/src/js/main.js - that is compiled into <root>/dist/main.js, as expected.

The webpack config file looks like so:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var path = require("path");

module.exports = {
mode: 'development',
entry: "./src/js/main.js",
output: {
    path: path.resolve(__dirname, "dist/js"),
    filename: '[name].js',
    publicPath: "/dist"
 },
  watch:true,
  module: {
    rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
            },
          },
        },
        {
          test: /\.s?css$/,
          use: [
            MiniCssExtractPlugin.loader,
            "css-loader",
            "sass-loader"
          ]
      }
    ]
  },
  plugins: [
      new MiniCssExtractPlugin({
        filename: "[name].css",
        chunkFilename: "[id].css"
      })
  ]
}

In <root>/src/scss/ I have an app.scss file with various imports:

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Bootstrap 4
@import '~bootstrap/scss/bootstrap';

// Layout
@import './layout';

The directories and files tree:

enter image description here

The package.json file:

{
  "name": "myproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/preset-env": "^7.16.11",
    "mini-css-extract-plugin": "^2.6.0",
    "node-sass": "^7.0.1",
    "sass": "^1.50.0",
    "sass-loader": "^12.6.0",
    "webpack": "^5.72.0",
    "webpack-cli": "^4.9.2"
  },
  "dependencies": {
    "@babel/core": "^7.17.9",
    "babel-loader": "^8.2.4",
    "bootstrap": "^4.6.0",
    "css-loader": "^6.7.1",
    "jquery": "^3.6.0",
    "popper.js": "^1.16.1",
    "style-loader": "^3.3.1"
  }
}

The problem:

I need the SCSS to be compiled into <root>/dist/css/app.css, but something must be missing from the webpack.config.js file because no CSS file is generated.

Questions:

  1. What is missing from the config file?
  2. How can I make sure the generated CSS is minified?

CodePudding user response:

css bundling

Basically your css is not bundled cause webpack is configruated to build only ./src/js/main.js file and all the other files that are imported from that single entry point.

To make webpack bundle css files you can either import it from handled js files or include it as additional entryPoint into webpack.config.js:

Option 1. Add import

Just add into src/js/main.js file the following line

import "../scss/app.scss";
Option 2. Specify entry point in webpack config

Remove current entry point line

entry: "./src/js/main.js",

And add new entry point line with multiple entry points specified

entry: ["./src/js/main.js", "./src/scss/app.scss"],

output files structure

In your question you mentioned that you want to put js bundle to ./dist/js/main.js and css bundle to ./dist/css/app.css but webpack is not very flexible with multiple entry points output paths. So it's better to update your webpack config output field to the following one:

output: {
  path: path.resolve(__dirname, "dist"),
  filename: "[name].js",
  publicPath: "/dist",
},

That will produce flat bundled chunks files structure like ./dist/main.js and ./dist/main.css.

css minification

To enable css minification you need to install css-minimizer-webpack-plugin (you can use any other minification plugin but I will just show example of using it) via npm install --save-dev css-minimizer-webpack-plugin or yarn add -D css-minimizer-webpack-plugin. And include it into your webpack.config.js file as following:

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
...
module.exports = {
...
  optimization: {
    minimizer: [new CssMinimizerPlugin()],
  },
  plugins: [
    ...,
    new CssMinimizerPlugin(),
  ],
...
}

To make sure your css is minfified you just need to run webpack build and checkout bundled css file in dist directory. If it has no unnecessary spaces or lines wrap after legal comments that means you css is minified ;)

  • Related