「前端 BUG 錄」變更 UI 庫主題引發的問題

linong發表於2022-05-23

最近有個專案(就叫他 P 專案)做了一次 UI 視覺統一。

之前是個小專案用的是預設主題 theme-d ,這次需求還針對性的釋出了一套 theme-p 主題。

然後出事故了,更新了主題之後我們的 dialog 顯示異常了。

使用控制檯檢視樣式

通過檢視樣式我們發現都是 UI 的樣式,並沒有我們手動覆蓋的樣式。

但是這裡有一個異常點有四個生效的樣式,正常情況是隻會有一個。但是這裡我忽略了這個問題,我以為只是有多餘的引入,或者沒有 externalspeerDependencies 導致有多個。

看上去樣式是生效了只不過效果不對,我就懷疑 theme-p 有問題,但是在文件站顯示是正常的。

那我們只能想辦法去排查這個錯誤樣式是誰引入進來的

通過控制變數法

因為樣式在頁面中都顯示 style,沒有辦法從檔名切入,所以這裡我先採用了控制變數法。

  1. main.ts 程式碼全部註釋掉
  2. main.ts 初始一個新的頁面,頁面中只渲染 dialog。
  3. 檢視效果,dialog 效果同 theme-p 文件站。
  4. main.ts 放開原始程式碼。
  5. 檢視效果,dialog 效果詭異。這個時候判斷問題出在 main.ts 中。
  6. main.ts 註釋掉一半,觀察效果。

    1. 如果效果異常,重複步驟6,再註釋掉一半。
    2. 當效果正常時,復原一半。
    3. 只到最後只保留下一行有問題的程式碼
    4. 進入到檔案中,重複步驟6。
  7. 最後就能定位到錯誤程式碼行你以為故事就結束了?這裡詭異的是我定位到了好幾個位置

    1. 第一次我定位到三方依賴中(沒完全定位,估計是被快取忽悠了)
    2. 第二次定位到了 import {dialog} from 'ui';
    3. 另一個同事定位到了我們的業務元件庫中(ui-p)。這裡也很重要,但是他介入定位比較晚,不然我們排查速度還能更快一點

這裡其實對於解決問題的幫助不太大。而且我們專案依賴巢狀嚴重,導致耗時嚴重。

大膽猜測

在我兩次定位之後,我知道這樣是無法分析出問題了,然後我給了幾個大膽的猜測。

  1. 沒有 externals,所以載入了新的樣式,導致樣式權重異常。這裡的特徵是產物中會有 css 程式碼
  2. externals,所以載入了新的樣式,導致樣式權重異常。這裡的特徵是會有明確的 require()
  3. 有地方 import 'ul.css'
  4. 沒有按需引入

在我給出猜測的時候我已經有了預感,就是因為 ui-p 用的是預設主題,並且做了 externals ,加上我們做了非同步元件,所以導致主題衝突。

加上另一個同事分析到了在 ui-p 中,所以我們接下來就是驗證是否是 ui-p 的問題。

斷點除錯

是的你沒聽錯,樣式也可以“斷點除錯”。

  1. 我們在 node_modules 先給 dialog.css 加了一行程式碼 body{background: red}
  2. 然後通過 Chrome-Devetools 中的 search 來查詢到 body{background: red} 所在的檔案
  3. 然後對程式碼進行斷點除錯
  4. 之後可以看到堆疊資訊,發現堆疊中有 ui-p

控制變數

把所有 ui-p 元件都幹掉,發現 dialog 也正常了

解決 ui-p 和主應用主題不同問題

  1. 升級 ui-ptheme-p 主題
  2. 還原 ptheme-d 主題
  3. 移除 ui-p
  4. ui-p 做名稱空間

各個方案都有問題,我們選擇了名稱空間

你以為到這裡就結束了嗎?並沒有,我將做完名稱空間的包放入專案中。還!是!有!問!題!

完了,不止一個 ui-p,接下來就重複上述的操作咯。

但是這次排查出來結果比較離譜,顯示是 common.js 載入。這使我懷疑上了另一個位置 splitChunks 異常

修改 splitChunks 策略

因為使用了 all 所以導致 asyncinitial 被合併了。這個使用 initial 其實會異常的大,因為裡面有 async 的程式碼.

所以我們只需要改成 initial 重新編譯即可。✿✿ヽ(°▽°)ノ✿ 成功了,我果然是最靚的仔。

這個時候成功條件變為了兩個,那我們需要看看是不是隻是 splitChunks 的問題,萬幸的是必須兩個都完成,才可以解決問題(我的時間沒有浪費 ?)

覆盤

  1. 做名稱空間是必須的
  2. splitChunks 應該不是必須的,只不過 dialog 並不在我的 async 中,所以我是正常的。
  3. 排查方法還需要繼續調研。上述方案比較低效

還有什麼方法可以檢視引入 css 的地方嘛?

這裡問了幾個同事,但是大家並沒有做過,也希望知道的老鐵可以留言哈

  1. webpack 是否可以?
  2. babel 是否可以?
  3. cli 的 --report 是否可以?
  4. 控制檯的斷點除錯是否可以?
  5. 壓縮前的程式碼是否有一些描述?
  6. externals,這是我能想到的一個位置。

    1. 預設的會把程式碼包含在產物中
    2. externals 會變成 require() 語句。

externals 排查

yarn build --target lib --name myLib --report

通過把調整構建目標,打出了 lib 版本的資源,的確是查到了。

但是看到之後我迷糊了,因為又是 ui-p。這裡我就徹底蒙了,因為我們專案是 monorepo 的,所以我在想是不是依賴的問題,但是我最後還是沒找到問題點。

專案&截圖

我把我在群裡的彙報截圖貼過來,感興趣可以看一下,專案的話暫時不提供復現 demo 了。

image.png

image.png

相關文章