此问题与 CLJS-2205 和 CLJS-2836 有关,尽管我相信它略有不同,我提供了一些额外的(希望有用的)信息。
当作为 npm-deps 使用 "semantic-ui-react" 节点模块时,它产生的代码无法加载。我能想到的最小复现案例如下
{noformat:title=build_opts.edn}
{:npm-deps {:react "16.2.0"
:react-dom "16.2.0"
:semantic-ui-react "0.82.2"}
:install-deps true}
{noformat:title=deps.edn}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.339"}}}
注意:我在当前主分支上看到了完全相同的问题,当时是提交 [81a1ea12|
https://github.com/clojure/clojurescript/tree/81a1ea127974d43a6166fbdae33bcaa296fe9156],在本地安装为 1.10.394。
{noformat:title=src/hello_world/core.cljs}
(ns hello-world.core
(:require semantic-ui-react))
(println "Hello world!")
文件组织结构
$ tree
.
├── build_opts.edn
├── deps.edn
└── src
└── hello_world
└── core.cljs
运行
clj -m cljs.main -co build_opts.edn -c hello-world.core
产生无法加载的代码,方式如下。首先,具有 {{index.js}} 文件的所有模块似乎缺少一个提供语句;例如
{noformat:title=out/node_modules/semantic-ui-react/dist/es/addons/Confirm/index.js}
goog.provide("module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm$index");
goog.provide("module$semantic_ui_react$dist$es$addons$Confirm$index");
goog.provide("module$semantic_ui_react$dist$es$addons$Confirm");
goog.require("module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm$Confirm");
var module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm$index={get default(){return module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm$Confirm["default"]}}
在其他地方以 "full path" 的方式被要求,而不包括最后的 "index"
{noformat:title=out/node_modules/semantic_ui_react/dist/es/index.js (省略)}
...
goog.require("module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm");
...
这导致一个错误,说 nameToPath 无法找到模块 {{"module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm"}}。我通过修补 ClojureScript 编译器(向 cljs.closure/add-converted-source 添加额外的 {{goog.provides}},如果当前源以 {{index}} 结尾,类似于 CLJS-2205 中的修补)修复了这个问题,但后来发现还有一个问题(这使我对我的方法是否是正确的修复方式产生了怀疑),即生成的代码实际上尝试使用带有包括索引部分的完整名称的模块
{noformat:title=out/node_modules/semantic_ui_react/dist/es/index.js (省略)}
...
goog.require("module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm");
...
var module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$index={get Confirm(){return module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm$index["default"]},
...
这导致一个错误,说变量 {{module$Users$gary$sparrho$cljs_bug_report$node_modules$semantic_ui_react$dist$es$addons$Confirm$index}} 未定义。
我对ClojureScript编译器、Google Closure编译器或ES6模块系统一无所知,这使得我难以进一步调查。我已经核实,在生成requires和provides调用({{cljs.closure/add-converted-source}})时,表示依赖关系的Closure对象不包含尾部的{{index}}部分,这与生成的{{goog.requires}}调用一致。{{goog.provides}}调用似乎是独立的生成,基于在{{src/main/cljs/cljs/module_deps.js}}中进行的js文件分析。我无法找到的(因此受阻)是生成试图访问"错误"变量名的JS代码的代码片段。这可能是ClojureScript没有生成正确的{{goog.requires}}调用中的错误,或者这可能是在{{Require}}对象上生成的相同JS变量名的一个错误。