请在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/"}Configs/

    )。

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

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

Node.js

var compiler-path = __dirname.replace(output-to, "") path.resolve (compiler-path, output-dir, "goog", "base.js") path.resolve (compiler-path, output-dir, "cljs_deps.js")

这假设如果output-to是相对的,那么output-dir也是相对的。如果它们不一致,需要做更多的工作来保持它们那样。

决定额外的复杂性是否值得这个使用案例不是我的任务。我实际上希望有一个更简单的解决方案来解决这个问题,但我没看到。

0
by

评论者:karolmajta

我发现这个行为真的很奇怪,并且愿意切换到{{__dirname}}。我也不确定我完全理解这种切换的后果(我有很少的 cljs 经验,更多的是从 nodejs 用户的角度来看)。我的观点是:当前的行为使得 ClojureScript 在命令行和桌面应用程序(特别是 Electron)中使用起来很难。

对于命令行和桌面应用程序,不能假设 CWD 的假设。目前我通过一个引导脚本 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
by

评论者: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](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](link:)

0

评论由:matthiasn 提出

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

0
参考: https://clojure.atlassian.net/browse/CLJS-1444 (由 martinklepsch 提出)
...