Skip to content

Commit

Permalink
🏗️ Scan the classpath for resources with content-hashed filenames
Browse files Browse the repository at this point in the history
Why:
- The UI must use public assets such as images, but their filenames are
  content-hashed to improve caching, so the UI doesn't know their exact
  filenames.
- The current solution scans the classpath for public assets on startup.
  This will be very fast at runtime, because it's just a hashmap lookup.
  But the disadvantage is that during development new and updated assets
  are not included automatically. Hopefully the assets are changed
  seldom enough for it to not become a problem, or the solution needs to
  be made more complicated.
  • Loading branch information
luontola committed May 12, 2024
1 parent 6bc70be commit 93227f5
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 5 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions .idea/libraries/Leiningen__org_reflections_reflections_0_10_2.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
[org.flywaydb/flyway-core "10.9.1"]
[org.flywaydb/flyway-database-postgresql "10.9.1"]
[org.postgresql/postgresql "42.7.2"]
[org.reflections/reflections "0.10.2"]
[prismatic/schema "1.4.1"]
[ring "1.11.0"]
[ring-logger "1.1.1"]
Expand Down
13 changes: 12 additions & 1 deletion src/territory_bro/ui/html.clj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
[hiccup.util :as hiccup.util]
[reitit.core :as reitit]
[ring.util.http-response :as http-response]
[ring.util.response :as response]))
[ring.util.response :as response])
(:import (org.reflections Reflections)
(org.reflections.scanners Scanners)))

(alter-var-root #'hiccup.util/*html-mode* (constantly :html)) ; change default from :xhtml to :html

Expand Down Expand Up @@ -76,3 +78,12 @@
(assert (some? page-path))
(binding [*page-path* page-path]
(handler request)))))

(def public-resources
(let [reflections (Reflections. "public" (into-array [Scanners/Resources]))]
(->> (.getResources reflections #".*")
(map (fn [resource-path]
(let [url (str/replace resource-path #"^public/" "/") ; resource path -> absolute URL
wildcard-url (str/replace url #"-[0-9a-f]{8}\." "-*.")] ; mapping for content-hashed filenames
[wildcard-url url])))
(into {}))))
3 changes: 2 additions & 1 deletion territory-bro.iml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@
<orderEntry type="library" name="Leiningen: org.eclipse.jetty/jetty-xml:11.0.18" level="project" />
<orderEntry type="library" name="Leiningen: org.flywaydb/flyway-core:10.9.1" level="project" />
<orderEntry type="library" name="Leiningen: org.flywaydb/flyway-database-postgresql:10.9.1" level="project" />
<orderEntry type="library" name="Leiningen: org.javassist/javassist:3.18.1-GA" level="project" />
<orderEntry type="library" name="Leiningen: org.javassist/javassist:3.28.0-GA" level="project" />
<orderEntry type="library" name="Leiningen: org.jetbrains.kotlin/kotlin-stdlib-common:1.9.0" level="project" />
<orderEntry type="library" name="Leiningen: org.jetbrains.kotlin/kotlin-stdlib-jdk7:1.9.23" level="project" />
<orderEntry type="library" name="Leiningen: org.jetbrains.kotlin/kotlin-stdlib-jdk8:1.9.23" level="project" />
Expand All @@ -193,6 +193,7 @@
<orderEntry type="library" name="Leiningen: org.nrepl/incomplete:0.1.0" level="project" />
<orderEntry type="library" name="Leiningen: org.objenesis/objenesis:3.3" level="project" />
<orderEntry type="library" name="Leiningen: org.postgresql/postgresql:42.7.2" level="project" />
<orderEntry type="library" name="Leiningen: org.reflections/reflections:0.10.2" level="project" />
<orderEntry type="library" name="Leiningen: org.ring-clojure/ring-jakarta-servlet:1.11.0" level="project" />
<orderEntry type="library" name="Leiningen: org.ring-clojure/ring-websocket-protocols:1.11.0" level="project" />
<orderEntry type="library" name="Leiningen: org.slf4j/slf4j-api:2.0.12" level="project" />
Expand Down
12 changes: 11 additions & 1 deletion test/territory_bro/ui/html_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
;; The license text is at http://www.apache.org/licenses/LICENSE-2.0

(ns territory-bro.ui.html-test
(:require [clojure.test :refer :all]
(:require [clojure.java.io :as io]
[clojure.test :refer :all]
[hiccup2.core :as h]
[territory-bro.ui.html :as html]))

Expand Down Expand Up @@ -77,3 +78,12 @@

(testing "works for raw hiccup strings"
(is (= "stuff" (html/visible-text (h/raw "<p>stuff</p>"))))))

(deftest public-resources-test
(testing "regular files are mapped as-is"
(is (= "/index.html" (get html/public-resources "/index.html"))))

(testing "content-hashed files are mapped using a wildcard"
(let [path (get html/public-resources "/assets/crop-mark-*.svg")]
(is (some? path))
(is (some? (io/resource (str "public" path)))))))

0 comments on commit 93227f5

Please sign in to comment.