I'm updating the libraries in our web app to the latest thus pushing Webpack up to Webpack5. When adjusting the parameters for 'webpack.config.dev.js' I keep running into the following error during compilation:
...../node_modules/webpack/lib/NormalModule.js:1306
hash.update(this.buildInfo.hash);
^
TypeError: Cannot read property 'hash' of undefined
Here is my webpack.config.dev.js file so far (I removed the comments to try and keep it a little shorter):
'use strict';
const autoprefixer = require('autoprefixer');
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
const publicPath = 'http://localhost:3000/';
const publicUrl = 'http://localhost:3000/';
const env = getClientEnvironment(publicUrl);
const BundleTracker = require('webpack-bundle-tracker');
// This is the development configuration.
// It is focused on developer experience and fast rebuilds.
// The production configuration is different and lives in a separate file.
module.exports = {
devtool: 'cheap-module-source-map',
entry: [
require.resolve('./polyfills'),
require.resolve('webpack-dev-server/client') + '?http://localhost:3000',
require.resolve('webpack/hot/dev-server'),
paths.appIndexJs,
],
output: {
pathinfo: true,
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].chunk.js',
publicPath: publicPath,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
},
resolve: {
modules: ['node_modules', paths.appNodeModules].concat(
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
'react-native': 'react-native-web',
},
plugins: [
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
new BundleTracker({path: paths.statsRoot, filename: 'webpack-stats.dev.json'}),
],
fallback: {
dgram: false,
fs: false,
net: false,
tls: false,
child_process: false
}
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.(js|jsx|mjs)$/,
enforce: 'pre',
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
{
oneOf: [
{
test: /\.worker\.(js|jsx|mjs)$/,
include: paths.appSrc,
use: [
require.resolve("worker-loader"),
require.resolve("thread-loader"),
{
loader: require.resolve("babel-loader"),
options: {
babelrc: false,
presets: [require.resolve("babel-preset-react-app")],
cacheDirectory: true,
highlightCode: true,
},
},
],
},
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
{
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
},
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
options: {
minimize: true
}
}
},
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
],
flexbox: 'no-2009',
}),
],
},
},
],
},
{
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
],
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
plugins: [
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin({
// inject: true,
template: paths.appHtml,
hash: false,
}),
new webpack.DefinePlugin(env.stringified),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new BundleTracker({path: paths.statsRoot, filename: 'webpack-stats.dev.json'}),
],
performance: {
hints: false,
},
optimization: {
moduleIds: 'named',
}
};
and here are my current relevant libraries (or at least the ones I think are relevant, I'll definitely post any others if needed)
html-webpack-plugin@5.3.2
webpack@5.51.1
react-dev-utils@11.0.4
The part that I believe is causing the issue is the plugins, specifically the HtmlWebpackPlugin:
plugins: [
*** I think the HtmlWebpackPlugin is causing the issue ***
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin({
// inject: true,
template: paths.appHtml,
hash: false,
}),
...
],
Any idea on how to fix the error? I feel like I am calling the HtmlWebpackPlugin correctly, but am I dumb?
Update 1: Inverting InterpolateHtmlPlugin and HtmlWebpackPlugin yields the same error
Update 2: HtmlWebpackPlugin was determined not to be the cause of the issue, the error is tracing back to Webpack at this time.
Update 3: Git repo to recreate error located at: https://github.com/mexicantexan/webpack-error-reproduction and an issue has been opened up at the following link: https://github.com/webpack/webpack/issues/14142
Update 4: Solved. Check below for the checkmarked solution.
Turns out that we had BundleTracker in the wrong place. In the config file we removed it from module.exports.resolve.plugins and the app started right up. Shout out to alexander-akait for noticing it!!