ClojureScript

更簡化的 JavaScript 預處理

2017 年 7 月 20 日
Juho Teperi

這是搶先看系列文章的第四篇。

Closure 編譯器可以處理 AMD、CommonJS 和 ES6 模組,為Node 生態系統提供廣泛的支援。即便如此,Closure 仍有一些熱門案例未直接支援,例如ReactJSX[1] Maria Geller 的 Google Summer of Code 工作也基於 David Nolen 概述的設計解決了這個問題,自1.7.48 版以來,一直存在預處理掛鉤。然而,原始設計使與其他建置工具的整合具有挑戰性,我們修改了方法以簡化此類整合。

動機

使用 JSX 或其他語法擴充功能的 JavaScript 函式庫通常會與已處理的程式碼一起封裝,因此可以直接使用,無需額外操作。儘管如此,在某些實際情況下,人們可能希望直接在專案中包含此類程式碼。例如,當將專案從 JavaScript 轉換為 ClojureScript 時,重複使用現有程式碼比嘗試一次重寫所有內容要容易得多。此外,建立複雜的使用者介面是一項團隊合作,而像 JSX 這樣的工具可以透過為設計師提供熟悉的工具來使該過程更受歡迎。透過允許 ClojureScript 存取 JSX 和其他流行的語法便利功能,ClojureScript 開發流程可以更具包容性。

JavaScript 轉換

在原始設計中,透過將 :preprocess 提供給外部函式庫對應來啟用預處理。該值是 cljs.closure/js-transforms 多重方法的一個關鍵字分派。使用者可以實作新的多重方法案例,並使用 Java 的內建Nashorn JavaScript引擎來執行像Babel這樣的 JavaScript 編譯器。

然而,這種方法為流行的 Clojure 和 ClojureScript 建置工具帶來了複雜性。提供預處理多重方法的 Clojure 命名空間必須在執行 ClojureScript 編譯器之前由使用者載入。雖然這在顯式的建置腳本中是可行的,但由於 LeiningenBoot 都將建置隔離到它們自己的類別路徑中,這個要求根本不切實際。

有幾種方法可以解決原始設計

  1. 提供一個新的組態選項來列舉在執行編譯器之前要 require 的命名空間。

  2. 在多重方法分派關鍵字和提供實作的命名空間之間建立關聯。例如,如果關鍵字是命名空間的,則關鍵字的命名空間部分可用於按需 require 該命名空間。

這兩種解決方案都可以直接在建置工具或 ClojureScript 編譯器中實作。從最終使用者的角度來看,第一個選項似乎很迂迴,雖然第二個選項突出了基本問題,但使用關鍵字來表示這種模式似乎不符合慣例。如果我們簡單地將關鍵字切換為符號,我們可以與現有的先例保持一致。

預處理符號

下一個版本的 ClojureScript 將支援符號作為 :preprocess 選項值。使用完全合格的符號可以明顯看出該值引用的是一個函式,並且該符號的命名空間部分可以用來代表使用者自動載入命名空間。

cljsjs/babel-standalone 已更新,並提供了一種使用此新模式將 Babel 與 ClojureScript 工具一起使用的簡單方法。

結論

熟悉 Clojure 哲學的使用者知道,我們將簡潔性置於大多數其他品質之上。但是,簡潔性並不總是與便利性相衝突,事實上,就與主機的互通性而言,長期以來一直是語言的優先事項。

雖然 Clojure 長期以來一直以與 Java 的出色整合而自豪,但對於 ClojureScript 來說,Google Closure 和主流 JavaScript 實務之間的摩擦使得這一承諾更難以兌現。

我們相信我們正在縮小差距,並且廣闊的 JavaScript 函式庫生態系統現在終於可以近在咫尺。


1。 有一個第三方編譯器傳遞,供 Closure 支援 JSX