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 编译的,因为我手头现在有这个。编译的 shim 看起来像这样

`
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_target*":"nodejs"};
goog.require("boot.cljs.main");
goog.require("cljs.nodejscli");
`

问题在于,{{path.resolve(".")}} 会返回启动 node 命令的目录,而不是 shim 目录。(见上面的 "Cannot find module..." 错误)

一个解决方案可能使用 {{__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}}。我也不是很确定我完全理解这种切换的后果(我几乎没有使用过 cljs,更多的是从 Node.js 用户的视角来看)。我的观点是:当前的行为使得 ClojureScript 对于命令行和桌面应用程序(尤其是 electron)难以使用。

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

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

我很幸运我的代码不需要使用真正的 CWD,但这更像是一个修复而不是一个真正的解决方案。

从 Node.js 的角度来看

  1. 使用绝对路径被认为是一种糟糕的做法。
  2. 不使用外部包(不依赖于 node_modules)的 Node.js 程序可以从任何 CWD 运行
  3. 依赖于 node_modules 的 Node.js 程序如果在包含 node_modules 的目录之外的其他目录中运行会崩溃,但这是预期行为。
0

评论者:pupeno

当我尝试开发一个 Electron 应用程序时,我遇到了这个问题。目前,它的运作方式基本上是不可打包的。我认为将这种行为作为选项会有所帮助,我很乐意为之工作一个补丁。

0
0

评论者:pupeno

一个可能的解决方案似乎是使用::简单优化。

0

评论者:thatismatt

我也在开发的电子应用中遇到了这个问题。@pupeno,你对你提出的补丁解决方案有何进展?我也乐意查找这个补丁。虽然我认为我需要一些指导才能开始。

0

评论者:thatismatt

经过今早的快速实验,将{{path.resolve('.')}}替换为{{__dirname}}似乎在(链接:https://github.com/clojure/clojurescript/blob/aa5f001300e9aebd976cb180f5b7ccb37fcb6898/src/main/clojure/cljs/closure.clj#L1460-L1461)对几个简单的电子和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报告)
...