diff --git a/client/package.json b/client/package.json index 4fdc8bb..fa470c3 100644 --- a/client/package.json +++ b/client/package.json @@ -3,44 +3,41 @@ "version": "0.0.1", "description": "Template for creating a new project with a node (express) server and a react client", "dependencies": { - "babel-core": "6.25.0", - "babel-loader": "7.1.1", - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-object-rest-spread": "6.23.0", - "babel-preset-es2015": "6.24.0", - "babel-preset-react": "6.23.0", - "case-sensitive-paths-webpack-plugin": "2.1.1", - "css-loader": "0.28.0", - "es6-promise": "4.1.0", - "extract-text-webpack-plugin": "2.1.2", - "fast-sass-loader": "1.2.5", - "node-sass": "4.5.2", - "path": "0.12.7", - "raw-loader": "0.5.1", - "react-router-routing-helpers": "1.0.3", - "simple-client-request": "1.0.8", - "style-loader": "0.16.1", - "uglifyjs-webpack-plugin": "1.0.1", - "webpack": "3.5.3", - "webpack-node-externals": "1.6.0" + "@babel/core": "^7.23.9", + "@babel/preset-env": "^7.23.9", + "@babel/preset-react": "^7.23.3", + "babel-loader": "^9.1.3", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.10.0", + "mini-css-extract-plugin": "^2.8.1", + "node-sass": "^9.0.0", + "path": "^0.12.7", + "raw-loader": "^4.0.2", + "react-router-routing-helpers": "^1.0.3", + "simple-client-request": "^1.0.8", + "style-loader": "^3.3.4", + "terser-webpack-plugin": "^5.3.10", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4", + "webpack-node-externals": "^3.0.0" }, "peerDependencies": { - "jquery": "3.2.1", - "prop-types": "15.6.1", - "react": "16.3.2", - "react-dom": "16.3.2", - "react-router-dom": "4.2.2" + "jquery": "^3.7.1", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.22.0" }, "devDependencies": { - "jquery": "3.2.1", - "prop-types": "15.6.1", - "react": "16.3.2", - "react-dom": "16.3.2", - "react-router-dom": "4.2.2", - "webpack-dev-server": "2.7.1" + "jquery": "^3.7.1", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.22.0", + "webpack-dev-server": "^4.15.1" }, "scripts": { - "start": "webpack-dev-server --config webpack.config.js --open --env=dev --hot", + "start": "webpack serve --config webpack.config.js --open --env=dev --hot", "compile": "NODE_ENV=production webpack --env=prod --config webpack.config.js --display verbose --progress", "compile-windows": "SET NODE_ENV=production & webpack --env=prod --config webpack.config.js --display verbose --progress", "compile-dev": "webpack --env=dev --config webpack.config.js", diff --git a/client/src/App.js b/client/src/App.js index 33575f3..8af1302 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,33 +1,27 @@ 'use strict'; import React from 'react'; -import {BrowserRouter, Route, Redirect, Switch} from 'react-router-dom'; +import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import layoutStyles from './styleMain/layout.sass'; -import {demoPages} from './routes'; -import {DemoModal} from './containers/modals'; +import { demoPages } from './routes'; +import { DemoModal } from './containers/modals'; +import { HomePage, DemoPage } from './containers/pages'; -import {HomePage, DemoPage} from './containers/pages'; - -class App extends React.Component { - //noinspection JSMethodCanBeStatic - render () { - return ( -
- -
- - - - - - -
-
-
- ); - } +function App() { + return ( +
+ + + } /> + } /> + } /> + + + +
+ ); } export default App; \ No newline at end of file diff --git a/client/src/index.js b/client/src/index.js index 36a89dc..c1f4d95 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,17 +1,14 @@ 'use strict'; import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import App from './App'; -function Main () { - return ( - - ); +function Main() { + return ; } -ReactDOM.render( -
, - document.getElementById('root') -); \ No newline at end of file +const container = document.getElementById('root'); +const root = createRoot(container); +root.render(
); \ No newline at end of file diff --git a/client/webpack.config.js b/client/webpack.config.js index ff5370f..1a79324 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -7,21 +7,18 @@ module.exports = function(env) { if (env === 'ssr') { generalConfig = require('./webpack/ssrConfig').webpack; - } - else { + } else { generalConfig = require('./webpack/clientConfig').webpack; } + const envConfig = require(`./webpack/webpack.${env}.js`); + const execConfig = { ...generalConfig, ...envConfig }; - const envConfig = require('./webpack/webpack.' + env + '.js'); - const execConfig = Object.assign({}, generalConfig, envConfig); - console.log(JSON.stringify(execConfig)); - - console.log('*******************'); - console.log('webpack ' + env + ' setup\n' + - 'Compiling entry point is ' + JSON.stringify(execConfig.entry) + '\n' + - 'Compiling files to ' + execConfig.output.path + ' folder.......'); - console.log('*******************'); + console.log('\n*******************'); + console.log(`Webpack ${env} Configuration:`); + console.log(`Entry point: ${JSON.stringify(execConfig.entry)}`); + console.log(`Output path: ${execConfig.output.path}`); + console.log('*******************\n'); return execConfig; }; \ No newline at end of file diff --git a/client/webpack/clientConfig.js b/client/webpack/clientConfig.js index b9f2334..c7f41a7 100644 --- a/client/webpack/clientConfig.js +++ b/client/webpack/clientConfig.js @@ -15,21 +15,39 @@ const configPaths = { module.exports.configPaths = configPaths; module.exports.webpack = { - entry: configPaths.appDir + '/index.js', + entry: { + main: path.join(configPaths.appDir, 'index.js') + }, output: { - path: configPaths.basePublicPath + configPaths.buildDir, - filename: '[name].bundle.js', - chunkFilename: '[name].bundle.js', - publicPath: configPaths.buildDir + '/' + path: path.join(configPaths.basePublicPath, configPaths.buildDir), + filename: '[name].[contenthash].bundle.js', + chunkFilename: '[name].[contenthash].bundle.js', + publicPath: configPaths.buildDir + '/', + clean: true + }, + resolve: { + extensions: ['.js', '.jsx', '.json'], + modules: ['node_modules', APP_DIR] }, externals: { - 'jquery': 'var jQuery', - - 'react': 'var React', - 'react-dom': 'var ReactDOM', - 'prop-types': 'var PropTypes', - - 'react-router': 'var ReactRouterDOM', - 'react-router-dom': 'var ReactRouterDOM', + jquery: 'jQuery', + react: 'React', + 'react-dom': 'ReactDOM', + 'prop-types': 'PropTypes', + 'react-router-dom': 'ReactRouterDOM' }, + optimization: { + moduleIds: 'deterministic', + runtimeChunk: 'single', + splitChunks: { + chunks: 'all', + cacheGroups: { + vendor: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + chunks: 'all' + } + } + } + } }; \ No newline at end of file diff --git a/client/webpack/webpack.dev.js b/client/webpack/webpack.dev.js index b3285cd..3474607 100644 --- a/client/webpack/webpack.dev.js +++ b/client/webpack/webpack.dev.js @@ -1,65 +1,97 @@ const webpack = require('webpack'); -//noinspection JSUnresolvedVariable -const DefinePlugin = webpack.DefinePlugin; // Replace code with specific values -const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); // Force case sensitive on client paths upon require/import +const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const {appDir, basePublicPath, buildDir} = require('./clientConfig').configPaths; module.exports = { + mode: 'development', module: { rules: [ { - test: /\.js$/, + test: /\.(js|jsx)$/, include: appDir, use: { loader: 'babel-loader', options: { - presets: [['es2015', {modules: false}]], - plugins: ['syntax-dynamic-import'] + presets: [ + ['@babel/preset-env', { modules: false }], + '@babel/preset-react' + ], + plugins: ['@babel/plugin-syntax-dynamic-import'] } } }, { - test: /\.jsx$/, - include: appDir, - use: { - loader: 'babel-loader' - } - }, - { - test: /\.global\.sass$/, // only files with .global will go through this loader. e.g. app.global.sass - loaders: [ + test: /\.global\.sass$/, + use: [ 'style-loader', - 'css-loader?importLoaders=1', - 'fast-sass-loader' + { + loader: 'css-loader', + options: { + importLoaders: 1, + sourceMap: true + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: true + } + } ] }, { - test: /^((?!\.global).)*\.sass$/, // anything with .global will not go through css modules loader + test: /^((?!\.global).)*\.sass$/, include: appDir, use: [ 'style-loader', - 'css-loader?importLoaders=1&modules&localIdentName=[path]___[name]__[local]___[hash:base64:5]', - 'fast-sass-loader' + { + loader: 'css-loader', + options: { + importLoaders: 1, + modules: { + localIdentName: '[path]___[name]__[local]___[hash:base64:5]' + }, + sourceMap: true + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: true + } + } ] } ] }, devServer: { - contentBase: basePublicPath, + static: { + directory: basePublicPath + }, port: 3000, proxy: { '/': process.env.API_HOST || 'http://localhost:4300' }, - publicPath: buildDir + '/' + hot: true, + historyApiFallback: true, + client: { + overlay: { + errors: true, + warnings: false + } + } }, - devtool: 'source-map', + devtool: 'eval-source-map', plugins: [ - new DefinePlugin({ - 'process.env': { - 'NODE_ENV': JSON.stringify('dev') - } + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify('development') }), new CaseSensitivePathsPlugin(), + new MiniCssExtractPlugin({ + filename: '[name].css', + chunkFilename: '[id].css' + }) ] }; diff --git a/client/webpack/webpack.prod.js b/client/webpack/webpack.prod.js index 8e08ddd..99a0b0f 100644 --- a/client/webpack/webpack.prod.js +++ b/client/webpack/webpack.prod.js @@ -1,84 +1,98 @@ 'use strict'; const webpack = require('webpack'); -//noinspection JSUnresolvedVariable -const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); // Uglify code -//noinspection JSUnresolvedVariable -const DefinePlugin = webpack.DefinePlugin; // Replace code with specific values - -const ExtractTextPlugin = require("extract-text-webpack-plugin"); - -const extractSass = new ExtractTextPlugin({ - filename: "bundle.css?[hash]-[chunkhash]-[contenthash]-[name]", - allChunks: true, - disable: process.env.NODE_ENV !== "production" -}); +const TerserPlugin = require('terser-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const {appDir} = require('./clientConfig').configPaths; module.exports = { + mode: 'production', module: { rules: [ { - test: /\.js$/, + test: /\.(js|jsx)$/, include: appDir, use: { loader: 'babel-loader', options: { - presets: [['es2015', {modules: false}]], - plugins: ['syntax-dynamic-import'] + presets: [ + ['@babel/preset-env', { modules: false }], + '@babel/preset-react' + ], + plugins: ['@babel/plugin-syntax-dynamic-import'] } } }, { - test: /\.jsx$/, - include: appDir, - use: { - loader: 'babel-loader' - } - }, - { - test: /\.global\.sass$/, // only files with .global will go through this loader. e.g. app.global.sass - use: ExtractTextPlugin.extract({ - use: [{ - loader: "css-loader?importLoaders=1", + test: /\.global\.sass$/, + use: [ + MiniCssExtractPlugin.loader, + { + loader: 'css-loader', + options: { + importLoaders: 1, + sourceMap: false + } + }, + { + loader: 'sass-loader', options: { sourceMap: false } - }, { - loader: "fast-sass-loader" - }], - // use style-loader in development - fallback: "style-loader" - }), + } + ] }, { - test: /^((?!\.global).)*\.sass$/, // anything with .global will not go through css modules loader + test: /^((?!\.global).)*\.sass$/, include: appDir, - use: ExtractTextPlugin.extract({ - use: [{ - loader: "css-loader?importLoaders=1&modules&localIdentName=[path]___[name]__[local]", + use: [ + MiniCssExtractPlugin.loader, + { + loader: 'css-loader', options: { - modules: true, - sourceMap: false, - minimize: true + importLoaders: 1, + modules: { + localIdentName: '[hash:base64:5]' + }, + sourceMap: false + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: false } - }, { - loader: "fast-sass-loader" - }], - // use style-loader in development - fallback: "style-loader" - }), + } + ] } ] }, + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + terserOptions: { + compress: { + drop_console: true + }, + format: { + comments: false + } + }, + extractComments: false + }), + new CssMinimizerPlugin() + ] + }, plugins: [ - extractSass, - new DefinePlugin({ - 'process.env': { - 'NODE_ENV': JSON.stringify('production') - } + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify('production') }), - new UglifyJsPlugin(), + new MiniCssExtractPlugin({ + filename: '[name].[contenthash].css', + chunkFilename: '[id].[contenthash].css' + }) ] }; diff --git a/server/package.json b/server/package.json index a093d0b..237c403 100644 --- a/server/package.json +++ b/server/package.json @@ -7,20 +7,20 @@ }, "devDependencies": {}, "dependencies": { - "react-router-routing-helpers": "1.0.3", + "react-router-routing-helpers": "^1.0.3", "simple-client-request": "file:./ssr/mockupPackages/simpleClientRequest", - "jquery": "3.2.1", - "prop-types": "15.6.1", - "react": "16.3.2", - "react-dom": "16.3.2", - "react-router-dom": "4.2.2", - "body-parser": "1.18.3", - "cookie-parser": "1.4.3", - "debug": "4.0.1", - "express": "4.16.3", - "express-session": "1.15.6", - "morgan": "1.9.1", - "pug": "2.0.3", - "serve-favicon": "2.5.0" + "jquery": "^3.7.1", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.22.0", + "body-parser": "^1.20.2", + "cookie-parser": "^1.4.6", + "debug": "^4.3.4", + "express": "^4.18.2", + "express-session": "^1.17.3", + "morgan": "^1.10.0", + "pug": "^3.0.2", + "serve-favicon": "^2.5.0" } }