如何在 ClojureScript 中编写不可知的 JavaScript 库?
How to author agnostic JavaScript library in ClojureScript?
假设我有一个包含以下内容的 cljs
文件:
(ns foo)
(defn add [x y]
(+ x y))
并希望将其作为 JavaScript 库提供给非 ClojureScript 开发人员(主要关注 node.js)。我可以做到:
clj -m cljs.main -c foo
但问题是输出面向 google 闭包的模块系统(例如 goog.require
)。我可以使用 -t
标志(而不是浏览器或节点)将目标设置为 none
,并且...不能解决这个问题。将它设置为 node
也不能解决问题:没有 index.js
(它在 Java 中被称为 main),没有 module.exports = blah blah
。它似乎适合独立的全节点应用程序,而不是库。
我知道 ClojureScript 使用 google 闭包作为它自己的子模块,我 不一定 想要摆脱所有这些(我'我不确定你可以)。我得到 es2015 原生 Java脚本模块因为它们的静态特性而被淘汰。
我 可以 手动或通过脚本修改输出以与 npm 生态系统配合良好,但令我惊讶的是没有编译器选项可以实际输出 npm-友好的模块。或者有吗?我只是读 --help
错了吗?
shadow-cljs supports output in a CommonJS format via :target :npm-module 确实支持您的要求。 Node 和其他 JS 工具(例如 webpack
)可以独立使用单独的命名空间。默认的 CLJS 工具不支持这种模式。
然而,ClojureScript 在很大程度上是在假设您的整个程序将由 Closure 编译器优化的情况下编写的。这使得编写要包含在其他构建中的库不太理想。每个以这种方式构建的 "library" 都将包含其自己的 cljs.core
版本,因此开始时会非常大,并且包括以这种方式构建的 2 个库是灾难的根源,因为它们彼此不兼容.
这假设您已经安装了 ClojureScript 和 Node.js
给定:
math101
|-- package.json
|-- src
| `-- com
| `-- example
| `-- math.cljs
package.json
{
"name": "math101",
"version": "1.0.0",
"main": "dist/index.js",
"license": "MIT",
"devDependencies": {
"shadow-cljs": "^2.8.52",
"source-map-support": "^0.5.13"
}
}
备注:
dist/index.js
- 这将包含转换为 JavaScript 的 ClojureScript 代码
shadow-cljs
- 我们需要的构建(和依赖管理)工具
source-map-support
- Required to run ClojureScript on Node.js
请确保您已经安装了这两个 NPM 依赖项,然后再继续。
math.cljs
(ns com.example.math)
(defn add [x y]
(+ x y))
1。设置构建工具
在 math101
运行 yarn shadow-cljs init
的根目录下。
这将创建一个名为 shadow-cljs.edn
的文件,其中包含一些默认设置:
;; shadow-cljs configuration
{:source-paths
["src/dev"
"src/main"
"src/test"]
:dependencies
[]
:builds
{}}
让我们做一些改变。
首先你不需要那么多源路径:
{:source-paths
["src"]
:dependencies
[]
:builds
{}}
然后让我们添加构建配置:
;; shadow-cljs configuration
{:source-paths
["src"]
:dependencies
[]
:builds
{:math101 {:target :node-library
:output-to "dist/index.js"
:exports-var com.example.math/add}}}
备注:
:math101
- 这是我们稍后将使用的构建 ID
:target :node-library
- 这告诉 shadow-cljs
您打算编写一个库
:output-to "dist/index.js"
- 您打算发布的代码
:exports-var com.example.math/add
- "Fully qualified name" 您打算发布的函数。这将产生一个 default 导出。
补充说明:
The :target :node-library emits code that can be used (via require) as a standard node library, and is useful for publishing your code for re-use as a compiled Javascript artifact.
有一个 :npm-module
目标可用,但到目前为止 :node-library
已经为我勾选了所有复选框。
2。让我们构建这个!
运行 yarn shadow-cljs compile math101
.
第一次 运行 时,shadow-cljs
会下载一堆东西。最终它会完成,当它完成时...
$ node
> var add = require('./dist')
> add(40, 2)
42
✨✨✨
需要导出不止一个函数?没问题。
让我们添加 subtract
:
(ns com.example.math)
(defn add [x y]
(+ x y))
(defn subtract [x y]
(- x y))
现在让我们更新构建配置:
;; shadow-cljs configuration
{:source-paths
["src"]
:dependencies
[]
:builds
{:math101 {:target :node-library
:output-to "dist/index.js"
:exports {:add com.example.math/add
:subtract com.example.math/subtract}}}}
运行 yarn shadow-cljs compile math101
再次完成时:
$ node
> var math101 = require('./dist')
> math101.add(40, 2)
42
> math101.subtract(44, 2)
42
✨✨✨✨✨✨
附录
这只是为了帮助您入门。 shadow-cljs compile
生成非生产代码(即它没有被缩小,死代码没有被删除 AFAIK 并且 Google Closure 还没有 运行 任何优化)。
用于生成生产就绪代码的命令是 shadow-cljs release
,但您可能想先调整您的构建配置。
我强烈建议您花时间阅读 shadow-cljs documentation。这是一个了不起的工具。
假设我有一个包含以下内容的 cljs
文件:
(ns foo)
(defn add [x y]
(+ x y))
并希望将其作为 JavaScript 库提供给非 ClojureScript 开发人员(主要关注 node.js)。我可以做到:
clj -m cljs.main -c foo
但问题是输出面向 google 闭包的模块系统(例如 goog.require
)。我可以使用 -t
标志(而不是浏览器或节点)将目标设置为 none
,并且...不能解决这个问题。将它设置为 node
也不能解决问题:没有 index.js
(它在 Java 中被称为 main),没有 module.exports = blah blah
。它似乎适合独立的全节点应用程序,而不是库。
我知道 ClojureScript 使用 google 闭包作为它自己的子模块,我 不一定 想要摆脱所有这些(我'我不确定你可以)。我得到 es2015 原生 Java脚本模块因为它们的静态特性而被淘汰。
我 可以 手动或通过脚本修改输出以与 npm 生态系统配合良好,但令我惊讶的是没有编译器选项可以实际输出 npm-友好的模块。或者有吗?我只是读 --help
错了吗?
shadow-cljs supports output in a CommonJS format via :target :npm-module 确实支持您的要求。 Node 和其他 JS 工具(例如 webpack
)可以独立使用单独的命名空间。默认的 CLJS 工具不支持这种模式。
然而,ClojureScript 在很大程度上是在假设您的整个程序将由 Closure 编译器优化的情况下编写的。这使得编写要包含在其他构建中的库不太理想。每个以这种方式构建的 "library" 都将包含其自己的 cljs.core
版本,因此开始时会非常大,并且包括以这种方式构建的 2 个库是灾难的根源,因为它们彼此不兼容.
这假设您已经安装了 ClojureScript 和 Node.js
给定:
math101
|-- package.json
|-- src
| `-- com
| `-- example
| `-- math.cljs
package.json
{
"name": "math101",
"version": "1.0.0",
"main": "dist/index.js",
"license": "MIT",
"devDependencies": {
"shadow-cljs": "^2.8.52",
"source-map-support": "^0.5.13"
}
}
备注:
dist/index.js
- 这将包含转换为 JavaScript 的 ClojureScript 代码
shadow-cljs
- 我们需要的构建(和依赖管理)工具source-map-support
- Required to run ClojureScript on Node.js
请确保您已经安装了这两个 NPM 依赖项,然后再继续。
math.cljs
(ns com.example.math)
(defn add [x y]
(+ x y))
1。设置构建工具
在 math101
运行 yarn shadow-cljs init
的根目录下。
这将创建一个名为 shadow-cljs.edn
的文件,其中包含一些默认设置:
;; shadow-cljs configuration
{:source-paths
["src/dev"
"src/main"
"src/test"]
:dependencies
[]
:builds
{}}
让我们做一些改变。
首先你不需要那么多源路径:
{:source-paths
["src"]
:dependencies
[]
:builds
{}}
然后让我们添加构建配置:
;; shadow-cljs configuration
{:source-paths
["src"]
:dependencies
[]
:builds
{:math101 {:target :node-library
:output-to "dist/index.js"
:exports-var com.example.math/add}}}
备注:
:math101
- 这是我们稍后将使用的构建 ID:target :node-library
- 这告诉shadow-cljs
您打算编写一个库:output-to "dist/index.js"
- 您打算发布的代码:exports-var com.example.math/add
- "Fully qualified name" 您打算发布的函数。这将产生一个 default 导出。
补充说明:
The :target :node-library emits code that can be used (via require) as a standard node library, and is useful for publishing your code for re-use as a compiled Javascript artifact.
有一个 :npm-module
目标可用,但到目前为止 :node-library
已经为我勾选了所有复选框。
2。让我们构建这个!
运行 yarn shadow-cljs compile math101
.
第一次 运行 时,shadow-cljs
会下载一堆东西。最终它会完成,当它完成时...
$ node
> var add = require('./dist')
> add(40, 2)
42
✨✨✨
需要导出不止一个函数?没问题。
让我们添加 subtract
:
(ns com.example.math)
(defn add [x y]
(+ x y))
(defn subtract [x y]
(- x y))
现在让我们更新构建配置:
;; shadow-cljs configuration
{:source-paths
["src"]
:dependencies
[]
:builds
{:math101 {:target :node-library
:output-to "dist/index.js"
:exports {:add com.example.math/add
:subtract com.example.math/subtract}}}}
运行 yarn shadow-cljs compile math101
再次完成时:
$ node
> var math101 = require('./dist')
> math101.add(40, 2)
42
> math101.subtract(44, 2)
42
✨✨✨✨✨✨
附录
这只是为了帮助您入门。 shadow-cljs compile
生成非生产代码(即它没有被缩小,死代码没有被删除 AFAIK 并且 Google Closure 还没有 运行 任何优化)。
用于生成生产就绪代码的命令是 shadow-cljs release
,但您可能想先调整您的构建配置。
我强烈建议您花时间阅读 shadow-cljs documentation。这是一个了不起的工具。