const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); const TerserPlugin = require('terser-webpack-plugin'); // 端口从环境变量读取,默认 3015(沙箱固定端口) const DEV_PORT = parseInt(process.env.DEV_PORT || '3015', 10); module.exports = (env, argv) => { const isDev = argv.mode !== 'production'; return { mode: isDev ? 'development' : 'production', entry: './src/index.tsx', output: { path: path.resolve(__dirname, 'dist'), filename: isDev ? '[name].js' : '[name].[contenthash:8].js', chunkFilename: isDev ? '[name].chunk.js' : '[name].[contenthash:8].chunk.js', publicPath: '/', clean: true, }, optimization: { minimize: !isDev, minimizer: [ new TerserPlugin({ terserOptions: { compress: { drop_console: true, drop_debugger: true, }, format: { comments: false, }, }, extractComments: false, }), ], splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all', }, }, }, }, module: { rules: [ { test: /\.mjs$/, include: /node_modules/, type: 'javascript/auto', resolve: { fullySpecified: false, }, }, { test: /\.(ts|tsx|js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-react', { runtime: 'automatic', development: isDev }], '@babel/preset-env', '@babel/preset-typescript' ] } } }, { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] }, { test: /\.(png|jpe?g|gif|webp|svg)$/i, type: 'asset', parser: { dataUrlCondition: { maxSize: 1024 * 1024 } } }, { exclude: /\.(js|jsx|ts|tsx|mjs|css|json|html)$/i, type: 'asset/resource' } ] }, resolve: { extensions: ['.mjs', '.ts', '.tsx', '.js', '.jsx'] }, devServer: { port: DEV_PORT, host: '0.0.0.0', allowedHosts: 'all', hot: true, historyApiFallback: true, proxy: [ { context: ['/api', '/ws'], target: `http://localhost:${process.env.GATEWAY_PORT || '8080'}`, ws: true, changeOrigin: true, }, ], }, plugins: [ new HtmlWebpackPlugin({ template: './index.html', inject: 'body', }), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'), '__APP_ENV__': JSON.stringify(isDev ? 'development' : 'production'), }), ], }; };