程式上線到UAT環境,因knockout.mapping未載入出錯,但在測試環境是好的。經過一番測試比對,發現犯了一個低級錯誤:
bundles.Add(new ScriptBundle("~/bundles/ko").Include(
"~/Scripts/knockout-3.0.0.js",
"~/Scripts/knockout.mapping-latest.debug.js"
));
當初想在偵測階段追蹤knockout.mapping原始檔,而它有兩個檔案:knockout.mapping-latest.js(壓縮版本)及knockout.mapping-latest.debug.js(原始碼版本),我自作聰明地挑了debug.js。而UAT環境啟取消了debug模式(<compilation debug="false" targetFramework="4.5" />),啟用JavaScript打包,而打包壓縮後的JavaScript中並不包含knockout.mapping。查了資料才發現,Bundle程序預設會忽略.debug.js、.min.js。更進一步,我在ScriptBundle寫knockout.mapping-latest.debug.js根本多此一舉,只要寫knockout.mapping-latest.js,在偵錯模式下若有同名*.debug.js,ScriptBundle將優先改用debug.js版本。所以,上述程式應改為:
bundles.Add(new ScriptBundle("~/bundles/ko").Include(
"~/Scripts/knockout-3.0.0.js",
"~/Scripts/knockout.mapping-latest.js"
));
在偵錯模式會自動載入knockout-3.0.0.debug.js及knockout.mapping-latest.debug.js。
最後補充一點:當同名*.min.js存在時,ScriptBundle將改用.min.js取代.js,但仍會重新壓縮,做個實驗驗證這一點。
準備兩個檔案boo.js及boo.min.js,其內容分別為:
var boo = { version: "Source" };
以及
//假裝是預先壓縮過的版本(明明不是)
var boo = { version: "Minified", test: function() {
var longVarName = "Test";
function log(msg) {
if (window.console) console.log(msg);
}
log(longVarName);
}};
實測結果,傳回的內容來自boo.min.js,但註解被移除了,內部變數名稱也被換成短版,且原本已縮為一列,經Chrome F12的Pretty print功能才排列如下圖,證明打包機制雖然改用boo.min.js,但仍會執行壓縮。