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.