2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请访问关于页面以获取更多有关此信息的工作原理。

0
ClojureScript

现在没有时间提供适当的复现,但基本问题可以用以下内容说明

`
~/c/boot-cljs-example (master=) node target/main.js
module.js:338

throw err;
      ^

错误:找不到模块 '/Users/martin/code/boot-cljs-example/out/goog/bootstrap/nodejs.js'

at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:278:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at Object.<anonymous> (/Users/martin/code/boot-cljs-example/target/main.js:6:1)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)

~/c/boot-cljs-example (master=) cd target/
~/c/b/target (master=) node main.js
开始...
`

这是使用 boot 编译的,因为这是我目前手头上的东西。编译的模拟器如下

`
var path = require("path");
try {

require("source-map-support").install();

} catch(err) {
}
require(path.join(path.resolve("."),"out","goog","bootstrap","nodejs.js"));
require(path.join(path.resolve("."),"out","cljs_deps.js"));
goog.global.CLOSURE_UNCOMPILED_DEFINES = {"cljs.core._STAR_targetSTAR":"nodejs"};
goog.require("boot.cljs.main");
goog.require("cljs.nodejscli");
`

问题在于 {{path.resolve(".")}} 将返回调用 {{node}} 命令的目录,而不是模拟器的目录。(参见上面的“找不到模块...”错误)

解决方案可能是使用 {{__dirname}},它始终指向当前文件的目录。这可能会破坏现有的配置。

11 回答

0

评论由:bensu 发布

我有一个解决方案,但我担心支持“从任何地方运行”会给生成的代码添加复杂的本质。我的思路

  1. 相对路径是产生“无上下文代码”的理想选择。如果用户选择绝对路径,那么将遵守这种行为,而无需处理任何事情(无需“路径代数”)。

  2. 处理相对路径时,整个系统需要建立“参考框架”,即根路径。ClojureScript 编译器假定编译的路径是参考框架,这通常与项目的最高根路径一致。虽然是任意的,但这是唯一合理的选择。

  3. 由于将其定义为{{{"."}}}, 参考框架在代码中并不明确。如果它是明确的话,就会揭示上下文,例如{{"/home/some-user/their-folder/this-project/"}}。

  4. 当我们从另一个参考点接触代码(从另一个目录执行脚本)时,首先需要找到原始编译器路径(参考点),然后从这里解析所有路径。编译器使用cljs.closure/path-relative-to来完成这个目的。

路径代数
{{编译器路径 = __dirname - 输出到}}

Node.js

var 编译器路径 = __dirname.replace(输出到, "") path.resolve(编译器路径, 输出目录, "goog", "base.js") path.resolve(编译器路径, 输出目录, "cljs_deps.js")

这假定如果输出到是相对的,那么输出目录也是相对的。如果它们不一致,就需要更多的努力来保持它们这样。

决定额外的复杂性是否值得用例并非我的责任。实际上,我希望有更简单的解决方案来解决此问题,而我没看到。

0

评论者:karolmajta

我发现这种行为真的很奇怪,并且倾向于切换到{{__dirname}}。我也不确定我完全理解这样切换的后果(我的ClojureScript经验很少,更多是从Node.js用户的角度来看)。我的观点是:当前的行为让ClojureScript在命令行和桌面应用程序(尤其是Electron)中难以使用。

对于命令行和桌面应用程序,不能假设CWD(当前工作目录)。目前我通过一个引导脚本JS脚本运行我的应用程序

process.chdir(__dirname); require('./target/out');

我很幸运我的代码不需要使用真实的CWD,但这更多是一个权宜之计,而不是真正的解决方案。

从Node.js的角度来看

  1. 使用绝对路径被认为是一个不好的实践。
  2. 不使用外部包(不依赖于node_modules)的Node.js程序可以从任何CWD运行
  3. 依赖于< strengthens>node_modules的Node.js程序如果在不包含< strengthens>node_modules的目录中运行将会失败,但这是一种预期行为。
0

评论者:pupeno

我就在尝试开发Electron应用时遇到了这个问题。目前的工作方式基本上是不可打包的。我认为即使作为选项也有这个行为,并且我很乐意为其修复这个问题。

0
0

评论者:pupeno

一种可能的解决办法似乎采用了:简单优化。

0

评论者:thatismatt

我还在我正在构建的一个Electron应用程序中遇到了这个问题。@pupeno 你的修复方案进展如何?我也很愿意调查这个修复方案。尽管我认为我需要一些指导才能开始。

0

评论者:thatismatt

今天早上快速测试结果显示,将{{path.resolve(".")}}替换为{{__dirname}}在(链接:https://github.com/clojure/clojurescript/blob/aa5f001300e9aebd976cb180f5b7ccb37fcb6898/src/main/clojure/cljs/closure.clj#L1460-L1461)中对于一些简单的Electron和Node应用是有效的。具体来说,即使当应用程序在当前工作目录不同于编译目录的位置启动时,错误也不会发生,即代码与路径无关。

完成更多完整测试后,我将附加一个修补程序。在此之前,关于这种方法任何反馈都受欢迎。

0

评论者:thatismatt

附上修复方案,建议在生成的脚本中使用__dirname代替"。",我已用nodejs 6.10.0和electron 1.6.5测试。

0

评论者:thatismatt

也请参阅:(链接:CLJS-1990)

0

评论者:matthiasn

在用 electron_builder 打包时遇到了相同的问题,无法使用 :none 优化。能否接受建议的补丁?谢谢!

0
参考资料:https://clojure.atlassian.net/browse/CLJS-1444(由 martinklepsch 报告)
...