You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack 5+React项目使用<Routes/>组件触发浏览器内存溢出问题

问题描述

我有一个基于Webpack 5和React的项目,当不使用*

return (<Routes/>)
*组件时,执行npm run dev启动项目一切正常,但一旦使用该组件,浏览器就会显示“Out of Memory”错误,而启动npm脚本的控制台无任何报错。我已尝试过node --max-old-space-size=x命令,当前环境为node v18.16.0、npm 9.5.1。

项目配置文件

package.json

{
    "name": "client",
    "version": "1.0.0",
    "private": true,
    "type": "commonjs",
    "scripts": {
        "dev": "cross-env NODE_ENV=development webpack serve --mode development --open",
        "build": "cross-env NODE_ENV=production webpack --mode production",
        "stats": "webpack --json > stats.json && webpack-bundle-analyzer stats.json",
        "lint": "eslint ./src"
    },
    "engines": {
        "node": ">= 6.0.0",
        "npm": ">= 3.0.0"
    },
    "browserslist": [
        "> 1%",
        "last 2 versions",
        "not ie <= 8"
    ],
    "author": "Pasha Makarenko",
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "latest",
        "@babel/eslint-parser": "latest",
        "@babel/polyfill": "latest",
        "@babel/preset-env": "latest",
        "@babel/preset-react": "latest",
        "@babel/preset-typescript": "latest",
        "@reduxjs/toolkit": "latest",
        "@types/react": "latest",
        "@types/react-dom": "latest",
        "@types/react-router-dom": "latest",
        "@types/webpack-env": "latest",
        "@typescript-eslint/eslint-plugin": "latest",
        "@typescript-eslint/parser": "latest",
        "autoprefixer": "latest",
        "babel-loader": "latest",
        "clean-webpack-plugin": "latest",
        "copy-webpack-plugin": "latest",
        "cross-env": "latest",
        "css-loader": "latest",
        "css-minimizer-webpack-plugin": "latest",
        "csv-loader": "latest",
        "eslint": "latest",
        "eslint-plugin-jsx-a11y": "latest",
        "eslint-plugin-react": "latest",
        "eslint-webpack-plugin": "latest",
        "file-loader": "latest",
        "html-loader": "latest",
        "html-webpack-plugin": "latest",
        "imagemin": "latest",
        "imagemin-webp": "latest",
        "imagemin-webp-webpack-plugin": "latest",
        "mini-css-extract-plugin": "latest",
        "node-sass": "latest",
        "postcss": "latest",
        "postcss-loader": "latest",
        "sass": "latest",
        "sass-loader": "latest",
        "style-loader": "latest",
        "terser-webpack-plugin": "latest",
        "thread-loader": "latest",
        "ts-loader": "latest",
        "typescript": "^5.0.4",
        "webpack": "latest",
        "webpack-bundle-analyzer": "latest",
        "webpack-cli": "latest",
        "webpack-dev-middleware": "latest",
        "webpack-dev-server": "latest",
        "webpack-merge": "latest",
        "webpackbar": "latest",
        "xml-loader": "latest"
    },
    "dependencies": {
        "react": "latest",
        "react-dom": "latest",
        "react-redux": "latest",
        "react-router-dom": "latest",
        "redux": "latest",
        "redux-devtools-extension": "latest",
        "redux-thunk": "latest"
    }
}

Webpack配置文件

webpack.config.js

const { merge } = require("webpack-merge"),
    common = require("./webpack/webpack.common.js"),
    envs = {
        development: "dev",
        production: "prod"
    },
    env = envs[process.env.NODE_ENV || "development"],
    envConfig = require(`./webpack/webpack.${env}.js`),
    dirname = __dirname

module.exports = env => merge(common(env, dirname), envConfig(dirname))

webpack.common.js

const path = require("path"),
    os = require("os"),
    HTMLWebpackPlugin = require("html-webpack-plugin"),
    CopyWebpackPlugin = require("copy-webpack-plugin"),
    MiniCssExtractPlugin = require("mini-css-extract-plugin"),
    { CleanWebpackPlugin } = require("clean-webpack-plugin")

module.exports = (env, dirname) => {
    const isDev = env === "development",
        isProd = env === "production",
        filename = ext => isDev ? `[name]${ext}` : `[name].[contenthash]${ext}`,
        cssLoader = loader => {
            const config = [
                isDev ? "style-loader" : {
                    loader: MiniCssExtractPlugin.loader,
                    options: {
                        publicPath: "../"
                    },
                },
                {
                    loader: "css-loader",
                    options: {
                        esModule: true,
                        importLoaders: 1,
                        modules: {
                            mode: "icss"
                        }
                    }
                },
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: isProd ? [
                                ["autoprefixer"]
                            ] : []
                        }
                    }
                }
            ]

            if (loader) config.push(loader)

            return config
        },
        jsLoader = loader => {
            const config = [
                {
                    loader: "thread-loader",
                    options: {
                        poolTimeout: 2000,
                        workers: os.cpus().length - 1
                    }
                },
                {
                    loader: "babel-loader",
                    options: {
                        presets: isProd ? ["@babel/preset-env", "@babel/preset-react"] : []
                    }
                }
            ]

            if (loader) config.push(loader)

            return config
        },
        plugins = () => [
            new HTMLWebpackPlugin({
                template: "./index.html",
                inject: "body",
                minify: {
                    collapseWhitespace: isProd
                }
            }),
            new CleanWebpackPlugin(),
            new CopyWebpackPlugin({
                patterns: [
                    {
                        from: path.resolve(dirname, "src/favicon.ico"),
                        to: path.resolve(dirname, "dist")
                    },
                    {
                        from: path.resolve(dirname, ".gitignore"),
                        to: path.resolve(dirname, "dist")
                    }
                ]
            }),
            new MiniCssExtractPlugin({
                filename: `css/${filename(".css")}`
            })
        ]

    return ({
        context: path.resolve(dirname, "src"),
        cache: true,
        entry: {
            main: ["@babel/polyfill", "./ts/index.ts"]
        },
        output: {
            filename: `${filename(".js")}`,
            path: path.resolve(dirname, "dist"),
            assetModuleFilename: "[path][name][ext]",
            clean: true
        },
        resolve: {
            extensions: [".js", ".ts", ".jsx", ".tsx", ".json"],
            alias: {
                "@": path.resolve(dirname, "src")
            }
        },
        optimization: {
            minimize: true,
            runtimeChunk: 'single',
            splitChunks: {
                chunks: 'all',
                maxInitialRequests: Infinity,
                minSize: 0,
                cacheGroups: {
                    vendor: {
                        test: /[\\/]node_modules[\\/]/,
                        name(module) {
                            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/) ?? 'package';
                            return `npm.${packageName[1].replace('@', '')}`;
                        }
                    }
                }
            }
        },
        plugins: plugins(),
        module: {
            rules: [
                {
                    test: /\.m?jsx?$/,
                    exclude: /node_modules/,
                    use: jsLoader()
                },
                {
                    test: /\.tsx?$/,
                    exclude: /node_modules/,
                    use: jsLoader({
                        loader: "ts-loader",
                        options: {
                            projectReferences: true,
                            happyPackMode: true,
                            transpileOnly: true
                        }
                    })
                },
                {
                    test: /\.css$/,
                    use: cssLoader()
                },
                {
                    test: /\.s[ac]ss$/,
                    use: cssLoader("sass-loader")
                },
                {
                    test: /\.html$/,
                    include: path.resolve(dirname, 'src/html/'),
                    use: "html-loader"
                },
                {
                    test: /\.(ico|png|jpg|jpeg|svg|gif|mp4|webp|webm)$/,
                    type: "asset/resource",
                    generator: {
                        filename: `./img/${filename("[ext]")}`
                    },
                },
                {
                    test: /\.(ttf|woff|woff2|otf|eot)$/,
                    type: "asset/inline",
                    generator: {
                        filename: `./fonts/${filename("[ext]")}`
                    }
                },
                {
                    test: /\.xml$/,
                    use: ["xml-loader"]
                },
                {
                    test: /\.csv$/,
                    use: ["csv-loader"]
                }
            ]
        }
    })
}

webpack.dev.js

const path = require("path"),
    ESLintWebpackPlugin = require("eslint-webpack-plugin"),
    WebpackBar = require("webpackbar"),
    { HotModuleReplacementPlugin } = require("webpack")

module.exports = (dirname) => ({
    mode: "development",
    target: "web",
    devtool: "eval-source-map",
    devServer: {
        compress: true,
        port: 3000,
        open: true,
        watchFiles: path.join(dirname, "/src"),
        historyApiFallback: true,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "*",
            "Access-Control-Allow-Headers": "*",
        },
        client: {
            overlay: false
        }
    },
    optimization: {
        usedExports: true
    },
    plugins: [
        new HotModuleReplacementPlugin(),
        new ESLintWebpackPlugin({
            extensions: ["js", "ts", "jsx", "tsx"],
            failOnError: false
        }),
        new WebpackBar()
    ]
})

内容的提问来源于stack exchange,提问作者Паша Макаренко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 04:44:55