I have been updating all my Babel and Webpack dependencies to remove vulnerabilities. Currently, my package.json file looks like this and it installs all dependencies perfectly:
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"watch": "webpack --watch",
"test": "jest --coverage --config ./jest.config.js",
"test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand",
"test:watch": "npm run test -- --watch",
"test:watchAll": "npm run test -- --watchAll",
"test:updateSnapshot": "jest --updateSnapshot"
},
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.8.1",
"core-js": "^3.36.0",
"dom-to-image": "2.6.0",
"i18n-react": "0.6.4",
"immutable": "^4.0.0-rc.12",
"jquery": "^3.4.1",
"mime-types": "latest",
"prop-types": "latest",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-redux": "^7.2.2",
"react-select": "3.0.4",
"react-svg": "^10.0.14",
"react-webcam": "^5.2.0",
"reactjs-popup": "^1.4.2",
"redux": "4.2.0",
"redux-logger": "3.0.6",
"redux-promise-middleware": "6.1.2",
"redux-thunk": "^2.4.1"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/eslint-parser": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-decorators": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"babel-jest": "^29.7.0",
"babel-loader": "^9.0.0",
"babel-plugin-react-html-attrs": "^3.0.5",
"babel-plugin-rewire": "^1.0.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.10.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.4.3",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.0.0",
"jest": "^29.7.0",
"less": "^4.2.0",
"less-loader": "^11.1.0",
"react-hot-loader": "4.8.4",
"style-loader": "^3.3.4",
"url-loader": "^4.0.0",
"webpack": "^5.76.0",
"webpack-cli": "^5.0.0",
"webpack-dev-server": "^5.0.0"
}
}
I am configuring through the webpack-config.js file, and it looks like this:
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Copy
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');
const config = {
js: {
srcDir: 'src/main/javascript',
resourceDir: 'src/main/resources',
src: ./main.jsx,
outputDir: './target/classes/static/',
outputFile: 'bundle.js',
},
};
const debug = process.env.NODE_ENV !== 'production';
const modules = [];
modules.push(config.js.srcDir);
const modulesWithNode = modules.slice();
modulesWithNode.push('node_modules');
module.exports = {
mode: debug ? 'development' : 'production',
context: path.join(__dirname, config.js.srcDir),
devtool: debug ? 'source-map' : 'hidden-source-map',
entry: {
app: [config.js.src],
},
output: {
filename: config.js.outputFile,
publicPath: '/',
path: path.join(__dirname, config.js.outputDir),
sourceMapFilename: 'prod-[file].map',
},
resolve: {
modules: modulesWithNode,
extensions: ['.js', '.jsx'],
fallback: { path: false },
},
module: {
rules: [
{
test: /.jsx?$/,
include: modules.map(module => path.resolve(__dirname, module)),
use: {
loader: 'babel-loader',
options: {
presets: [['@babel/preset-env', { useBuiltIns: 'entry', corejs: 3 }], '@babel/preset-react'],
plugins: [['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }], '@babel/plugin-proposal-class-properties'],
retainLines: true,
},
},
},
{
test: /.less$/,
include: modules.map(module => path.resolve(__dirname, module)),
use: [
{ loader: 'style-loader'},
{ loader: 'css-loader', options: { sourceMap: debug } },
{ loader: 'less-loader', options: { sourceMap: debug } }
],
},
{
test: /.(jpg|png|woff|woff2|eot|ttf|svg|wav)$/,
use: 'url-loader?limit=100000'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
inject: 'body'
}),
new CopyWebpackPlugin({
patterns: [
{
context: '../resources',
from: './static/assets/sounds/camera-shutter-sound.wav',
to: 'assets/sounds',
toType: 'dir',
},
{
from: './sw',
to: './',
},
]
}),
]
};
I am using Node version 20.11.0 and npm version 10.2.4. When I install all the dependencies through Maven, I don't get any errors. However, when I start my application through Spring Boot and deploy the frontend, I always receive this error on browser console:
Uncaught Error: You must pass a component to the function returned by connect. Instead received {"kind":"class","elements":[{"kind":"method","key":"render","placement":"prototype","descriptor":{"writable":true,"configurable":true,"enumerable":false}}]}
I assume it has something to do with the configuration of the decorators, which is causing this condition in the connectAdvanced.js file of react-redux, as I haven't made any changes to the code.
I have been trying to configure decorators in so many ways, but none worked. I expect to load all components on my page without errors.
The issue seems to be how Babel is transpiling your JS code, specifically regarding the use of the decorators with React components.
When using the
@babel/plugin-proposal-decoratorsplugin, the order of plugins matters, especially when used in conjunction with the@babel/plugin-proposal-class-propertiesplugin. The decorators proposal has had several iterations, and the syntax and semantics have changed over time, so it's crucial that Babel plugins are correctly configured.You can try to change the order of the plugins. The
@babel/plugin-proposal-decoratorsshould come before the@babel/plugin-proposal-class-propertiesplugin in your Babel configuration array. Moreover, if you are using the legacy mode for decorators (common in React projects), you need to set thelegacy: trueoption for the decorators plugin andloose: truefor class properties:This setup is important because the
legacy: trueoption enables the use of the older decorator syntax, which is what most React and Redux codebases that use decorators require.After you change their orders and add the
legacy/loose pair, you should run the commands: