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_targetSTAR":"nodejs"};
goog.require("boot.cljs.main");
goog.require("cljs.nodejscli");
`

问题在于{{path.resolve(".")}}会返回调用node命令的目录,而不是shim的目录。(参见上面的“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(output-to, "") path.resolve (编译器路径, 输出目录, "goog", "base.js") path.resolve (编译器路径, 输出目录, "cljs_deps.js")

这假设如果输出到路径是相对的,那么输出目录也是相对的。如果它们不同步,则需要做更多的工作来保持它们那样。

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

0

评论者:karolmajta

我发现这种行为真的很奇怪,并且倾向于切换到 {{__dirname}}。我也不是非常确定我完全理解这种切换的后果(我有一些 cljs 经验,更多地是从 nodejs 用户的角度来看)。我的观点是:当前的行为使得 clojurescript 在命令行和桌面应用程序(特别是 electron)中难以使用。

对于命令行和桌面应用程序,不能假设当前工作目录(CWD)。

目前我通过一个引导脚本 JS 脚本运行我的应用程序

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

我很幸运,我的代码不需要使用真实的 CWD,但这更像是一个折衷方案,而不是真正的解决方案。

  1. 从 nodejs 视角来看
  2. 不使用外部包(不依赖于 node_modules)的 Nodejs 程序可以从任何 CWD 运行
  3. 如果 Nodejs 程序依赖于 node_modules,那么如果从包含 node_modules 的不同目录运行将会失败,但这是预期的行为。
0

评论者:pupeno

当我尝试开发一个 Electron 应用程序时,遇到了这个问题。目前的工作方式基本上是不可打包的。我认为将其作为选项具有这样的行为会很不错,并且我很乐意为其编写补丁。

0
0

评论者: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打包时遇到了相同的问题,无法使用: none优化。有没有可能接受提出的补丁?谢谢!

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