使用模块化处理(CJS/ES6)的 JavaScript 代码可以使用例如 {{goog.require("name.space")}} 或 {{import * from "goog:name.space";}} 来要求 ClojureScript 命名空间。但当前如果此命名空间只由 JS 模块使用而不是其他 ClojureScript 命名空间,则 Closure 优化会失败。
当 {{build}} {{source}} 是单个文件,或者当 {{:optimization}} 和 {{:main}} 被设置时,会发生此情况,因为在这种情况下,构建入口点是 {{:main}} 文件。
问题在于在构建管道中,在添加 {{:libs}} 中的 JS 文件(包括模块处理中的文件)后,不会将新的 ClojureScript 源代码添加到构建中:
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L2809-L2819
使用 {{:optimization :none}},构建过程中不会显示错误,但会在运行时出现关于缺少模块的错误。使用优化,Closure 将抛出关于缺少模块的错误。
;; build.clj
(require 'cljs.build.api)
(cljs.build.api/build
"src"
{:main 'hello.core
:output-to "target/main.js"
:output-dir "target/main.out"
:asset-path "main.out"
:optimizations :simple
:foreign-libs [{:file "src"
:module-type :es6}]})
;; 或者 "src/hello/core.cljs" 作为源文件,并且 :optimization :one
;; src/hello/core.cljs
(ns hello.core (:require [hello.es-module :refer [greet]]))
(greet "test")
;; src/hello/say.cljs
(ns hello.say)
(defn ^:export it [m]
(str "Hello, " m))
;; src/hello/es_module.js
import it from "goog:hello.say";
export var greet = function(m) {
document.write(hello.say.it(m));
};
Closure 错误
Mar 27, 2018 7:02:07 PM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 1 error(s), 0 warning(s)
ERROR: JSC_MISSING_PROVIDE_ERROR. required "hello.say" namespace never provided at /home/juho/tmp/cljs-in-js-in-cljs/target/main.out/src/hello/es_module.js line 2 : 0
Exception in thread "main" java.lang.Exception: Closure 编译失败, compiling:(/home/juho/tmp/cljs-in-js-in-cljs/build.clj:3:1)