ClojureScript

進階編譯

如果您以傳統的 JavaScript 客戶端(網頁瀏覽器)為目標,從一開始就考慮進階編譯非常重要。否則,您將不可避免地遇到一些問題,而這些問題本來可以透過一些預先準備輕鬆避免。一般來說,不要等到最後才嘗試進階建置,您應該始終定期生成生產建置,以便更快發現問題。

避免外部函式庫

如果 Google Closure 函式庫或現有的 ClojureScript 函式庫中存在解決方案,最好直接避免使用外部函式庫。外部函式庫必須提供外部宣告,以使進階編譯能夠一致地運作。

當然,在某些情況下,外部函式庫是無法避免的。

使用外部函式庫

如果必須使用外部函式庫,請使用像 CLJSJS 提供的經過整理的函式庫。這些函式庫會附帶外部宣告,因此您不必自己提供。

有時您可能會發現需要一個沒有預先封裝的外部函式庫。

提供外部宣告

當使用不提供外部宣告的外部函式庫時,請花時間為您打算使用的 API 撰寫外部宣告檔案。提供外部宣告檔案非常簡單。例如,如果外部函式庫具有您希望存取的屬性 Foo.bar,則您的外部宣告檔案應具有以下條目

Foo.bar;

如果外部函式庫具有您希望調用的方法 Foo.baz,則您的外部宣告檔案應具有以下條目

Foo.baz = function() {};

有時不會有頂層 API,而是一些方法命名慣例,也就是特別介面/協定。在這種情況下,請使用 Object 定義您的外部宣告

Object.foo = function() {};
Object.bar = function() {};

當然,有時您會遺漏一個外部宣告條目,並且生產檔案會產生含糊不清的錯誤。幸好,由於 Closure 編譯器的一些選項,這些問題不再難以除錯。

從 JavaScript 存取

如果您想從 JavaScript 存取 ClojureScript 程式碼,那麼您需要應對進階編譯將會混淆您的 Var 名稱的 JavaScript 表示形式的事實。這可以透過將 :export metadata 新增到應可從 JavaScript 使用的 Vars 來輕鬆解決。

例如,如果您有一個 square 函數,您可以按如下所示使用 ^:export 對其進行註解

(ns my-math.core)

(defn ^:export square [x]
  (* x x))

這樣,您可以按如下所示從 JavaScript 呼叫您的 square 函數

my_math.core.square(3);

這是透過在 :export meta 與 Var 相關聯的任何地方,在發出的 JavaScript 中包含 goog.exportSymbol 呼叫來實現的。

對於每個匯出的 Var,都會建立一個額外的未重新命名的別名,該別名指向 Closure 混淆的名稱。混淆的名稱將繼續在最佳化程式碼內部使用。

^:export 功能是用於(且僅用於)透過未重新命名的別名提供對 Vars 的外部存取。如果您想除錯使用縮短名稱的最佳化程式碼,請考慮使用 :pseudo-names:pretty-print,這些將在下一節中介紹。

您可以個別匯出與協定方法相關聯的 Vars。在此範例中,將匯出 barquux

(defprotocol IFoo
  (^:export bar [this])
  (baz [this x])
  (^:export quux [this x y]))

修正進階編譯問題

將您的生產建置變更為使用兩個額外的選項 :pseudo-names true:pretty-print true。現在您的錯誤將顯示與原始來源中的名稱對應的名稱。為這個遺漏的情況新增一個外部宣告條目。

有關 :foreign-libs 編譯器選項語法的更多資訊,請參閱相依性