tr最早的實現是
- 把使用者放在
content目錄裡面的.scrbl檔案夾進一個適當的上下文裡面,然後輸出到_tmp目錄 - 建構階段幫每一個地址開啟一個racket subprocess輸出HTML
這個實現的缺點就是慢到不行,而且如果用racket的 for/async(平行執行)常常會超出系統開啟行程的限制然後炸掉,用 for 線性執行則是需要好幾分鐘才能建構好網站,但相應的這個方法必定會進行修改
改善效能的過程中發現這個用行程調用的過程不是必須的,racket提供的 dynamic-rerequire 正好可以做到這件事,以我的網站來說建構時間降到分鐘以下的等級
接下來就是改正快取正確性,之前的快取我也是單純比較mtime(這個錯誤每個建構系統都會犯至少一次xd)。現在的版本是查看檔案原始內容,建立hash然後把一些元資料放到 _tmp/cache/<hash> 裡面
快取這裏還有一些坑,要注意把外部依賴放到變更監控裡面,所以除了一開始就遇到的 @include,我後來又加上 @tr/depends 讓使用者自己宣告一些隱藏的檔案依賴(會影響到目前卡片的建置的外部檔案變更)
但從這邊開始監控檔案的連續建置就開始出問題了,有時候修改會沒有觸發新的建構。最後用property-based test才慢慢調查到問題正在於 dynamic-rerequire,最後發現誒怎麼 dynamic-rerequire 也是比較mtimehttps://github.com/racket/racket/blob/2b83c3f3480b94c63a0c5e252b42cc1245b12c7f/racket/collects/racket/rerequire.rkt#L177來判斷要不要觸發重新載入。所以為了確保 dynamic-rerequire 在tr判斷內容有變化的時候一定會執行,我選擇把hash也放到生成的暫時檔名中。這樣內容變化就蘊含檔名變化,新的檔案就一定會觸發建構
更仔細考慮的話,目前的機制都缺乏對退出訊號的處理,所以可能遇到任意時機的中斷,不過這就留待未來處理了