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}}。我也不能完全理解这种切换的后果(我有点cljs经验,更多的是从nodejs用户的视角)。我的观点是:当前行为使得ClojureScript在命令行和桌面应用程序(特别是electron)中使用困难。

对于命令行和桌面应用程序,不能确定当前工作目录。目前,我通过引导脚本运行我的应用程序JS脚本

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

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

从Node.js的角度来看

  1. 使用绝对路径被认为是不良实践。
  2. 不使用外部包(不依赖于 node_modules)的Node.js程序可以从任何当前工作目录运行
  3. 依赖于 node_modules 的Node.js程序将在从包含 node_modules 的不同目录运行时损坏,但这是一种预期行为。
0

评论者:pupeno

我在尝试开发一个Electron应用程序时遇到了这个问题。目前的工作方式实际上是难以打包的。我认为将其作为选项很酷,并且我很乐意为此编写补丁。

0
0

评论者:pupeno

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

0

评论者:thatismatt

我也在我的一个电子应用中遇到了这个问题。@pupeno,你关于修复补丁的提议有什么进展吗?我也很乐意考虑对这个问题的补丁。尽管我认为我需要一些指引才能开始。

0

评论者:thatismatt

今早的一次快速实验表明,在(链接:https://github.com/clojure/clojurescript/blob/aa5f001300e9aebd976cb180f5b7ccb37fcb6898/src/main/clojure/cljs/closure.clj#L1460-L1461)处将{{path.resolve(".")}}替换为{{__dirname}}对于几个简单的电子和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 报告)
...