请分享您的想法,参与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/"}}。

  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)。目前我通过一个启动脚本运行我的应用程序。

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

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

从Node.js的角度来说

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

评论由:pupeno

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

0
0

评论由:pupeno

似乎可以使用:简单优化作为解决问题的关键。

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