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 目录。(见上面“无法找到模块...”错误)

一个解决方案可能是在使用 {{__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票数
by

评论者:karolmajta

我觉得这种行为真的很奇怪,并愿意改为使用 {{__dirname}}。我也不确定我是否完全理解这样的切换的后果(我的 ClojureScript 经验不多,更多是从 Node.js 用户的角度来看)。我的观点是:当前的行为使得 ClojureScript 在命令行和桌面应用程序(特别是 Electron)中难以使用。

对于命令行和桌面应用程序,不能做出关于当前工作目录的假设。到目前为止,我用一个启动脚本 JS 脚本来运行我的应用程序

process.chdir(__dirname); require('./目标/out');

我很幸运,我的代码不需要真正使用当前工作目录,但这只是一种权宜之计,而不是一个真正的解决方案。

从 Node.js 的角度来看

  1. 使用绝对路径被认为是一种不好的做法。
  2. 不使用外部包的 Node.js 程序(不依赖于 node_modules)可以从任何当前工作目录中运行
  3. 依赖于 node_modules 的 Node.js 程序如果在 node_modules 所在的目录外运行将会出错,但这是一种预期的行为。
0票数
by

评论者:pupeno

我在尝试开发一个 Electron 应用程序时遇到了这个问题。目前这种做法基本上是不可打包的。我认为把这个行为作为一个选项会很好,我很乐意为此工作一个补丁。

0票数
0票数
by

评论者:pupeno

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

0票数

评论者:thatismatt

我正在构建的一个 electron 应用程序中也遇到了这个问题。@pupeno,你对修复的提案有何进展?我也乐意查看这个修复方案。尽管我认为我需要一些指导才能开始。

0票数

评论者:thatismatt

今天早上快速实验表明,在(链接:https://github.com/clojure/clojurescript/blob/aa5f001300e9aebd976cb180f5b7ccb37fcb6898/src/main/clojure/cljs/closure.clj#L1460-L1461)处将 {{path.resolve(".")}} 替换为 {{__dirname}} 对几个简单的 electron 和 node 应用程序有效。我特别指的是即使应用是从不同的当前工作目录开始的(即编译目录),错误也不会出现,即代码是路径无关的。

在做更多完整的测试之后,我会上传一个修复方案。在此之前,任何对这个方法的反馈都将是受欢迎的。

0票数

评论者:thatismatt

附上修复方案,建议使用 __dirname 而不是 "." 在生成的脚本中。我已经在 nodejs 6.10.0 和 electron 1.6.5 上进行了测试。

0票数

评论者:thatismatt

也参见:(链接:CLJS-1990)

0票数

评论者:matthiasn

在与 electron_builder 打包时遇到了相同的问题,无法使用 optimization :none。有希望接受提出的修复方案吗?谢谢!

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