fix: 修复静态资源哈希 key 与模板 URL 路径不匹配导致版本号全为 0
- 重构 walkStaticDir 统一处理三个 static 目录 - URL key 基于文件相对于 static 目录的路径,不含主题目录名
This commit is contained in:
@ -11,7 +11,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"metazone.cc/metalab/internal/model"
|
"metazone.cc/metalab/internal/model"
|
||||||
|
|
||||||
@ -19,81 +18,44 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// assetHashes 静态资源文件哈希表(URL 路径 → 短哈希,文件不变哈希不变)
|
// assetHashes 静态资源文件哈希表(URL 路径 → 短哈希,文件不变哈希不变)
|
||||||
var (
|
var assetHashes map[string]string
|
||||||
assetHashes map[string]string
|
|
||||||
assetOnce sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
// ComputeAssetHashes 遍历 static 目录,计算每个文件的 CRC32作为版本号
|
// ComputeAssetHashes 遍历 static 目录,计算每个文件的 CRC32 作为版本号
|
||||||
func ComputeAssetHashes(templateDir string) {
|
func ComputeAssetHashes(templateDir string) {
|
||||||
assetHashes = make(map[string]string)
|
assetHashes = make(map[string]string)
|
||||||
staticDir := filepath.Join(templateDir, "static")
|
// 前端主题:templates/MetaLab-2026/static → URL /static/
|
||||||
filepath.WalkDir(staticDir, func(path string, d fs.DirEntry, err error) error {
|
walkStaticDir(filepath.Join(templateDir, "static"), "/static")
|
||||||
if err != nil || d.IsDir() {
|
// 共享资源:templates/shared/static → URL /shared/static/
|
||||||
return nil
|
walkStaticDir(filepath.Join(filepath.Dir(templateDir), "shared", "static"), "/shared/static")
|
||||||
}
|
// 管理后台:templates/admin/static → URL /admin/static/
|
||||||
// 只处理 .js 和 .css
|
walkStaticDir(filepath.Join(filepath.Dir(templateDir), "admin", "static"), "/admin/static")
|
||||||
ext := filepath.Ext(path)
|
|
||||||
if ext != ".js" && ext != ".css" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
h := crc32.ChecksumIEEE(data)
|
|
||||||
shortHash := strconv.FormatUint(uint64(h), 16)
|
|
||||||
// 生成 URL 路径:/static/...
|
|
||||||
rel, _ := filepath.Rel(filepath.Dir(templateDir), path)
|
|
||||||
urlPath := "/" + filepath.ToSlash(rel)
|
|
||||||
assetHashes[urlPath] = shortHash
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
// 也处理 shared/static 目录
|
|
||||||
sharedDir := filepath.Join(filepath.Dir(templateDir), "shared", "static")
|
|
||||||
filepath.WalkDir(sharedDir, func(path string, d fs.DirEntry, err error) error {
|
|
||||||
if err != nil || d.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ext := filepath.Ext(path)
|
|
||||||
if ext != ".js" && ext != ".css" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
h := crc32.ChecksumIEEE(data)
|
|
||||||
shortHash := strconv.FormatUint(uint64(h), 16)
|
|
||||||
rel, _ := filepath.Rel(filepath.Dir(templateDir), path)
|
|
||||||
urlPath := "/" + filepath.ToSlash(rel)
|
|
||||||
assetHashes[urlPath] = shortHash
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
// 也处理 admin/static 目录
|
|
||||||
adminDir := filepath.Join(filepath.Dir(templateDir), "admin", "static")
|
|
||||||
filepath.WalkDir(adminDir, func(path string, d fs.DirEntry, err error) error {
|
|
||||||
if err != nil || d.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ext := filepath.Ext(path)
|
|
||||||
if ext != ".js" && ext != ".css" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
h := crc32.ChecksumIEEE(data)
|
|
||||||
shortHash := strconv.FormatUint(uint64(h), 16)
|
|
||||||
rel, _ := filepath.Rel(filepath.Dir(templateDir), path)
|
|
||||||
urlPath := "/" + filepath.ToSlash(rel)
|
|
||||||
assetHashes[urlPath] = shortHash
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
log.Printf("[AssetHashes] computed %d file hashes", len(assetHashes))
|
log.Printf("[AssetHashes] computed %d file hashes", len(assetHashes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// walkStaticDir 遍历目录,计算每个 .js/.css 的 CRC32,存入 assetHashes
|
||||||
|
func walkStaticDir(dir, urlPrefix string) {
|
||||||
|
filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil || d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ext := filepath.Ext(path)
|
||||||
|
if ext != ".js" && ext != ".css" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
h := crc32.ChecksumIEEE(data)
|
||||||
|
shortHash := strconv.FormatUint(uint64(h), 16)
|
||||||
|
// 生成 URL 路径:urlPrefix + 相对于 dir 的子路径
|
||||||
|
rel, _ := filepath.Rel(dir, path)
|
||||||
|
urlPath := urlPrefix + "/" + filepath.ToSlash(rel)
|
||||||
|
assetHashes[urlPath] = shortHash
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// AssetV 返回指定静态资源的哈希版本号(模板函数)
|
// AssetV 返回指定静态资源的哈希版本号(模板函数)
|
||||||
func AssetV(path string) string {
|
func AssetV(path string) string {
|
||||||
if h, ok := assetHashes[path]; ok {
|
if h, ok := assetHashes[path]; ok {
|
||||||
|
|||||||
Reference in New Issue
Block a user