I inherited an old repository and I'm trying to update Node as well as some dependencies. The repo uses webpack 3.6 and I'm bumping that up to webpack 5.70.0.
I'm getting the following error when running npm run build
:
> node scripts/build.js
Creating an optimized production build...
Failed to compile.
Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.module.rules[1] should be one of these:
["..." | object { assert?, compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?, loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?, resource?, resourceFragment?, resourceQuery?, rules?, scheme?, sideEffects?, test?, type?, use? }, ...]
-> A rule.
Details:
* configuration.module.rules[1].oneOf[2].loader should be a non-empty string.
-> A loader request.
Here is my webpack.config
const path = require('path');
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require("copy-webpack-plugin");
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const resolveApp = relativePath => path.resolve(__dirname, relativePath);
// Note: defined here because it will be used more than once.
const cssFilename = '/css/[name].css';
const paths = {
appEntry: resolveApp('web/static'),
appAssets: resolveApp('web/static/assets'),
appOutput: resolveApp('priv/static')
}
module.exports = {
bail: true,
devtool: 'source-map',
entry: {
index: [paths.appEntry '/js/index.js', paths.appEntry '/css/globals.scss'],
ads: paths.appEntry '/js/ads.js'
},
output: {
path: paths.appOutput,
filename: 'js/[name].js',
pathinfo: true,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
},
resolve: {
modules: [ "node_modules", __dirname "/web/static/js" ],
extensions: ['.web.js', '.js', '.json', '.web.jsx', '.jsx', '.scss'],
},
optimization: {
minimizer: [
new UglifyJsPlugin({
// compress: {
// warnings: false,
// // Disabled because of an issue with Uglify breaking seemingly valid code:
// // https://github.com/facebookincubator/create-react-app/issues/2376
// // Pending further investigation:
// // https://github.com/mishoo/UglifyJS2/issues/2011
// comparisons: false,
// },
// output: {
// comments: false,
// // Turned on because emoji and regex is not minified properly using default
// // https://github.com/facebookincubator/create-react-app/issues/2488
// ascii_only: true,
// },
sourceMap: true,
}),
]
},
module: {
strictExportPresence: true,
rules: [
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|jsx)$/,
enforce: 'pre',
use: [
{
options: {
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appEntry,
},
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: '/images/[name].[hash:8].[ext]',
},
},
// Process JS with Babel.
{
test: /\.(js|jsx)$/,
include: paths.appEntry,
loader: require.resolve('babel-loader'),
options: {
compact: true
},
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
{
test: /\.s?css$/,
loader: ExtractTextPlugin.extract(
Object.assign(
{
fallback: require.resolve('style-loader'),
use: [
{
loader: require.resolve('css-loader'),
options: {
modules: true,
importLoaders: 1,
minimize: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'> 1%',
'last 8 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
require.resolve('sass-loader')
],
},
{ publicPath: Array(cssFilename.split('/').length).join('../') }
)
),
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
// Exclude `js` files to keep "css" loader working as it injects
// it's runtime that would otherwise processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.js$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: '/images/[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 webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
// Minify the code.
// new webpack.optimize.UglifyJsPlugin({
// compress: {
// warnings: false,
// // Disabled because of an issue with Uglify breaking seemingly valid code:
// // https://github.com/facebookincubator/create-react-app/issues/2376
// // Pending further investigation:
// // https://github.com/mishoo/UglifyJS2/issues/2011
// comparisons: false,
// },
// output: {
// comments: false,
// // Turned on because emoji and regex is not minified properly using default
// // https://github.com/facebookincubator/create-react-app/issues/2488
// ascii_only: true,
// },
// sourceMap: true,
// }),
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
new ExtractTextPlugin({
filename: cssFilename,
}),
new CopyWebpackPlugin({patterns:[{ from: paths.appAssets }]}),
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/
})
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
// node: {
// dgram: 'empty',
// fs: 'empty',
// net: 'empty',
// tls: 'empty',
// child_process: 'empty',
// },
}
The error is referring to this rule, but I'm just not sure what the problem is here.
{
test: /\.s?css$/,
loader: ExtractTextPlugin.extract(
Object.assign(
{
fallback: require.resolve('style-loader'),
use: [
{
loader: require.resolve('css-loader'),
options: {
modules: true,
importLoaders: 1,
minimize: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'> 1%',
'last 8 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
require.resolve('sass-loader')
],
},
{ publicPath: Array(cssFilename.split('/').length).join('../') }
)
),
}
Any help is greatly appreciated!
CodePudding user response:
The error says that the value for "loader" should be a non-empty string. So if you look at the value for "loader", you see this:
loader: ExtractTextPlugin.extract(
I'm willing to bet that the above does not return a string. When looking at the docs for the ExtractTextPlugin
, it says to use it like so:
use: ExtractTextPlugin.extract(