请在 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}} 命令的目录,而不是包装器的目录。 (参见上面 "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}}。我也不确定我完全理解这种切换的后果(我对clojurescript的经验不多,更多地是从nodejs用户的角度来看)。我的观点是:当前的行为使得clojurescript对于命令行和桌面应用程序(尤其是electron)很难使用。

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

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

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

从nodejs的角度来看

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

评论者:pupeno

我在尝试开发一个Electron应用程序时遇到了这个问题。目前它的运行方式基本上是不可打包的。我认为如果可以选择这种行为就更好了,我很高兴为此工作。

0
0

评论者:pupeno

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

0

评论者:thatismatt

我最近也在一个我正在构建的electron应用中遇到了这个问题。@pupeno 您关于修复补丁的建议有没有什么进展?我也愿意调查这个补丁。尽管我认为我需要一些指导才能开始。

0

评论者:thatismatt

通过今天早上的快速实验,看样子在这里用{{__dirname}}代替{{path.resolve(".")}},对于几个简单的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 报告)
...