+5
-2
.dockerignore
+5
-2
.dockerignore
+4
-1
.gitignore
+4
-1
.gitignore
+6
-6
Dockerfile
+6
-6
Dockerfile
···
19
RUN /go/bin/templ generate
20
21
# Create the directory structure for static assets
22
-
RUN mkdir -p ./internal/web/state/static
23
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
29
30
-
RUN tailwindcss -i ./input.css -o ./static/style.css --minify
31
32
RUN go build -v -o /run-app ./cmd/server/main.go
33
···
19
RUN /go/bin/templ generate
20
21
# Create the directory structure for static assets
22
+
RUN mkdir -p ./static/files
23
24
# Download frontend libraries into the static folder
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
30
+
RUN tailwindcss -i ./input.css -o ./static/files/style.css --minify
31
32
RUN go build -v -o /run-app ./cmd/server/main.go
33
+24
-8
internal/server/handlers/static.go
+24
-8
internal/server/handlers/static.go
···
1
package handlers
2
3
import (
4
-
"io/fs"
5
"log"
6
"net/http"
7
"strings"
···
10
)
11
12
func (h *Handler) HandleStatic() http.Handler {
13
if h.Config.Core.Dev {
14
-
return http.StripPrefix("/static/", http.FileServer(http.Dir("static")))
15
}
16
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))))
22
}
23
24
func Cache(h http.Handler) http.Handler {
···
29
// Cache minified js for a year
30
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
31
} else {
32
-
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
33
}
34
35
h.ServeHTTP(w, r)
36
})
37
}
···
1
package handlers
2
3
import (
4
"log"
5
"net/http"
6
"strings"
···
9
)
10
11
func (h *Handler) HandleStatic() http.Handler {
12
+
var finalHandler http.Handler
13
+
14
if h.Config.Core.Dev {
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))
26
}
27
28
+
return finalHandler
29
}
30
31
func Cache(h http.Handler) http.Handler {
···
36
// Cache minified js for a year
37
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
38
} else {
39
+
w.Header().Set("Cache-Control", "public, max-age=3600")
40
}
41
42
h.ServeHTTP(w, r)
43
})
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
+
}