如何在ClojureScript中编写不可知的JavaScript库?

时间:2018-10-19 14:28:16

标签: clojurescript clojurescript-javascript-interop

假设我有一个包含以下内容的cljs文件:

(ns foo)
(defn add [x y]
  (+ x y))

,并希望将其作为JavaScript库提供给非ClojureScript开发人员(主要侧重于node.js)。我可以这样做:

clj -m cljs.main -c foo

但是问题是输出是针对Google Closure的模块系统(例如goog.require)的。我可以使用none标志(与浏览器或节点相对)将目标设置为-t,但是...无法解决此问题。将其设置为node也不能解决问题:没有index.js(在Java中称为main),没有module.exports = blah blah。似乎它面向的是独立的全节点应用程序,而不是库。

我了解ClojureScript使用google闭包作为其自身的子模块,而且我不是不必要希望摆脱所有这些问题(我不确定您可以< / em>)。而且我知道es2015本机JavaScript模块由于其静态特性而退出了。

可以手动或通过脚本对输出进行按摩,以使其在npm生态系统中发挥出色的作用,但令我惊讶的是,没有编译器选项实际上可以输出对npm友好的模块。还是在那里?我只是读错了--help吗?

2 个答案:

答案 0 :(得分:2)

shadow-cljs支持通过:target :npm-module以CommonJS格式输出,它确实支持您的要求。 Node和其他JS工具(例如webpack)可以独立使用单独的命名空间。默认的CLJS工具不支持此模式。

但是,ClojureScript的编写前提是Closure Compiler将优化您的整个程序。这使其不适合编写要包含在其他版本中的库。以这种方式构建的每个“库”都将包含其自己的cljs.core版本,因此开始时将非常庞大,并且包括以这种方式构建的2个库是灾难的秘诀,因为它们彼此之间不兼容。 / p>

答案 1 :(得分:1)

这假设您已经安装了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"
  }
}

注意:

?请确保您已安装这两个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-您要发布的功能的“完全限定名称”。这将产生一个默认导出。

其他说明:

  

:target:node-library发出的代码可以(通过require)用作标准节点库,并且对于发布代码以用作已编译的Javascript工件很有用。

Source

有一个: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。这是一个了不起的工具。