首页 > 解决方案 > 如何在 ClojureScript 中编写不可知的 JavaScript 库?

问题描述

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

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

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

clj -m cljs.main -c foo

但问题是输出面向谷歌闭包的模块系统(例如goog.require)。我可以none使用-t标志将目标设置为(而不是浏览器或节点),并且...不能解决这个问题。将它设置为node也不能解决问题:no index.js(它在 Java 中称为 main),no module.exports = blah blah. 似乎它面向独立的全节点应用程序,而不是库。

我知道 ClojureScript 对它自己的子模块使用 google 闭包,我不一定希望摆脱所有这些(我不确定你是否可以)。我知道 es2015 原生 JavaScript 模块因为它们的静态特性而被淘汰了。

可以手动或通过脚本按摩输出以与 npm 生态系统配合使用,但令我惊讶的是,没有编译器选项可以实际输出对 npm 友好的模块。或者有吗?我只是读--help错了吗?

标签: clojurescriptclojurescript-javascript-interop

解决方案


这假设您已经安装了 ClojureScript 和 Node.js


鉴于:

math101
|-- package.json
|-- src
|   `-- com
|       `-- example
|           `-- math.cljs

包.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 依赖项。

数学.cljs

(ns com.example.math)

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

1.设置构建工具

math101run的根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 工件重复使用很有用。

资源

有一个:npm-module可用的目标,但到目前为止:node-library已经为我选中了所有框。

2. 让我们建造它!

运行yarn shadow-cljs compile math101
第一次运行时,shadow-cljs会下载一堆东西。最终它会完成,当它完成时......

$ node
> var add = require('./dist')
> add(40, 2)
42

✨✨✨</p>

需要导出多个函数?没问题。

让我们添加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 文档。这是一个了不起的工具。


推荐阅读