+5
-2
.dockerignore
+5
-2
.dockerignore
+4
-1
.gitignore
+4
-1
.gitignore
+6
-6
Dockerfile
+6
-6
Dockerfile
···
19
19
RUN /go/bin/templ generate
20
20
21
21
# Create the directory structure for static assets
22
-
RUN mkdir -p ./internal/web/state/static
22
+
RUN mkdir -p ./static/files
23
23
24
24
# Download frontend libraries into the static folder
25
-
RUN curl -sLo ./static/htmx.min.js https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
26
-
RUN curl -sLo ./static/lucide.min.js https://unpkg.com/lucide@0.525.0/dist/umd/lucide.min.js
27
-
RUN curl -sLo ./static/alpinejs.min.js https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js
28
-
RUN curl -sLo ./static/htmx-toaster.min.js https://unpkg.com/htmx-toaster@0.0.20/dist/htmx-toaster.min.js
25
+
RUN curl -sLo ./static/files/htmx.min.js https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
26
+
RUN curl -sLo ./static/files/lucide.min.js https://unpkg.com/lucide@0.525.0/dist/umd/lucide.min.js
27
+
RUN curl -sLo ./static/files/alpinejs.min.js https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js
28
+
RUN curl -sLo ./static/files/htmx-toaster.min.js https://unpkg.com/htmx-toaster@0.0.20/dist/htmx-toaster.min.js
29
29
30
-
RUN tailwindcss -i ./input.css -o ./static/style.css --minify
30
+
RUN tailwindcss -i ./input.css -o ./static/files/style.css --minify
31
31
32
32
RUN go build -v -o /run-app ./cmd/server/main.go
33
33
+24
-8
internal/server/handlers/static.go
+24
-8
internal/server/handlers/static.go
···
1
1
package handlers
2
2
3
3
import (
4
-
"io/fs"
5
4
"log"
6
5
"net/http"
7
6
"strings"
···
10
9
)
11
10
12
11
func (h *Handler) HandleStatic() http.Handler {
12
+
var finalHandler http.Handler
13
+
13
14
if h.Config.Core.Dev {
14
-
return http.StripPrefix("/static/", http.FileServer(http.Dir("static")))
15
+
fileSystem := http.Dir("./static/files")
16
+
fileServer := http.FileServer(fileSystem)
17
+
finalHandler = NoCache(http.StripPrefix("/static/", fileServer))
18
+
} else {
19
+
fs, err := static.FS()
20
+
if err != nil {
21
+
log.Fatal("failed to create embedded static file system:", err)
22
+
}
23
+
fileSystem := fs
24
+
fileServer := http.FileServer(fileSystem)
25
+
finalHandler = Cache(http.StripPrefix("/static/", fileServer))
15
26
}
16
27
17
-
sub, err := fs.Sub(static.StaticFiles, "static")
18
-
if err != nil {
19
-
log.Fatal("failed to find static folder:", err)
20
-
}
21
-
return Cache(http.StripPrefix("/static/", http.FileServer(http.FS(sub))))
28
+
return finalHandler
22
29
}
23
30
24
31
func Cache(h http.Handler) http.Handler {
···
29
36
// Cache minified js for a year
30
37
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
31
38
} else {
32
-
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
39
+
w.Header().Set("Cache-Control", "public, max-age=3600")
33
40
}
34
41
35
42
h.ServeHTTP(w, r)
36
43
})
37
44
}
45
+
46
+
func NoCache(h http.Handler) http.Handler {
47
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
48
+
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
49
+
w.Header().Set("Pragma", "no-cache")
50
+
w.Header().Set("Expires", "0")
51
+
h.ServeHTTP(w, r)
52
+
})
53
+
}
+18
static/static.go
+18
static/static.go
···
1
+
package static
2
+
3
+
import (
4
+
"embed"
5
+
"io/fs"
6
+
"net/http"
7
+
)
8
+
9
+
//go:embed files
10
+
var StaticFiles embed.FS
11
+
12
+
func FS() (http.FileSystem, error) {
13
+
subFS, err := fs.Sub(StaticFiles, "files")
14
+
if err != nil {
15
+
return nil, err
16
+
}
17
+
return http.FS(subFS), nil
18
+
}