ClojureScript

外部ライブラリのグローバルエクスポート

2017年7月30日
David Nolen

npm エコシステムとの統合により、Closureを認識しないJavaScript依存関係に関する摩擦を大幅に軽減できると期待されます。ただし、この作業は現在進行中で、"外部"依存関係の問題に対する既存のソリューションの改善を妨げるものではありません。

ClojureScriptの` :foreign-libs` オプションは、Closure高度コンパイルを通過できないと予想されるJavaScriptライブラリを含めるための方法を長年提供してきました。CLJSJSのようなコミュニティの努力を通じて、ClojureScript開発者は、ClojureScriptまたはClosureライブラリでは容易に提供されない機能を比較的簡単に利用できます。

しかし、` :foreign-libs` の設計には常に大きな欠陥がありました。これらのライブラリはグローバルにロードされると想定されていました。外部ライブラリによってエクスポートされたAPIは、グローバル環境を介してアクセスする必要がありました。

(ns foo
  (:require [cljsjs.react]))

(def react js/React)

したがって、外部ライブラリは` :as`、` :refer`、` :rename`などの通常の` :require`機能をまったくサポートしていませんでした。

これは些細な問題のように見えるかもしれませんが、長年にわたり、ユーザーは他の場所で提供されていない機能のためにJavaScriptエコシステムをますます深く利用するようになりました。多くのプロジェクトでは、Webpackのようなツールを使用して、そのようなすべての依存関係を単一の外部ライブラリにパッケージ化していました。これは迅速な方法ですが、非慣用的なスタイルにつながり、さらにユーザーが将来これらの依存関係を` node_modules`からの直接使用に移行しようとすると障害となります。

次のリリースでは、` :foreign-libs` コンパイラオプションに簡単な新しい機能である` :global-exports` を導入します。外部ライブラリエントリは、どの名前空間がどのグローバルエクスポート名にマップされるかを宣言できるようになりました。

:foreign-libs [{:provides ["cljsjs.react"]
                :global-exports '{cljsjs.react React}}
               {:provides ["cljsjs.react.dom"]
                :global-exports '{cljsjs.react.dom ReactDOM}}]

この簡単な変更により、` cljsjs.react` は通常の名前空間として扱えるようになりました。

(ns foo
  (:require [cljsjs.react :as react :refer [createElement]))

` :global-exports` は名前空間とグローバルエクスポートのマップであるため、Webpackを使用して単一の外部ライブラリを作成しているユーザーは、バンドルされたすべてのライブラリを慣用的な方法で使用するために簡単にマップできます。

これは、必要に応じて` node_modules`への段階的な移行パスも提供します。たとえば、ユーザーはReactで宣言された` :npm-deps` を持つ` cljsjs.react` アーティファクトを作成できます。外部ライブラリの使用は、通常の名前空間の使用と統合されているため、ソースコードに変更を加えることなく、選択した依存関係管理ツール(Maven、Lein、Boot)の依存関係を変更するだけで、` node_modules`依存関係に切り替えることができます。

この機能により、長年の課題に対処し、` node_modules`ベースの依存関係へのスムーズな移行パスが提供されると考えています。ClojureScript 1.9.854以降で試してみてください。