Skip to content

Commit 1525124

Browse files
committed
Use dynamic file names for assets
1 parent 7009eb9 commit 1525124

File tree

11 files changed

+299
-36
lines changed

11 files changed

+299
-36
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ FOMANTIC_WORK_DIR := web_src/fomantic
104104

105105
WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f)
106106
WEBPACK_CONFIGS := webpack.config.js
107-
WEBPACK_DEST := public/js/index.js public/css/index.css
108-
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack public/serviceworker.js
107+
WEBPACK_DEST := public/js
108+
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack $(wildcard public/serviceworker.*.js) public/assets-manifest.json
109109

110110
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
111111
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))

modules/public/manifest.go

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build !bindata
6+
// +build !bindata
7+
8+
package public
9+
10+
import (
11+
"io"
12+
"io/fs"
13+
"net/http"
14+
"sync"
15+
"time"
16+
17+
"code.gitea.io/gitea/modules/json"
18+
"code.gitea.io/gitea/modules/log"
19+
"code.gitea.io/gitea/modules/setting"
20+
)
21+
22+
var (
23+
manifest map[string]string
24+
manifestName = "assets-manifest.json"
25+
manifestMutex = &sync.Mutex{}
26+
manifestModified time.Time
27+
)
28+
29+
func readManifestFile(fs http.FileSystem) (http.File, fs.FileInfo, error) {
30+
f, err := fs.Open(manifestName)
31+
if err != nil {
32+
return nil, nil, err
33+
}
34+
35+
fi, err := f.Stat()
36+
if err != nil {
37+
return nil, nil, err
38+
}
39+
40+
return f, fi, nil
41+
}
42+
43+
func readManifest(fs http.FileSystem) map[string]string {
44+
manifestMutex.Lock()
45+
var assetMap map[string]string
46+
47+
f, fi, err := readManifestFile(fs)
48+
if err != nil {
49+
log.Error("[Static] Failed to open %q: %v", manifestName, err)
50+
return assetMap
51+
}
52+
defer f.Close()
53+
54+
bytes, err := io.ReadAll(f)
55+
if err != nil {
56+
log.Error("[Static] Failed to read %q: %v", manifestName, err)
57+
return assetMap
58+
}
59+
60+
err = json.Unmarshal(bytes, &assetMap)
61+
if err != nil {
62+
log.Error("[Static] Failed to parse %q: %v", manifestName, err)
63+
return assetMap
64+
}
65+
66+
manifestModified = fi.ModTime()
67+
manifestMutex.Unlock()
68+
return assetMap
69+
}
70+
71+
// ResolveWithManifest turns /js/index.js into /js/index.5ed90373e37c.js using assets-manifest.json
72+
func ResolveWithManifest(fs http.FileSystem, file string) string {
73+
if len(manifest) == 0 {
74+
manifest = readManifest(fs)
75+
}
76+
77+
// in development, the manifest can frequently change, check and reload if necessary
78+
if !setting.IsProd {
79+
f, fi, err := readManifestFile(fs)
80+
if err != nil {
81+
log.Error("[Static] Failed to open %q: %v", manifestName, err)
82+
} else {
83+
defer f.Close()
84+
}
85+
86+
if fi.ModTime().After(manifestModified) {
87+
manifest = readManifest(fs)
88+
}
89+
}
90+
91+
if mappedFile, ok := manifest[file]; ok {
92+
return mappedFile
93+
}
94+
return file
95+
}

modules/public/manifest_bindata.go

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build bindata
6+
// +build bindata
7+
8+
package public

modules/public/public.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ func AssetsHandlerFunc(opts *Options) http.HandlerFunc {
6969
}
7070

7171
// custom files
72-
if opts.handle(resp, req, http.Dir(custPath), file) {
72+
if opts.handle(resp, req, http.Dir(custPath), file, false) {
7373
return
7474
}
7575

7676
// internal files
77-
if opts.handle(resp, req, fileSystem(opts.Directory), file) {
77+
if opts.handle(resp, req, fileSystem(opts.Directory), file, true) {
7878
return
7979
}
8080

@@ -101,9 +101,14 @@ func setWellKnownContentType(w http.ResponseWriter, file string) {
101101
}
102102
}
103103

104-
func (opts *Options) handle(w http.ResponseWriter, req *http.Request, fs http.FileSystem, file string) bool {
104+
func (opts *Options) handle(w http.ResponseWriter, req *http.Request, fs http.FileSystem, file string, isInternal bool) bool {
105+
// respect webpack assets manifest for internal files
106+
if isInternal {
107+
file = ResolveWithManifest(fs, path.Clean(file))
108+
}
109+
105110
// use clean to keep the file is a valid path with no . or ..
106-
f, err := fs.Open(path.Clean(file))
111+
f, err := fs.Open(file)
107112
if err != nil {
108113
if os.IsNotExist(err) {
109114
return false

modules/templates/helper.go

-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ func NewFuncMap() []template.FuncMap {
150150
"DiffTypeToStr": DiffTypeToStr,
151151
"DiffLineTypeToStr": DiffLineTypeToStr,
152152
"ShortSha": base.ShortSha,
153-
"MD5": base.EncodeMD5,
154153
"ActionContent2Commits": ActionContent2Commits,
155154
"PathEscape": url.PathEscape,
156155
"PathEscapeSegments": util.PathEscapeSegments,

0 commit comments

Comments
 (0)