Skip to content

Commit defbb23

Browse files
committed
Own Vite integration
1 parent b821aff commit defbb23

File tree

11 files changed

+169
-94
lines changed

11 files changed

+169
-94
lines changed

app/app.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import (
88
"os"
99
"os/signal"
1010

11-
"github.com/nicolashery/simply-shared-notes/app/assets"
1211
"github.com/nicolashery/simply-shared-notes/app/config"
1312
"github.com/nicolashery/simply-shared-notes/app/db"
1413
"github.com/nicolashery/simply-shared-notes/app/server"
1514
"github.com/nicolashery/simply-shared-notes/app/session"
15+
"github.com/nicolashery/simply-shared-notes/app/vite"
1616
)
1717

1818
func Run(ctx context.Context, distFS embed.FS, pragmasSQL string) error {
@@ -32,19 +32,9 @@ func Run(ctx context.Context, distFS embed.FS, pragmasSQL string) error {
3232
}
3333
logger := slog.New(h)
3434

35-
var assetsConfig assets.AssetsConfig
36-
if cfg.IsDev {
37-
assetsConfig, err = assets.DevAssets()
38-
if err != nil {
39-
return err
40-
}
41-
logger.Info("using dev assets, make sure Vite is running")
42-
} else {
43-
assetsConfig, err = assets.ProdAssets(distFS)
44-
if err != nil {
45-
return err
46-
}
47-
logger.Info("using prod assets")
35+
vite, err := vite.New(logger, cfg.IsDev, distFS)
36+
if err != nil {
37+
return err
4838
}
4939

5040
sqlDB, err := db.InitDB(ctx, cfg.DatabasePath(), pragmasSQL)
@@ -55,7 +45,7 @@ func Run(ctx context.Context, distFS embed.FS, pragmasSQL string) error {
5545

5646
sessionStore := session.InitStore(cfg.CookieSecret, cfg.IsDev)
5747

58-
s := server.New(cfg, logger, sqlDB, queries, assetsConfig, sessionStore)
48+
s := server.New(cfg, logger, sqlDB, queries, vite, sessionStore)
5949

6050
return server.Run(ctx, s, logger, cfg.Port)
6151
}

app/assets/assets.go

Lines changed: 0 additions & 60 deletions
This file was deleted.

app/rctx/vite.context.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@ import (
44
"context"
55
"net/http"
66

7-
"github.com/olivere/vite"
7+
"github.com/nicolashery/simply-shared-notes/app/vite"
88
)
99

10-
func ViteCtxMiddleware(viteFragment *vite.Fragment) func(http.Handler) http.Handler {
10+
func ViteCtxMiddleware(vite *vite.Vite) func(http.Handler) http.Handler {
1111
return func(next http.Handler) http.Handler {
1212
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
13-
ctx := context.WithValue(r.Context(), viteContextKey, viteFragment)
13+
ctx := context.WithValue(r.Context(), viteContextKey, vite)
1414
next.ServeHTTP(w, r.WithContext(ctx))
1515
})
1616
}
1717
}
1818

19-
func GetVite(ctx context.Context) *vite.Fragment {
20-
viteFragment, ok := ctx.Value(viteContextKey).(*vite.Fragment)
19+
func GetVite(ctx context.Context) *vite.Vite {
20+
vite, ok := ctx.Value(viteContextKey).(*vite.Vite)
2121
if !ok {
2222
panic("vite not found in context, make sure to use middleware")
2323
}
2424

25-
return viteFragment
25+
return vite
2626
}

app/server/server.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,26 @@ import (
1010
"github.com/go-chi/chi/v5"
1111
"github.com/go-chi/chi/v5/middleware"
1212
"github.com/gorilla/sessions"
13-
"github.com/nicolashery/simply-shared-notes/app/assets"
1413
"github.com/nicolashery/simply-shared-notes/app/config"
1514
"github.com/nicolashery/simply-shared-notes/app/db"
1615
"github.com/nicolashery/simply-shared-notes/app/handlers"
1716
"github.com/nicolashery/simply-shared-notes/app/rctx"
17+
"github.com/nicolashery/simply-shared-notes/app/vite"
1818
)
1919

20-
func New(cfg *config.Config, logger *slog.Logger, sqlDB *sql.DB, queries *db.Queries, assetsConfig assets.AssetsConfig, sessionStore *sessions.CookieStore) http.Handler {
20+
func New(cfg *config.Config, logger *slog.Logger, sqlDB *sql.DB, queries *db.Queries, vite *vite.Vite, sessionStore *sessions.CookieStore) http.Handler {
2121
router := chi.NewRouter()
2222

2323
router.Use(
2424
middleware.Logger,
2525
middleware.Recoverer,
26-
rctx.ViteCtxMiddleware(assetsConfig.ViteFragment),
26+
rctx.ViteCtxMiddleware(vite),
2727
)
2828

2929
handlers.RegisterRoutes(router, cfg, logger, sqlDB, queries, sessionStore)
3030

31-
StaticDir(router, "/assets", assetsConfig.AssetsFS)
32-
StaticFile(router, "/robots.txt", assetsConfig.PublicFS)
31+
StaticDir(router, "/assets", vite.AssetsFS)
32+
StaticFile(router, "/robots.txt", vite.PublicFS)
3333

3434
return router
3535
}

app/views/layouts/base.layout.templ

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ package layouts
33
import "github.com/nicolashery/simply-shared-notes/app/rctx"
44

55
templ Base(title string) {
6+
{{ vite := rctx.GetVite(ctx) }}
67
<!DOCTYPE html>
78
<html lang="en">
89
<head>
910
<meta charset="utf-8"/>
1011
<meta name="viewport" content="width=device-width, initial-scale=1"/>
1112
<title>{ title } - Simply Shared Notes</title>
12-
@templ.Raw(rctx.GetVite(ctx).Tags)
13+
@templ.Raw(vite.Fragment([]string{"assets/app.css", "assets/app.js"}))
1314
</head>
1415
<body>
1516
<main class="min-h-screen bg-base-200">

app/views/layouts/base.layout_templ.go

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/vite/vite.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package vite
2+
3+
import (
4+
"embed"
5+
"encoding/json"
6+
"fmt"
7+
"html/template"
8+
"io/fs"
9+
"log/slog"
10+
"os"
11+
"strings"
12+
)
13+
14+
type Vite struct {
15+
IsDev bool
16+
PublicFS fs.FS
17+
AssetsFS fs.FS
18+
Manifest Manifest
19+
DevPrefix string
20+
ProdPrefix string
21+
}
22+
23+
type Manifest map[string]*Chunk
24+
25+
type Chunk struct {
26+
File string `json:"file"`
27+
}
28+
29+
func New(logger *slog.Logger, isDev bool, distFS embed.FS) (*Vite, error) {
30+
var publicFS fs.FS
31+
var assetsFS fs.FS
32+
var err error
33+
if isDev {
34+
publicFS = os.DirFS("./public")
35+
assetsFS = os.DirFS("./assets")
36+
37+
logger.Info("using dev assets, make sure Vite is running")
38+
} else {
39+
publicFS, err = fs.Sub(distFS, "dist")
40+
if err != nil {
41+
return nil, fmt.Errorf("failed to create sub-filesystem for 'dist' directory: %w", err)
42+
}
43+
assetsFS, err = fs.Sub(publicFS, "assets")
44+
if err != nil {
45+
return nil, fmt.Errorf("failed to create sub-filesystem for 'dist/assets' directory: %w", err)
46+
}
47+
48+
logger.Info("using prod assets")
49+
}
50+
51+
var manifest Manifest
52+
if !isDev {
53+
err = parseManifest(publicFS, &manifest)
54+
if err != nil {
55+
return nil, err
56+
}
57+
}
58+
59+
return &Vite{
60+
IsDev: isDev,
61+
PublicFS: publicFS,
62+
AssetsFS: assetsFS,
63+
Manifest: manifest,
64+
DevPrefix: "http://localhost:5173",
65+
ProdPrefix: "",
66+
}, nil
67+
}
68+
69+
func parseManifest(distFS fs.FS, manifest *Manifest) error {
70+
mf, err := distFS.Open(".vite/manifest.json")
71+
if err != nil {
72+
return fmt.Errorf("failed to open manifest file: %w", err)
73+
}
74+
defer mf.Close()
75+
76+
err = json.NewDecoder(mf).Decode(manifest)
77+
if err != nil {
78+
return fmt.Errorf("failed to parse manifest file: %w", err)
79+
}
80+
81+
return nil
82+
}
83+
84+
func (v *Vite) Fragment(entries []string) template.HTML {
85+
var sb strings.Builder
86+
87+
if v.IsDev {
88+
sb.WriteString(v.makeScriptTag("@vite/client"))
89+
90+
for _, entry := range entries {
91+
if isCSS(entry) {
92+
sb.WriteString(v.makeStylesheetTag(entry))
93+
} else {
94+
sb.WriteString(v.makeScriptTag(entry))
95+
}
96+
}
97+
} else {
98+
for _, entry := range entries {
99+
chunk, ok := v.Manifest[entry]
100+
if !ok {
101+
continue
102+
}
103+
104+
if isCSS(entry) {
105+
sb.WriteString(v.makeStylesheetTag(chunk.File))
106+
} else {
107+
sb.WriteString(v.makeScriptTag(chunk.File))
108+
}
109+
}
110+
}
111+
112+
return template.HTML(sb.String())
113+
}
114+
115+
func (v *Vite) makeStylesheetTag(path string) string {
116+
var prefix string
117+
if v.IsDev {
118+
prefix = v.DevPrefix
119+
} else {
120+
prefix = v.ProdPrefix
121+
}
122+
123+
return fmt.Sprintf(
124+
`<link rel="stylesheet" href="%s/%s" />`,
125+
prefix,
126+
path,
127+
)
128+
}
129+
130+
func (v *Vite) makeScriptTag(path string) string {
131+
var prefix string
132+
if v.IsDev {
133+
prefix = v.DevPrefix
134+
} else {
135+
prefix = v.ProdPrefix
136+
}
137+
138+
return fmt.Sprintf(
139+
`<script type="module" src="%s/%s"></script>`,
140+
prefix,
141+
path,
142+
)
143+
}
144+
145+
func isCSS(path string) bool {
146+
return strings.HasSuffix(path, ".css")
147+
}

assets/app.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
import './app.css';
21

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ require (
1010
github.com/gorilla/sessions v1.4.0
1111
github.com/joho/godotenv v1.5.1
1212
github.com/matoous/go-nanoid/v2 v2.1.0
13-
github.com/olivere/vite v0.1.0
1413
modernc.org/sqlite v1.37.0
1514
)
1615

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
3030
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
3131
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
3232
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
33-
github.com/olivere/vite v0.1.0 h1:Wi5zTtS3BbnOrfG+oRT7KZOI9lp48gRv59VptSBmPO4=
34-
github.com/olivere/vite v0.1.0/go.mod h1:ef1SWmGSWAYJxSuY2Bu90YLQ7hUBxYmejIVuFGsIIe8=
3533
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3634
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3735
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=

0 commit comments

Comments
 (0)