const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const isProduction = process.env.NODE_ENV === 'production'; module.exports = { mode: isProduction ? 'production' : 'development', entry: './src/react/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: (pathData) => { return pathData.chunk.name === 'main' ? 'static/js/bundle.js' : 'static/js/[name].[contenthash:8].js'; }, chunkFilename: 'static/js/chunk.[id].[contenthash:8].js', publicPath: '/', clean: true, }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env', { targets: { browsers: ['> 0.25%', 'not dead'], }, modules: false, }], ['@babel/preset-react', { runtime: 'automatic', }], ], plugins: [ '@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread', ], }, }, }, { test: /\.css$/i, use: [ isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: { auto: true, localIdentName: isProduction ? '[hash:base64:8]' : '[name]__[local]__[hash:base64:4]', }, }, }, { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ 'autoprefixer', isProduction && 'cssnano', ].filter(Boolean), }, }, }, ], }, { test: /\.(png|jpe?g|gif|svg|webp)$/i, type: 'asset/resource', generator: { filename: 'static/media/[name].[hash:8][ext]', }, }, { test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/resource', generator: { filename: 'static/fonts/[name].[hash:8][ext]', }, }, ], }, plugins: [ ...(isProduction ? [ new MiniCssExtractPlugin({ filename: 'static/css/[name].[contenthash:8].css', chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', }), ] : []), ], optimization: { minimize: isProduction, minimizer: [ new TerserPlugin({ terserOptions: { compress: { drop_console: isProduction, drop_debugger: isProduction, }, }, }), new CssMinimizerPlugin(), ], splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendor', chunks: 'all', enforce: true, }, }, }, }, resolve: { extensions: ['.js', '.jsx', '.json'], alias: { '@': path.resolve(__dirname, 'src/react'), '@components': path.resolve(__dirname, 'src/react/components'), '@utils': path.resolve(__dirname, 'src/react/utils'), '@assets': path.resolve(__dirname, 'src/react/assets'), }, }, devServer: { static: { directory: path.join(__dirname, 'dist'), }, compress: true, port: 3000, hot: true, open: true, historyApiFallback: true, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, secure: false, }, }, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', 'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization', }, }, devtool: isProduction ? 'source-map' : 'eval-cheap-module-source-map', performance: { hints: isProduction ? 'warning' : false, maxEntrypointSize: 512000, maxAssetSize: 512000, }, stats: { colors: true, children: false, chunks: false, chunkModules: false, modules: false, reasons: false, errorDetails: true, assets: true, version: false, timings: true, }, };