2024 Clojure 状况调研!分享你的想法。

欢迎!请查阅关于页面以了解更多关于这个系统的工作方式的信息。

0 投票
ClojureScript

现在没有时间提供合适的重现,但基本问题可以通过以下示例说明

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

throw err;
      ^

Error: 找不到模块 '/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_targetSTAR":"nodejs"};
goog.require("boot.cljs.main");
goog.require("cljs.nodejscli");
`

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

一个解决方案可能是使用 {{__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脚本来运行我的应用程序

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

从Node.js的角度来看

  1. 使用绝对路径被认为是一种坏做法。
  2. 不使用外部包的Node.js程序(不依赖于node_modules)可以从任何CWD运行
  3. 依赖于node_modules的Node.js程序,如果从包含node_modules的目录之外运行会失败,这属于预期行为。
0 投票

评论者:pupeno

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

0 投票
0 投票

评论者:pupeno

似乎可以通过使用:simple 优化作为可能的解决方案。

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 投票
by
参考:https://clojure.atlassian.net/browse/CLJS-1444(martinklepsch 报告)
...