同事報案,舉發古怪茶包一枚。

ASP.NET MVC專案新増了moment.js,在BundleConfig將其加入打包範圍[延伸閱讀]:

            bundles.Add(new ScriptBundle("~/bundles/common").Include(
                    "~/Scripts/jquery-2.1.3.js",
                    "~/Scripts/jquery.blockUI.js",
                    "~/Scripts/moment.js",
                    "~/Scripts/angular.js",
                    "~/Scripts/angular-animate.js",
                    "~/Scripts/angular-sanitize.js"));

更新簽入TFS,使用先前設計好的Build Definition,按個鈕自動部署到測試台[延伸閱讀]。不過,在DLL及JS檔案都更新後,網站卻未如預期載入moment.js。初步研判有兩種可能:moment.js沒部署成功、網站應用程式的DLL沒更新。

用瀏覽器直接連httq://test-server/myweb/scripts/moment.js確認moment.js存在,查看\bin\MyWeb.dll,檔案更新時間正確,不放心,反組譯BundleConfig確認RegisterBundles()已納入moment.js,而覆寫MyWeb.dll會重啟Application Pool,不可能還保留更新前的Cache。試著重新儲存web.config迫使網站應用程式重啟,moment.js就現身了,完全排除MyWeb.dll沒更新到的可能。至此,案情陷入膠著…

福爾摩斯轉過身,重新坐下來,在煙斗裡填上煙絲後開始吞雲吐霧,他的四周隨即飄起雲一般的青煙。彷彿過了一世紀那麼久,他終於開口說:「華生,我想我們忘了時間差…」

覆寫\bin\MyApp.dll會重啟Application Pool無庸置疑,但ScriptBundle有個特性,會自動略過不存在的js不傳回錯誤,而ScriptBundle會記住缺檔不會每次重查,補上js也不會馬上出現,需等到Cache逾時或網站程序重啟。另一方面,自動部署複製檔案是有順序的,會先複製\bin\MyApp.dll,陸續更新\Content\…,\Html\才輪到\Scripts\moment.js。這裡構成了一個時間差陷阱:若複製完MyApp.dll到moment.js寫入這段期間有使用者連上網站,ScriptBundle判定「沒有moment.js」並記憶下來,由於部署程序不包含覆寫web.config(我們採取web.config不進版控的策略,需要修改時由OP人員手動調整),於是部署結束時也更新了moment.js,但ScriptBundle停留在忽略moment.js的狀態,如此解釋前述觀察到的現象。

說到這裡,華生同事一拍大腿:「沒錯,部署期間同事D就開始用測試台驗證修正結果,的確有此可能」

為了驗證,做了個實驗:

  1. 把moment.js更名為moment_.js,修改web.config讓網站應用程式重啟,ScriptBundle吐回結果不含moment.js
  2. 將moment_.js改回moment.js,重新整理網頁,ScriptBundle仍未補上moment.js
  3. 修改web.config重啟網站應用程式,moment.js出現惹

結論:下回遇到更新ScriptBundle項目後如變更未如期出現,可再次重啟網站應用程式以排除前述時間差茶包。


Comments

Be the first to post a comment

Post a comment