背景
URLSearchParmas
API 爲 URL 的查詢字符串(query string)提供了方便操作的接口,管理端的項目大多都應用了該接口,但這個 API 因爲部分瀏覽器沒有實現(如 IE 和舊版 Edge,詳見),所以引入了相應的 polyfill(github.com/WebReflection/url-search-params )進行支持,npm 包名爲 url-search-params
。
URLSearchParams
的使用方式使用詳見這裏。
存在問題
隨着2018年4月 windows 10 系統的更新發布,Edge 瀏覽器的排版引擎升級到了17,開始支持 URLSearchParams
API。但是由於存在一些 bug,而且引入的 polyfill 也沒有發現並進行處理,所以導致管理端的項目在 Edge 瀏覽器上請求時,在一定條件下會出現參數錯誤,最後導致請求失敗。
如何復現
當請求參數中,但參數值同時出現“&”符號和“ ”空格時,URLSearchParams
的 toString()
方法就會出問題。
舉個例子,下面是一個參數 q
,值爲 a & b
,預期“ ”轉爲“+”,“&”轉爲"%26" :
const params = new URLSearchParams({q: 'a & b'});
params.toString();
// 期望返回“q=a+%26+b”,Edge 17瀏覽器則返回了“q=a+&+b”
從上面結果可以看出,Edge 17沒有成功轉義“&”符,由於這個字符是用於分割參數的,這樣原本只有一個參數 q='a & b'
,但是由於沒有成功轉義”&“,就變成 q='a '
和 ' b'=''
(注意 b 前面有一個空格)兩個參數了,改變了原本的請求參數。
如何解決
解決方法
Plan A
原有 polyfill 的 GitHub 代碼內沒有對一些實現不規範的 URLSearchParams
API 進行替換處理,解決改問題需要在模塊引入前先清掉瀏覽器的 API( window.URLSearchParams
設爲 undefined
),模塊引入時就會賦予一個代碼實現的 API。
原本打算在沿用舊有的 polyfill 上,不改變舊的 npm 包,應用上述方法進行修復。但是要在引用 polyfill 之前插入一段代碼判斷,會增加了代碼耦合,所以放棄了。還有一種是直接在原有的 polyfill 代碼上改,但由於該項目用 make 命令進行構建,對此不太熟悉,並且作者已將該項目轉移到新的項目進行維護,構建方式也改了,最後就放棄了。
Plan B
原有 polyfill 由於已經轉移到新的 Github 項目進行維護(github.com/ungap/url-search-params),構建也改爲 npm 進行構建,npm 包名改爲 @ungap/url-search-params
,前面加了個 scope
。
在新的 polyfill 項目代碼中,作者這次有對不規範的 URLSearchParams
API 進行判斷和替換,這樣恰好也能在此添加 Edge 瀏覽器的判斷。
於是就可以 fork 該項目代碼修改和測試,然後給該項目提了個 pull request 給作者,很快作者就合併了代碼,併發布了新的 npm 包。
然後,先把原來的 npm 包卸載,然後替換上新的 npm 包。
# 卸載
npm uninstall --save url-search-params
# 安裝
npm install --save @ungap/url-search-params
最後,把模塊引入的代碼改下。
import URLSearchParams from 'url-search-params';
// 改爲
import URLSearchParams from '@ungap/url-search-params';
最後
最近,微軟官方宣佈 Edge 瀏覽器將放棄 EdgeHTML 內核,將採用 Chromium 內核,前端開發紛紛期待新 Edge 到來。不過時間應該還長,而且用戶升級也要時間,所以大家還是趕緊修復。