Bundle and minify multiple JS and CSS files with webpack - ERROR Module not found
Asked Answered
K

1

1

Trying to use Webpack to bundle and minify all the JS files to a bundle.min.js file, and all the CSS files into a bundle.min.css file.

Folder structure:

root
|- assets
|- src
|-- js
|--- *.js
|-- css
|--- *.css

Code:

const glob = require('glob');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    mode: 'production',
    entry: {
        scripts: glob.sync('./src/js/*.js'),
        styles: glob.sync('./src/css/*.css')
    },
    output: {
        path: path.resolve(__dirname, 'assets'),
        filename: '[name].bundle.min.js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].bundle.min.css'
        })
    ],
    optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()]
    }
}

When I try to run npx webpack --config webpack.config.js, I get the following error(s) for all the JS and CSS files:

ERROR in [...]
Module not found: Error: Can't resolve 'src\css\[...].css' in '[...]'
Did you mean './src\css\[...].css'?
Requests that should resolve in the current directory need to start with './'.
Requests that start with a name are treated as module requests and resolve within module directories (node_modules).
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.

Kinda stuck at this point. Any suggestions is GREATLY appreciated. Thanks in advance.

Karrikarrie answered 29/6, 2023 at 18:26 Comment(1)
I'm sure it's because of glob, maybe this will help you Wildcards in entry points and How to add wildcard mapping in entry of webpackRabbin
M
1

The advice in the building errors message is clear.

Requests that should resolve in the current directory need to start with './'.

If the path doesn't start with './', it will parse the request as a module

Requests that start with a name are treated as module requests and resolve within module directories (node_modules).

Webpack will try to resolve the module within module directories (node_modules).

Project structure:

$ tree -L 3 -I node_modules
.
├── assets
│   ├── scripts.bundle.min.js
│   ├── styles.bundle.min.css
│   └── styles.bundle.min.js
├── package-lock.json
├── package.json
├── src
│   ├── css
│   │   ├── a.css
│   │   └── b.css
│   └── js
│       ├── a.js
│       └── b.js
└── webpack.config.js

Two solutions:

  • Use { dotRelative: true } option for glob.sync()

Prepend all relative path strings with ./ (or .\ on Windows).

E.g.

glob.sync('./src/js/*.js', { dotRelative: true })
// [ './src/js/b.js', './src/js/a.js' ]

webpack.config.js:

const glob = require('glob');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    mode: 'production',
    entry: {
        scripts: glob.sync('./src/js/*.js', { dotRelative: true }),
        styles: glob.sync('./src/css/*.css', { dotRelative: true }),
    },
    output: {
        path: path.resolve(__dirname, 'assets'),
        filename: '[name].bundle.min.js',
        clean: true,
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader'],
            },
        ],
    },
    plugins: [new MiniCssExtractPlugin({ filename: '[name].bundle.min.css' })],
};

When enabled, webpack would prefer to resolve module requests as relative requests instead of using modules from node_modules directories.

This solution is also mentioned in the error:

If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.

webpack.config.js:

const glob = require('glob');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    mode: 'production',
    entry: {
        scripts: glob.sync('./src/js/*.js'),
        styles: glob.sync('./src/css/*.css'),
    },
    output: {
        path: path.resolve(__dirname, 'assets'),
        filename: '[name].bundle.min.js',
        clean: true,
    },
    resolve: {
        preferRelative: true,
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader'],
            },
        ],
    },
    plugins: [new MiniCssExtractPlugin({ filename: '[name].bundle.min.css' })],
};

Build logs:

> webpack

asset styles.bundle.min.css 76 bytes [compared for emit] (name: styles)
asset scripts.bundle.min.js 34 bytes [compared for emit] [minimized] (name: scripts)
asset styles.bundle.min.js 0 bytes [compared for emit] [minimized] (name: styles)
Entrypoint scripts 34 bytes = scripts.bundle.min.js
Entrypoint styles 76 bytes = styles.bundle.min.css 76 bytes styles.bundle.min.js 0 bytes
orphan modules 3.23 KiB (javascript) 1.83 KiB (runtime) [orphan] 12 modules
cacheable modules 136 bytes (javascript) 74 bytes (css/mini-extract)
  javascript modules 136 bytes
    modules by path ./src/js/*.js 36 bytes
      ./src/js/b.js 18 bytes [built] [code generated]
      ./src/js/a.js 18 bytes [built] [code generated]
    modules by path ./src/css/*.css 100 bytes
      ./src/css/b.css 50 bytes [built] [code generated]
      ./src/css/a.css 50 bytes [built] [code generated]
  css modules 74 bytes
    css ./node_modules/css-loader/dist/cjs.js!./src/css/b.css 37 bytes [built] [code generated]
    css ./node_modules/css-loader/dist/cjs.js!./src/css/a.css 37 bytes [built] [code generated]
webpack 5.88.1 compiled successfully in 245 ms

package versions:

"css-loader": "^6.8.1",
"glob": "^10.3.1",
"mini-css-extract-plugin": "^2.7.6",
"webpack": "^5.80.0",
"webpack-cli": "^5.0.2"

Note: For better demonstration, I simplified the example, removed some loaders, plugins and configuration. Because they are not the cause of the problem.

Meredithmeredithe answered 6/7, 2023 at 3:18 Comment(2)
THANK YOU! Tried the dotRelative option version, and came back with the same error as I originally posted. Then, tried the preferRelative version, and worked! Now... one thing that happens it builds and empty styles.bundle.min.js file - which I saw in your build log. Is it because of the how the output for the entry points is set up? Any way of preventing this?Karrikarrie
@Karrikarrie see github.com/webpack-contrib/extract-text-webpack-plugin/issues/… and github.com/webdiscus/webpack-remove-empty-scriptsMeredithmeredithe

© 2022 - 2025 — McMap. All rights reserved.