Webpack: compile SASS in own file with multiple entry points

Webpack allows specifying multiple entry points, for example, to compile multiple JavaScript files via Babel. This post shows how to compile SASS to its own file when using various entry points.

The problem

Until now, I always had something like that as the entry in my Webpack config:

entry: ['./assets/src/js/functions.js', './assets/src/scss/frontend.scss', './assets/src/scss/editor.scss'],

With various loaders, I compiled the JavaScript via Babel to a functions.js and the SASS files to the CSS files frontend.css and editor.css. Now I wanted to add a second JavaScript file as an entry, which should be compiled to a separate file. The Webpack documentation on entry points shows how to define multiple entry points, and that was my first attempt:

entry: {
    functions: './assets/src/js/functions.js',
    glide: './assets/src/js/glide.js',
    frontend: './assets/src/scss/frontend.scss',
    editor: './assets/src/scss/editor.scss',
},

That worked somehow but had its problems. For every CSS file, I got a JavaScript file with the same name. Theoretically, I could ignore them, but that would not be very satisfying.

The solution

In the afterthought, the solution is relatively simple: I write the SASS files in an array with one of the JavaScript files and get my wanted solution of two JavaScript and two CSS files.

entry: {
    functions: ['./assets/src/js/functions.js', './assets/src/scss/frontend.scss', './assets/src/scss/editor.scss'],
    glide: './assets/src/js/glide.js',
},

That could be a Webpack 4 config file with the solution:

const path = require('path');

module.exports = {
    mode: 'development',
    entry: {
        functions: ['./assets/src/js/functions.js', './assets/src/scss/frontend.scss', './assets/src/scss/editor.scss'],
        glide: './assets/src/js/glide.js',
    },
    output: {
        path: path.resolve(__dirname, 'assets'),
        filename: 'dist/js/[name].js',
    },
    module: {
        rules: [
            /**
             * Running Babel on JS files.
             */
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        plugins: ['lodash'],
                        presets: ['@wordpress/default']
                    }
                }
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: 'dist/css/[name].css',
                        }
                    },
                    {
                        loader: 'extract-loader'
                    },
                    {
                        loader: 'css-loader?-url'
                    },
                    {
                        loader: 'postcss-loader'
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            }
        ]
    },
};

Here are the devDependencies from my package.json (more than needed for that example):

"devDependencies": {
  "@wordpress/babel-preset-default": "^1.3.0",
  "autoprefixer": "^8.5.0",
  "babel-core": "^6.26.0",
  "babel-loader": "^7.1.2",
  "babel-preset-env": "^1.6.0",
  "css-loader": "^0.28.7",
  "extract-loader": "^2.0.1",
  "file-loader": "^1.1.11",
  "lodash-webpack-plugin": "^0.11.5",
  "node-sass": "^4.9.0",
  "postcss-cli": "^5.0.0",
  "postcss-loader": "^2.0.6",
  "sass-loader": "^7.0.1",
  "svg-spritemap-webpack-plugin": "^2.6.0",
  "svgo": "^1.0.5",
  "svgo-loader": "^2.1.0",
  "webpack": "^4.8.3",
  "webpack-cli": "^3.0.8"
},

And that is the content of my postcss.config.js:

module.exports = {
    plugins: {
        autoprefixer: { browsers: ['last 2 versions'], grid: true }
    }
}

Related posts

Leave a Comment

Your email address will not be published. Required fields are marked *