明明这三行代码没用到,我注释了之后页面却白屏了

背景

最近项目的缓存越来越混乱,各种store、localStorage、sessionStorage到处都是,维护起来简直是噩梦。于是我决定花点时间重构一下缓存逻辑,让代码更清爽一些。

事故现场

在清理代码的过程中,我打开了 文件,发现里面有一些看起来没用到的store相关代码。

我就注释了没被用到的三行代码

1. 顶部的import语句:

/* 我注释的第一行代码
 import { useVerifyStore } from '@/stores/index.js'
 */

2. beforeEnter钩子中的代码: if语句底下是原本就注释的代码,所以我看到整个文件没有对useVerifyStore去使用,心想着先给他注释了吧,结果就白屏了

{
  path: '/ticketBook',
  name: 'ticketBook',
  component: () => import('../pages/ticketBook/index.vue'),
  beforeEnter: (to, from, next) => { 
     /*这是我注释的第二行和第三行代码
     let useVerifyStoreObj = useVerifyStore() //验价store
     let { query } = to
    */
    next();
    //这是原本就注释了的代码
    // if (!useVerifyStoreObj.verifyObj.verifyRefTraceId) {//没有验价
    //    next({
    //     path: '/preloadLoading',
    //     query,
    //   });
    // } else {
    //   next();
    // }
  }
}

心想:"这些代码看起来没啥用啊,验证功能我也没在这个路由里看到相关逻辑,而且都被注释了",于是就很自然地把它们彻底删除了,也就注释了三行代码。

保存,刷新页面...

白屏!

整个应用直接挂了,控制台报错如下:

从错误信息可以看到:

  • Uncaught ReferenceError: Cannot access 'useBaggageUtils' before initialization
  • 还有一些关于事件监听器的警告

这说明模块初始化顺序出了问题,i18n在还没初始化完成时就被访问了。

排查过程

第一反应:懵逼

我当时的心情就是:???

明明只是注释了一些看起来无关紧要的代码,怎么整个应用都崩了?难道这些代码有什么魔法?

深入调查

既然问题出在这些代码上,我就开始追踪这个依赖链条:

1. router/index.js 的依赖关系

import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'
import { Base64 } from "js-base64";
import qs from 'qs'
import CurrencyAll from '@/pages/components/Currency/currency.js'
import { useVerifyStore } from '@/stores/index.js'  // 这里引入了stores
import { getEncryptionStr,getDecryptionStr } from '@/utils/index.js'
import { eventTracking } from '../server/request';
import { FlightSearchParams } from '@/utils/paramsModels.js'
import {setLangFromBrowser} from '@/utils/switchLanguage.js'  // 这里也引入了switchLanguage
import ExpiredLinkPage from '@/pages/components/ExpiredLinkPage.vue';

2. stores/index.js 的依赖关系

import { ref, computed, reactive, toRefs } from 'vue'
import { defineStore } from 'pinia'
import { handleOfferData } from '@/utils'
import axios from '@/server/axios.js'
import apis from '@/server/api'
import { Languages } from "@/utils/enums";
import { useI18n } from 'vue-i18n'
import * as vant from 'vant'
import Decimal from 'decimal.js'
import { createEsimLogic } from '@/utils/esimUtils.js'
import vantLanguage from '@/utils/vantLanguage'
import { flushLanguageCallbacks } from '@/utils/switchLanguage'  // 又引入了switchLanguage!
import { useBaggageAndOtherPoliclesStores } from './baggageAndOtherPoliclesStores'

3. utils/switchLanguage.js 的依赖关系

import { useGlobalStore, useLocalGlobalStore } from '@/stores/index.js'  // 又引回了stores!
import apis from '@/server/api.js'
import axios from '@/server/axios.js'
import { generateUUID } from '.'

4. lang/i18n.js 的依赖关系

import { createI18n } from "vue-i18n";
import {setLangFromBrowser} from '@/utils/switchLanguage.js'  // 也引入了switchLanguage
// ... 其他语言包导入

// 在初始化过程中调用
let langStore = localStorage.getItem('language');
if (langStore) {
  local = langStore
}else{
  const browserLang = navigator.language
  const langFromBrowser = setLangFromBrowser(browserLang)  // 这里调用了switchLanguage的函数
  if(langFromBrowser){
    local = langFromBrowser
  }
}

真相大白

卧槽!多重循环依赖!

依赖链条是这样的:

  1. router/index.js → stores/index.js
  2. stores/index.js → utils/switchLanguage.js
  3. utils/switchLanguage.js → stores/index.js (循环!)
  4. 同时,lang/i18n.js → utils/switchLanguage.js

原来是这样的:

  • 平时虽然存在循环依赖,但因为 router/index.js 中 useVerifyStore() 的调用,让模块初始化有了一个稳定的顺序
  • 当我注释掉 import { useVerifyStore } from '@/stores/index.js' 和 let useVerifyStoreObj = useVerifyStore() 后,模块加载顺序发生了变化
  • 某些工具函数(如useBaggageUtils)在还没初始化完成时就被访问了
  • 整个依赖链条崩塌,导致白屏

这就像是一个精妙的平衡系统,我以为自己只是拿掉了一个看似无用的零件,结果整个系统都垮了。

解决方案

实际解决方案:重构依赖结构

我的解决方法是把循环依赖的根源给切断了:

1. 创建独立的语言工具文件

setLangFromBrowser方法从switchLanguage.js中分离出来,创建一个新的languageUtils.js文件:

// 纯函数,不依赖任何store
export function setLangFromBrowser(browserLang){
  // 浏览器语言映射逻辑
  const langMapping = {
    'zh-CN': 'zh_CN',
    'zh-TW': 'zh_TW',
    'zh-HK': 'zh_TW',
    'en-US': 'en',
    'en-GB': 'en',
    'ko-KR': 'ko',
    'es-ES': 'es',
    'fr-FR': 'fr',
    'de-DE': 'de',
    'it-IT': 'it',
    'nb-NO': 'nb_NO',
    'my-MY': 'my',
    'th-TH': 'th'
  }
  
  return langMapping[browserLang] || langMapping[browserLang.split('-')[0]] || null
}

2. 修改i18n.js的引用路径

// 原来的引用(会造成循环依赖)
// import {setLangFromBrowser} from '@/utils/switchLanguage.js'

// 新的引用(从独立文件引入)
import {setLangFromBrowser} from '@/utils/languageUtils.js'

3. 打破循环依赖链

这样就彻底切断了 i18n.js → switchLanguage.js → stores/index.js 这条依赖链。

为什么这个方案有效

  • 根本性解决:不是绕过问题,而是从根源上解决了循环依赖
  • 最小改动:只需要创建一个新文件,修改一个引用路径
  • 清晰的职责分离:语言相关的纯函数独立出来,职责更清晰
  • 消除隐式依赖:不再依赖某个特定的模块加载顺序来维持稳定

教训总结

1. 看似无用的代码可能有隐藏作用

在重构时,不要轻易删除或注释看起来"无用"的代码,特别是在复杂的依赖关系中。有时候一行看似无关的代码可能在维持整个系统的平衡。

2. 循环依赖是定时炸弹

虽然JavaScript允许循环依赖,但这种设计本身就是有问题的。它让代码变得脆弱,一个小改动就可能引发连锁反应。

3. 重构要小步快跑

重构时应该:

  • 一次只改一个地方
  • 每次改动后都要测试
  • 使用版本控制,随时可以回滚
  • 理解代码的依赖关系再动手

4. 职责分离很重要

把纯函数和有副作用的函数分开,把工具函数和业务逻辑分开,这样可以大大减少不必要的依赖关系。

后续优化

这次事故让我意识到,项目的架构设计确实需要优化。后续计划:

  1. 继续梳理其他可能的循环依赖:使用工具分析整个项目的依赖图
  2. 建立更清晰的分层架构:utils层不应该依赖stores层
  3. 制定模块引用规范:避免循环依赖的编码规范
  4. 把更多的纯函数独立出来:减少不必要的依赖关系

结语

重构是好事,但要谨慎。特别是在复杂的项目中,看似简单的改动可能会触发意想不到的问题。

这次的经历告诉我:解决问题要从根源入手,不要只是绕过问题。

有时候,最简单直接的解决方案往往是最有效的!理解代码的依赖关系,比盲目地删除"无用"代码更重要。

大家觉得不错可以点点赞,收藏收藏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值