const path = require('path'); const webpack = require('webpack'); const { BundleAnalyzerPlugin } = process.env.ANALYZE ? require('webpack-bundle-analyzer') : { BundleAnalyzerPlugin: null }; module.exports = { webpack: { configure: (webpackConfig, { env, paths }) => { // ============== 持久化缓存配置 ============== // 大幅提升二次构建速度(可提升 50-80%) webpackConfig.cache = { type: 'filesystem', cacheDirectory: path.resolve(__dirname, 'node_modules/.cache/webpack'), buildDependencies: { config: [__filename], }, // 增加缓存有效性检查 name: env === 'production' ? 'production' : 'development', compression: env === 'production' ? 'gzip' : false, }; // ============== 生产环境优化 ============== if (env === 'production') { // 高级代码分割策略 webpackConfig.optimization = { ...webpackConfig.optimization, splitChunks: { chunks: 'all', maxInitialRequests: 30, minSize: 20000, maxSize: 244000, // 限制单个 chunk 最大大小(约 244KB) cacheGroups: { // React 核心库单独分离 react: { test: /[\\/]node_modules[\\/](react|react-dom|react-router-dom)[\\/]/, name: 'react-vendor', priority: 30, reuseExistingChunk: true, }, // 大型图表库分离(echarts, d3, apexcharts 等) charts: { test: /[\\/]node_modules[\\/](echarts|echarts-for-react|apexcharts|react-apexcharts|recharts|d3|d3-.*)[\\/]/, name: 'charts-lib', priority: 25, reuseExistingChunk: true, }, // Chakra UI 框架 chakraUI: { test: /[\\/]node_modules[\\/](@chakra-ui|@emotion)[\\/]/, name: 'chakra-ui', priority: 22, reuseExistingChunk: true, }, // Ant Design antd: { test: /[\\/]node_modules[\\/](antd|@ant-design)[\\/]/, name: 'antd-lib', priority: 22, reuseExistingChunk: true, }, // 3D 库(three.js) three: { test: /[\\/]node_modules[\\/](three|@react-three)[\\/]/, name: 'three-lib', priority: 20, reuseExistingChunk: true, }, // 日期/日历库 calendar: { test: /[\\/]node_modules[\\/](moment|date-fns|@fullcalendar|react-big-calendar)[\\/]/, name: 'calendar-lib', priority: 18, reuseExistingChunk: true, }, // 其他第三方库 vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: 10, reuseExistingChunk: true, }, // 公共代码 common: { minChunks: 2, priority: 5, reuseExistingChunk: true, name: 'common', }, }, }, // 优化运行时代码 runtimeChunk: 'single', // 使用确定性的模块 ID moduleIds: 'deterministic', // 最小化配置 minimize: true, }; // 生产环境禁用 source map 以加快构建(可节省 40-60% 时间) webpackConfig.devtool = false; } else { // 开发环境使用更快的 source map webpackConfig.devtool = 'eval-cheap-module-source-map'; } // ============== 模块解析优化 ============== webpackConfig.resolve = { ...webpackConfig.resolve, alias: { ...webpackConfig.resolve.alias, // 根目录别名 '@': path.resolve(__dirname, 'src'), // 功能模块别名(按字母顺序) '@assets': path.resolve(__dirname, 'src/assets'), '@components': path.resolve(__dirname, 'src/components'), '@constants': path.resolve(__dirname, 'src/constants'), '@contexts': path.resolve(__dirname, 'src/contexts'), '@data': path.resolve(__dirname, 'src/data'), '@hooks': path.resolve(__dirname, 'src/hooks'), '@layouts': path.resolve(__dirname, 'src/layouts'), '@lib': path.resolve(__dirname, 'src/lib'), '@mocks': path.resolve(__dirname, 'src/mocks'), '@providers': path.resolve(__dirname, 'src/providers'), '@routes': path.resolve(__dirname, 'src/routes'), '@services': path.resolve(__dirname, 'src/services'), '@store': path.resolve(__dirname, 'src/store'), '@styles': path.resolve(__dirname, 'src/styles'), '@theme': path.resolve(__dirname, 'src/theme'), '@utils': path.resolve(__dirname, 'src/utils'), '@variables': path.resolve(__dirname, 'src/variables'), '@views': path.resolve(__dirname, 'src/views'), }, // 减少文件扩展名搜索 extensions: ['.js', '.jsx', '.json'], // 优化模块查找路径 modules: [ path.resolve(__dirname, 'src'), 'node_modules' ], // 优化符号链接解析 symlinks: false, }; // ============== 插件优化 ============== // 移除 ESLint 插件以提升构建速度(可提升 20-30%) webpackConfig.plugins = webpackConfig.plugins.filter( plugin => plugin.constructor.name !== 'ESLintWebpackPlugin' ); // 添加打包分析工具(通过 ANALYZE=true 启用) if (env === 'production' && process.env.ANALYZE && BundleAnalyzerPlugin) { webpackConfig.plugins.push( new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: true, reportFilename: 'bundle-report.html', }) ); } // 忽略 moment 的语言包(如果项目使用了 moment) webpackConfig.plugins.push( new webpack.IgnorePlugin({ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/, }) ); // ============== Loader 优化 ============== const babelLoaderRule = webpackConfig.module.rules.find( rule => rule.oneOf ); if (babelLoaderRule && babelLoaderRule.oneOf) { babelLoaderRule.oneOf.forEach(rule => { // 优化 Babel Loader if (rule.loader && rule.loader.includes('babel-loader')) { rule.options = { ...rule.options, cacheDirectory: true, cacheCompression: false, compact: env === 'production', }; // 限制 Babel 处理范围 rule.include = path.resolve(__dirname, 'src'); rule.exclude = /node_modules/; } // 优化 CSS Loader if (rule.use && Array.isArray(rule.use)) { rule.use.forEach(loader => { if (loader.loader && loader.loader.includes('css-loader') && loader.options) { loader.options.sourceMap = env !== 'production'; } }); } }); } // ============== 性能提示配置 ============== webpackConfig.performance = { hints: env === 'production' ? 'warning' : false, maxEntrypointSize: 512000, // 512KB maxAssetSize: 512000, }; return webpackConfig; }, }, // ============== Babel 配置优化 ============== babel: { plugins: [ // 运行时辅助函数复用 ['@babel/plugin-transform-runtime', { regenerator: true, useESModules: true, }], ], loaderOptions: { cacheDirectory: true, cacheCompression: false, }, }, // ============== 开发服务器配置 ============== devServer: { hot: true, port: 3000, compress: true, client: { overlay: false, progress: true, }, // 优化开发服务器性能 devMiddleware: { writeToDisk: false, }, // 代理配置:将 /api 请求代理到后端服务器 proxy: { '/api': { target: 'http://49.232.185.254:5001', changeOrigin: true, secure: false, logLevel: 'debug', }, }, }, };