(ns foo
(:require [cljsjs.react]))
(def react js/React)
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)
因此,外部库不支持任何常见的 :require
辅助功能,如 :as
、:refer
、:rename
等。
虽然这看起来可能是一个小问题,但多年来,用户一直在更深入地进入 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
提供了一条渐进的迁移路径,如果需要的话。例如,用户可以创建一个 cljsjs.react
工件,该工件在 React 上声明了 :npm-deps
。由于外部库的使用现在与正常的命名空间使用统一,因此您可以切换到 node_modules
依赖项,而无需实际更改源代码,只需更改您选择的依赖项管理工具(Maven、Lein、Boot)中的依赖项即可。
我们相信这个功能解决了长期存在的痛点,并为基于 node_modules
的依赖项提供了平滑的迁移路径。请在 ClojureScript 1.9.854 或更高版本中试用一下。