在 boot-clj 项目中使用 resources/public 目录

Using a resources/public directory in a boot-clj project

我正在尝试设置一个引导项目,它使用一个包含子目录 public 的资源目录。后者应该包含例如所有与网络相关的内容、编译的 clojurescript 等。

这对于您想要持有不打算公开的资源的情况是有意义的public。

在没有额外的 public 目录的情况下,它可以完美地工作。尝试使用附加子目录时,出现错误。下面是相关配置:

在build.boot:

(set-env! :resource-paths #{"resources"} ...)

...

(deftask dev
  []
  (comp
   (serve
    :handler 'myapp.server/handler
    :reload true
    :port 3000)
   (watch)
   (reload)
   (cljs-repl)
   (cljs)
   (target :dir #{"resources/public"})))

从资源目录中:

bash-4.3$ tree
└── public
    ├── index.html
    └── js
        └── main.cljs.edn

而 main.cljs.edn 看起来像:

{:require [{{name}}.core]
 :compiler-options {:asset-path "js/main.out"}}

调用 boot dev 时会发生以下情况:ClojureScript 继续编译但出现错误,直到进程被手动终止。看起来像是与某些相对路径相关的递归错误。

Compiling ClojureScript...
• public/js/main.js
Writing target dir(s)...
java.util.concurrent.ExecutionException: java.nio.file.NoSuchFileException: resources/public/public/public/js/main.out/goog/deps.js

而保持 运行 的时间越长,public/public/public/.. 就会扩展。

有人建议可以解决这个问题吗?


更新

这是问题的更新版本:

考虑资源文件夹的这种结构:

bash-4.3$ tree
└── private_file.txt
└── public
    ├── index.html
    └── js
        └── main.cljs.edn

以及 build.boot 中的以下部分:

   (set-env! :resource-paths #{"resources"} ...)

   (deftask dev
      []
      (comp
       (serve
        :handler 'myapp.server/handler
        :reload true
        :port 3000)
       (watch)
       (reload)
       (cljs-repl)
       (cljs)
       (target)))

'myapp.server/handler 知道只提供来自 resources/public 的文件(由 wrap-resource 或等效的 compojure resources 实现)。后者甚至默认为 "private".

但问题出现得更早: 当 运行 boot dev 整个资源目录被复制到目标目录中时,当然包括 private_file.txt 。 (这是预期的行为吗?,我的意思是文件可能会很大,然后它会占用双倍的光盘 space)

此时我不确定 main 中的 :asset-path 对此有何影响。在此处的示例中,我将其保留为 "js/main.out",这可能是不正确的。

我认为问题在于您将生成的代码放入源目录,这可能会导致您的构建任务变得混乱,因为它们将开始使用它们正在生成的文件。罪魁祸首是:

(target :dir #{"resources/public"})

我会将其保留为默认值:

(target :dir #{"target"})

相当于

(target)

当您使用 serve 任务并提供您自己的环处理程序 ('myapp.server/handler) 时,您还需要确保您的处理程序将通过指定正确的根目录来提供类路径中的资源在你的类路径上("public")。可能你已经在使用 ring.middleware.resource/wrap-resource 这样的:

(wrap-resource handler "public")

最后一件事是您的 main.cljs.edn 文件。它的 :asset-path should be set to js as it should be the relative path to JS files served by your server/handler(来自 target/public/js 的文件将被提供 http://localhost:xxxx/js)。

通过此设置,您的源文件(html、css 和来自 resources/public 的其他文件)以及 target/public 中的 cljs 等任务生成的文件=] 应该可以在您的浏览器中使用。