vue-router的beforeEach无限循环的问题:Error: Out of stack space

本文探讨了Vue.js中使用beforeEach路由守卫时可能遇到的无限循环问题,详细解释了next('/')如何错误地重新触发beforeEach,导致堆栈溢出错误。文章最后提供了修正代码的示例。
<template> <div> <h3 text-center m-0 mb-20px>{{ t("login.login") }}</h3> <el-form ref="loginFormRef" :model="loginFormData" :rules="loginRules" size="large" :validate-on-rule-change="false"> <!-- 用户名 --> <el-form-item prop="username"> <el-input v-model.trim="loginFormData.username" :placeholder="t('login.username')"> <template #prefix> <el-icon> <User /> </el-icon> </template> </el-input> </el-form-item> <!-- 密码 --> <el-tooltip :visible="isCapsLock" :content="t('login.capsLock')" placement="right"> <el-form-item prop="password"> <el-input v-model.trim="loginFormData.password" :placeholder="t('login.password')" type="password" show-password @keyup="checkCapsLock" @keyup.enter="handleLoginSubmit"> <template #prefix> <el-icon> <Lock /> </el-icon> </template> </el-input> </el-form-item> </el-tooltip> <div class="flex-x-between w-full"> <el-checkbox v-model="loginFormData.rememberMe">{{ t("login.rememberMe") }}</el-checkbox> <el-link type="primary" underline="never" @click="toOtherForm('resetPwd')"> {{ t("login.forgetPassword") }} </el-link> </div> <!-- 登录按钮 --> <el-form-item> <el-button :loading="loading" type="primary" class="w-full" @click="handleLoginSubmit"> {{ t("login.login") }} </el-button> </el-form-item> </el-form> <div flex-center gap-10px> <el-text size="default">{{ t("login.noAccount") }}</el-text> <el-link type="primary" underline="never" @click="toOtherForm('register')"> {{ t("login.reg") }} </el-link> </div> <!-- 第三方登录 --> <div class="third-party-login"> <div class="divider-container"> <div class="divider-line"></div> <span class="divider-text">{{ t("login.otherLoginMethods") }}</span> <div class="divider-line"></div> </div> <div class="flex-center gap-x-5 w-full text-[var(--el-text-color-secondary)]"> <CommonWrapper> <div text-20px class="i-svg:wechat" /> </CommonWrapper> <CommonWrapper> <div text-20px cursor-pointer class="i-svg:qq" /> </CommonWrapper> <CommonWrapper> <div text-20px cursor-pointer class="i-svg:github" /> </CommonWrapper> <CommonWrapper> <div text-20px cursor-pointer class="i-svg:gitee" /> </CommonWrapper> </div> </div> </div> </template> <script setup lang="ts"> import type { FormInstance } from "element-plus"; import { User, Lock } from "@element-plus/icons-vue"; import { useI18n } from "vue-i18n"; import { useRoute, useRouter } from "vue-router"; import { ElMessage } from "element-plus"; // 引入核心依赖(移除 permissionStore 相关) import AuthAPI, { type LoginFormData } from "@/api/auth-api"; import { useUserStore } from "@/store"; // 仅保留用户Store import CommonWrapper from "@/components/CommonWrapper/index.vue"; import { AuthStorage } from "@/utils/auth"; import axios from "axios"; // 初始化工具实例(移除 permissionStore) const { t } = useI18n(); const userStore = useUserStore(); const route = useRoute(); const router = useRouter(); // 确保是全局正确的路由实例 // 表单核心状态(不变) const loginFormRef = ref<FormInstance>(); const loading = ref(false); const isCapsLock = ref(false); // 登录表单数据(不变) const loginFormData = ref<Omit<LoginFormData, "captchaKey" | "captchaCode">>({ username: "李四", password: "123", rememberMe: false }); // 表单验证规则(不变) const loginRules = computed(() => ({ username: [ { required: true, trigger: "blur", message: t("login.message.username.required") } ], password: [ { required: true, trigger: "blur", message: t("login.message.password.required") } ] })); /** * 登录提交(核心简化:移除动态路由逻辑,直接跳转) */ async function handleLoginSubmit() { try { const valid = await loginFormRef.value?.validate(); if (!valid) return; loading.value = true; // 1. 执行登录(存储 Token) await userStore.login(loginFormData.value); console.log("登录成功,表单数据:", loginFormData.value); // 2. 获取 Token 并校验(确保登录状态有效) const token = AuthStorage.getAccessToken(); if (!token) { throw new Error("Token 存储失败,请重试"); } console.log("当前 Token:", token); // 3. (可选)获取用户信息(仅存信息,不依赖其菜单) const infoRes = await axios({ url: "http://10.170.1.104:8978/admin/admin/info", method: "get", headers: { "Authorization": token } }); if (infoRes.data.code !== 200) { throw new Error(`获取用户信息失败:${infoRes.data.msg || "未知错误"}`); } console.log("用户信息:", infoRes.data.data); // 仅打印,不用于路由 // 4. 确定跳转路径(简化:redirect参数优先,无则跳首页) let redirectPath = "/"; // 兜底跳首页(静态路由,确保存在) // 如果有 redirect 参数(如之前访问 /dashboard 被拦截),则跳该路径 if (route.query.redirect && typeof route.query.redirect === "string") { const decodedRedirect = decodeURIComponent(route.query.redirect); // 仅允许跳静态路由中的路径(避免无效路径) const validStaticPaths = ["/", "/dashboard", "/profile"]; // 替换为你的静态路由路径 if (validStaticPaths.includes(decodedRedirect)) { redirectPath = decodedRedirect; } console.log("使用 redirect 参数跳转:", redirectPath); } console.log("最终跳转路径:", redirectPath); // // 5. 直接跳转(移除所有动态路由相关干扰) // await router.replace(redirectPath); // ElMessage.success("登录成功,已进入系统"); // 5. 直接跳转(添加详细日志) console.log("准备执行跳转,路由实例:", router); console.log("router.replace 方法是否存在:", typeof router.replace === "function"); console.log("跳转路径是否为字符串:", typeof redirectPath === "string"); try { console.log("开始执行 router.replace,路径:", redirectPath); const result = await router.replace(redirectPath); console.log("router.replace 执行成功,返回结果:", result); ElMessage.success("登录成功,已进入系统"); } catch (error) { console.error("router.replace 执行失败,错误详情:", error); // console.error("错误名称:", error.name); // console.error("错误消息:", error.message); // console.error("错误堆栈:", jumpError.stack); // ElMessage.error("跳转失败:" + jumpError.message); } } catch (error: any) { // 错误详情打印(便于排查) console.error("登录跳转失败详情:", { message: error.message, statusCode: error.response?.status, responseData: error.response?.data, requestUrl: error.response?.config?.url }); // 用户友好提示 const errorMsg = error.response?.data?.msg || error.message || "登录失败,请联系管理员"; ElMessage.error(errorMsg); } finally { loading.value = false; } } // 大写锁定检查(不变) function checkCapsLock(event: KeyboardEvent) { isCapsLock.value = event.getModifierState("CapsLock"); } // 切换表单(不变) const emit = defineEmits(["update:modelValue"]); function toOtherForm(type: "register" | "resetPwd") { emit("update:modelValue", type); } </script> <style lang="scss" scoped> .third-party-login { .divider-container { display: flex; align-items: center; margin: 40px 0; .divider-line { flex: 1; height: 1px; background: linear-gradient(to right, transparent, var(--el-border-color-light), transparent); } .divider-text { padding: 0 16px; font-size: 12px; color: var(--el-text-color-regular); white-space: nowrap; } } } </style> import { createApp } from "vue"; import App from "./App.vue"; import setupPlugins from "@/plugins"; // 导入router import router from "@/router"; // 暗黑主题样式 import "element-plus/theme-chalk/dark/css-vars.css"; import "vxe-table/lib/style.css"; // 暗黑模式自定义变量 import "@/styles/dark/css-vars.css"; import "@/styles/index.scss"; import "uno.css"; // 过渡动画 import "animate.css"; // 自动为某些默认事件(如 touchstart、wheel 等)添加 { passive: true },提升滚动性能并消除控制台的非被动事件监听警告 import "default-passive-events"; const app = createApp(App); // 注册插件 app.use(setupPlugins); app.use(router); app.mount("#app"); // src/router/index.ts import type { App } from "vue"; // ✅ 从 vue 导入 App 类型 import type { RouteRecordRaw } from "vue-router"; // ✅ RouteRecordRaw 仍从 vue-router 导入 import { createRouter, createWebHashHistory } from "vue-router"; // 1. 导入静态路由(根据你的项目实际路由调整,若没有单独文件可直接定义) const constantRoutes: RouteRecordRaw[] = [ { path: "/login", component: () => import("@/views/login/index.vue"), meta: { hidden: true }, }, { path: "/404", component: () => import("@/views/error/404.vue"), meta: { hidden: true }, }, { path: "/test-jump", name: "TestJump", component: () => import("../views/test/TestJump.vue"), // 新建空白组件 meta: { hidden: true }, }, { path: "/", component: () => import("@/layouts/index.vue"), // 你的布局组件路径 redirect: "/dashboard", children: [ { path: "dashboard", component: () => import("@/views/dashboard/index.vue"), // 你的首页路径 meta: { title: "首页", icon: "home" }, }, ], }, ]; // 2. 创建路由实例(这里用 hash 模式,避免后端配置,适合开发) const router = createRouter({ history: createWebHashHistory(), // 若用 history 模式,需改 createWebHistory() routes: constantRoutes, scrollBehavior: () => ({ left: 0, top: 0 }), // 跳转后滚动到顶部 }); // 3. 全局注册路由的方法(供 main.ts 使用) export function setupRouter(app: App<Element>) { app.use(router); } // 4. 关键:添加默认导出!!!(解决“不提供 default 导出”的核心) export default router; // 可选:保留命名导出(方便需要显式导入的场景,非必需) export { router, constantRoutes }; 为什么不能执行const result = await router.replace(redirectPath);,进行安全跳转
10-17
error in ./src/components/index/IndexAsideStatic.vue?vue&type=style&index=0&id=0175fa3e&lang=scss&scoped=true& Module build failed (from ./node_modules/sass-loader/dist/cjs.js): Error: Cannot find module 'node-sass' Require stack: - E:\bishezuihzongban\daima\admin\node_modules\sass-loader\dist\getDefaultSassImplementation.js - E:\bishezuihzongban\daima\admin\node_modules\sass-loader\dist\getSassImplementation.js - E:\bishezuihzongban\daima\admin\node_modules\sass-loader\dist\index.js - E:\bishezuihzongban\daima\admin\node_modules\sass-loader\dist\cjs.js - E:\bishezuihzongban\daima\admin\node_modules\loader-runner\lib\loadLoader.js - E:\bishezuihzongban\daima\admin\node_modules\loader-runner\lib\LoaderRunner.js - E:\bishezuihzongban\daima\admin\node_modules\webpack\lib\NormalModule.js - E:\bishezuihzongban\daima\admin\node_modules\webpack\lib\NormalModuleFactory.js - E:\bishezuihzongban\daima\admin\node_modules\webpack\lib\Compiler.js - E:\bishezuihzongban\daima\admin\node_modules\webpack\lib\webpack.js - E:\bishezuihzongban\daima\admin\node_modules\@vue\cli-service\lib\commands\serve.js - E:\bishezuihzongban\daima\admin\node_modules\@vue\cli-service\lib\Service.js - E:\bishezuihzongban\daima\admin\node_modules\@vue\cli-service\bin\vue-cli-service.js at Function.Module._resolveFilename (internal/modules/cjs/loader.js:931:15) at Function.Module._load (internal/modules/cjs/loader.js:774:27) at Module.require (internal/modules/cjs/loader.js:1003:19) at require (internal/modules/cjs/helpers.js:107:18) at getDefaultSassImplementation (E:\bishezuihzongban\daima\admin\node_modules\sass-loader\dist\getDefaultSassImplementation.js:24:10) at getSassImplementation (E:\bishezuihzongban\daima\admin\node_modules\sass-loader\dist\getSassImplementation.js:19:72) at Object.loader (E:\bishezuihzongban\daima\admin\node_modules\sass-loader\dist\index.js:40:61) @ ./node_modules/vue-style-loader??ref--8-oneOf-1-0!./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/ postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/index/IndexAsideStatic.vue?vue&type=style&index=0&id=0175fa3e&lang=scss&scoped=true& 4:14-489 14:3-18:5 15:22-497 @ ./src/components/index/IndexAsideStatic.vue?vue&type=style&index=0&id=0175fa3e&lang=scss&scoped=true& @ ./src/components/index/IndexAsideStatic.vue @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/index.vue?vue&type=script&lang=js& @ ./src/views/index.vue?vue&type=script&lang=js& @ ./src/views/index.vue @ ./src/router/router-static.js @ ./src/main.js @ multi (webpack)-dev-server/client?http://172.20.10.6:8081/sockjs-node (webpack)/hot/dev-server.js ./src/main.js
06-12
PS D:\zhWork\202501gsykj\website-kjcg> npm run dev > results-manage@0.1.0 dev D:\zhWork\202501gsykj\website-kjcg > vue-cli-service serve Browserslist: caniuse-lite is outdated. Please run: npx update-browserslist-db@latest Why you should do it regularly: https://github.com/browserslist/update-db#readme INFO Starting development server... [24%] building (3/7 modules) [24%] building (5/151 modules) [BABEL] Note: The code generator has deoptimised the styling of D:\zhWork\202501gsykj\website-kjcg\node_modules\element-ui\lib\element-ui.common.js as it exceeds the[51%] building (807/2570 modules) <--- Last few GCs ---> [16848:000001C56D82D290] 63788 ms: Mark-sweep (reduce) 4087.5 (4101.6) -> 4087.0 (4103.1) MB, 629.4 / 0.0 ms (average mu = 0.204, current mu = 0.008) allocation failure scavenge might not succeed [16848:000001C56D82D290] 64421 ms: Mark-sweep (reduce) 4088.0 (4102.1) -> 4087.5 (4103.6) MB, 627.9 / 0.0 ms (average mu = 0.115, current mu = 0.008) allocation failure scavenge might not succeed <--- JS stacktrace ---> FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory 1: 00007FF62825412F napi_wrap+133311 2: 00007FF6281EDD06 SSL_get_quiet_shutdown+63062 3: 00007FF6281EEB9D node::OnFatalError+301 4: 00007FF628AD19CE v8::Isolate::ReportExternalAllocationLimitReached+94 5: 00007FF628AB67BD v8::SharedArrayBuffer::Externalize+781 6: 00007FF62895FFCC v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1516 7: 00007FF62894AA4B v8::internal::NativeContextInferrer::Infer+59739 8: 00007FF62892FD1F v8::internal::MarkingWorklists::SwitchToContextSlow+56975 9: 00007FF628943A0B v8::internal::NativeContextInferrer::Infer+31003 10: 00007FF62893AAED v8::internal::MarkCompactCollector::EnsureSweepingCompleted+6285 11: 00007FF628942C5E v8::internal::NativeContextInferrer::Infer+27502 12: 00007FF628946CAB v8::internal::NativeContextInferrer::Infer+43963 13: 00007FF6289506A2 v8::internal::ItemParallelJob::Task::RunInternal+18 14: 00007FF628950631 v8::internal::ItemParallelJob::Run+641 15: 00007FF628923C93 v8::internal::MarkingWorklists::SwitchToContextSlow+7683 16: 00007FF62893AF9C v8::internal::MarkCompactCollector::EnsureSweepingCompleted+7484 17: 00007FF6289397D4 v8::internal::MarkCompactCollector::EnsureSweepingCompleted+1396 18: 00007FF628937348 v8::internal::MarkingWorklists::SwitchToContextSlow+87224 19: 00007FF628965DB1 v8::internal::Heap::LeftTrimFixedArray+929 20: 00007FF628967EA5 v8::internal::Heap::PageFlagsAreConsistent+789 21: 00007FF62895D0C1 v8::internal::Heap::CollectGarbage+2049 22: 00007FF62895B2C5 v8::internal::Heap::AllocateExternalBackingStore+1349 23: 00007FF628975155 v8::internal::GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact+1029 24: 00007FF6289755A5 v8::internal::Factory::AllocateRaw+37 25: 00007FF62898AC9E v8::internal::FactoryBase<v8::internal::Factory>::NewStruct+94 26: 00007FF628983A95 v8::internal::Factory::NewStackTraceFrame+53 27: 00007FF6289AD0E2 v8::internal::Isolate::CaptureSimpleStackTrace+2354 28: 00007FF6289AC971 v8::internal::Isolate::CaptureSimpleStackTrace+449 29: 00007FF6289AC0BD v8::internal::Isolate::CaptureAndSetSimpleStackTrace+45 30: 00007FF6289A28A0 v8::internal::MessageLocation::MessageLocation+3664 31: 00007FF6289A63BC v8::internal::MessageFormatter::Format+13100 32: 00007FF62897ADB6 v8::internal::Factory::NewError+134 33: 00007FF628984AF2 v8::internal::Factory::NewTypeError+162 34: 00007FF6289A6561 v8::internal::MessageHandler::MakeMessageObject+337 35: 00007FF6286ABF7C v8::internal::interpreter::JumpTableTargetOffsets::iterator::operator=+9596 36: 00007FF628B5CDFD v8::internal::SetupIsolateDelegate::SetupHeap+474253 37: 00007FF628AED1C9 v8::internal::SetupIsolateDelegate::SetupHeap+16473 38: 00007FF628AF2FC2 v8::internal::SetupIsolateDelegate::SetupHeap+40530 39: 0000007021B7AE30 npm ERR! code ELIFECYCLE npm ERR! errno 134 npm ERR! results-manage@0.1.0 dev: `vue-cli-service serve` npm ERR! Exit status 134 npm ERR! npm ERR! Failed at the results-manage@0.1.0 dev script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! D:\softwareInstall\nvmInstall\nodejs\node_cache\_logs\2025-07-19T14_07_13_559Z-debug.log
07-20
<think>我们正在处理一个关于Vite项目在构建或运行时出现"Maximum call stack size exceeded"错误的问题。根据提供的引用和用户的问题,我们可以总结以下几点: 1. 该错误通常表示递归调用过深,导致调用栈溢出。 2. 在Vue项目中,这可能是由以下原因引起的: - 在计算属性(computed)中使用了递归,且递归没有正确终止(如引用[3]所示)。 - 在模板中可能存在循环引用或无限循环的渲染(如引用[1]中的输入处理可能引起的问题,但更可能是递归组件)。 - 在路由守卫中出现了无限循环(如引用[4]所示)。 3. 该错误在本地开发环境可能不会出现,但在生产构建时出现,可能是因为生产构建的代码优化和压缩使得调用栈更深,或者生产模式下的严格性更高。 根据用户的问题,我们关注的是Vite项目(Vite是一个现代前端构建工具)。Vite在生产构建时使用Rollup,而开发环境下使用ES模块加载,因此生产构建和开发环境的行为可能不同。 解决思路: 1. **检查递归函数**:查看项目中是否有递归函数(特别是在计算属性、方法或生命周期钩子中),并确保递归有正确的终止条件。引用[3]提到在computed中使用了递归,并且线上打包后出现问题。 2. **检查循环依赖**:组件之间的循环引用可能导致无限递归。例如,组件A引用了组件B,而组件B又引用了组件A,这可能会导致栈溢出。 3. **检查路由守卫**:在路由守卫中,如果没有正确调用next()或跳转条件设置不当,可能会导致无限循环(如引用[4]所示)。 4. **检查自定义指令**:引用[1]中有一个自定义指令`v-wxInput`,它可能在内部实现中引起了递归。检查自定义指令中是否有可能导致无限循环的逻辑。 5. **检查打包配置**:引用[2]提到npm前端项目编译时栈溢出,虽然背景是vue+elementui和jenkins,但我们可以参考其处理方案:尝试清除缓存、升级依赖、增加Node.js内存限制等。 具体步骤: ### 1. 定位递归或循环 - 检查所有计算属性(computed)中是否有递归操作,并确保递归终止条件正确。 - 检查是否有递归组件(即组件在模板中调用自身)且没有终止条件。在Vue中,递归组件必须有终止条件(如v-if)。 ### 2. 检查路由 - 在路由守卫中,确保不会出现无限重定向。例如: ```javascript router.beforeEach((to, from, next) => { if (to.path === '/some-path' && !isAuthenticated) { next('/login'); } else { next(); // 不要忘记调用next,否则会卡住 } }); ``` 如果条件设置不当,可能会导致循环跳转。 ### 3. 检查自定义指令 - 如果使用了自定义指令(如引用[1]中的`v-wxInput`),检查其实现,确保没有无限循环。例如,在指令的更新钩子中修改了绑定的值,而该值又会触发指令更新,形成循环。 ### 4. 增加Node.js内存限制(针对构建时错误) - 如果错误发生在构建阶段(如vite build),可以尝试增加Node.js的内存限制。在package.json的脚本中: ```json "scripts": { "build": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build" } ``` 这里将内存限制增加到4GB(4096MB),根据情况可以调整。 ### 5. 更新依赖 - 确保所有依赖(特别是Vite、Vue、插件等)都是最新版本,因为可能是一个已知问题已被修复。 ### 6. 检查循环依赖 - 使用工具检测循环依赖。例如,使用`npm ls`或专门的循环依赖检测包(如`madge`)。安装madge: ``` npm install -g madge ``` 然后在项目根目录运行: ``` madge --circular src/ ``` ### 7. 简化代码,定位问题 - 如果以上方法无法定位,可以尝试注释掉部分代码,逐步排查是哪个部分导致的问题。 ### 示例解决方案 假设我们在计算属性中发现了一个递归函数,如下: ```javascript const list = computed(() => { return parseList(props.list); // 假设parseList是一个递归函数 }); ``` 我们需要检查`parseList`函数,确保它不会无限递归。例如,如果`parseList`处理树形结构,应该设置递归深度限制或确保数据没有循环引用。 ### 总结 由于该错误在本地不出现而在生产构建后出现,最可能的原因是生产构建时的代码优化(如函数内联)导致调用栈深度增加。因此,重点检查递归函数和循环依赖。 根据引用和Vite的特点,我们给出以下解决方案: 1. 检查并修复递归函数(特别是计算属性中的递归)。 2. 检查路由守卫,避免无限循环。 3. 检查自定义指令。 4. 增加Node.js内存限制(针对构建时错误)。 5. 更新依赖。 6. 使用工具检测循环依赖。 希望这些步骤能帮助您解决问题。 §§相关问题§§ 1. 如何增加Node.js的内存限制? 2. 如何在Vue中避免递归组件导致的无限循环? 3. 如何检测前端项目中的循环依赖? 4. Vue3中计算属性的使用有哪些注意事项? 5. Vite构建过程中常见的性能优化有哪些? </think> ### 解决 Vite 出现 "Maximum call stack size exceeded" 错误的方法 该错误表示**调用栈溢出**,通常由以下原因引起: #### 1. **递归函数未正确终止(最常见原因)** - 检查所有递归函数(尤其是 `computed`/`watch` 中的逻辑) - 确保递归有明确的终止条件 - 示例修复(参考引用[3]): ```javascript // 错误示例:递归未终止 const recursiveFn = (data) => { return data.map(item => { if (item.children) { return recursiveFn(item.children) // 可能导致无限递归 } return item }) } // 正确示例:添加终止条件 const recursiveFn = (data) => { if (!data || data.length === 0) return [] // 终止条件 return data.map(/* ... */) } ``` #### 2. **组件循环引用** - 当组件 A 导入组件 B,同时组件 B 又导入组件 A 时 - 解决方案: ```javascript // 使用异步组件解决循环引用 export default { components: { CompB: () => import('./CompB.vue') // 延迟加载 } } ``` #### 3. **路由守卫死循环**(参考引用[4]) - 在路由守卫中确保跳转逻辑不会循环触发: ```javascript router.beforeEach((to, from, next) => { if (to.path === '/login' && isLoggedIn) { next('/dashboard') // ✅ 正确跳转 // 错误示例: next('/login') 会导致循环 } else { next() } }) ``` #### 4. **内存优化配置(构建阶段错误)** 在 `vite.config.js` 中增加内存限制(参考引用[2]): ```javascript // vite.config.js export default { build: { chunkSizeWarningLimit: 2000, // 提高块大小警告阈值(默认500KB) sourcemap: false // 禁用 sourcemap 减少内存 } } ``` #### 5. **依赖项问题** - 升级 Vite 和插件版本: ```bash npm update vite @vitejs/plugin-vue ``` - 清除缓存并重装依赖: ```bash rm -rf node_modules/.vite npm install ``` > **关键提示**:该错误在开发环境可能不出现,但在生产构建时触发,因为: > 1. 生产构建会进行代码优化/压缩,改变调用栈深度 > 2. 生产环境的路由懒加载等机制可能暴露递归问题[^3] > 3. 生产构建过程本身需要更多内存资源[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值