Clojure

改善開發啟動時間

你知道嗎

  • 大多數函式庫都以原始碼形式發布,而且您會反覆編譯它們

  • 您可以使用 compile 明確編譯命名空間

  • 命名空間編譯具有傳遞性

  • compile 會將這些檔案寫入磁碟,而 require 會使用它們

  • 您可以在開始開發時載入命名空間、在 user.clj 中,或在您作為伺服器執行的主要命名空間中使用 compile 來改善您的啟動時間

compile 函式會取得命名空間符號,並將該命名空間及其所需的所有命名空間編譯成 *compile-path*(預設為 classes)。該目錄必須存在且位於您的類別路徑中

(compile 'my.namespace)    ;; writes .class files to *compile-path*

隨後,當需要任何這些已編譯的命名空間時,將載入類別檔案,而不是原始的 .clj 檔案。如果原始碼檔案已更新(因此較新),則將載入該檔案。您需要定期重新編譯,以考量新的相依關係或變更的程式碼。

請注意,編譯是載入的副作用,因此對已載入的命名空間沒有影響。特別是,一個特例是 user.clj 檔案,它會由 Clojure 執行時期自動載入。如果您在開發中使用 user.clj(或需要編譯已編譯的命名空間),您可以在編譯時強制重新載入來執行此操作

(binding [*compile-files* true] ;; compile during load
  (require 'user :reload-all))  ;; reload this and all transitively loaded namespaces

就是這樣!此技術可以在開發過程中大幅縮短您的啟動時間,特別是在您載入的相依關係數量增加時。

使用別名進行開發

在 deps.edn 專案中,您應該建立一個包含 classes 目錄的開發別名(例如 :dev

{:deps { ... }
 :aliases
 {:dev {:extra-paths ["classes"]}}}

您還需要確保 classes 目錄存在。將空的 classes 目錄包含在您的版本控制專案結構中可能很有用(請務必忽略並不要包含已編譯的 .class 檔案)。

然後,您可以使用別名和 compile 來啟動您的 REPL,以填入您的 classes 目錄並開始看到好處

$ clj -A:dev
Clojure 1.10.1
user=> (compile 'my.namespace)

將 user.clj 納入您的開發別名

如果您想使用自動載入的 user.clj,您應該透過新增原始碼路徑 dev 將其納入您的開發別名

{:deps { ... }
 :aliases
 {:dev {:extra-paths ["dev" "classes"]}}}

然後建立 dev/user.clj

(ns user
  (:require ... ))

;; dev-only functions, etc

記得對 user.clj 使用修改過的編譯程序

$ clj -A:dev
Clojure 1.10.1
user=> (binding [*compile-files* true] (require 'user :reload-all))

原始作者:Alex Miller