Go语言网站缓存css和js文件(使用sync.map)
一般css和js这类文件非常小,网站上线后就不怎么改了,每个用户来访问都要进行磁盘I/O会感觉有些浪费,所以建议存在内存里。go语言里面有实现文件服务器的代码,例如,将url中的js指向实际目录中 html 目录下的 js 目录,通常大家都是这样写的:
http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./html/js"))))
看了一下golang源代码,http.StripPrefix
函数中的第二个参数实际上也是一个http.Handler
,所以我们只需要定义一个带有ServeHTTP()方法的对象就可以了,以缓存css文件为例。
type cssFile struct{}
func (x *cssFile) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path := "./html/style/" + strings.ToLower(r.URL.Path)
// 根据路径载入文件缓存
buf, err := loadFile(path)
if err != nil {
http.NotFound()(w, r)
return
}
// 这里一定要设置请求头 response
w.Header().Set("Content-Type", "text/css; charset=utf-8")
w.Write(buf)
}
// sync 库里支持并发的 map
var mk = new(sync.Map)
// loadFile 载入文件缓存
// 可以使用 redis 或 freecache 这类缓存中间件、也可以使用 sync.map
func loadFile(path string) ([]byte, error) {
pathMd5 := fmt.Sprintf("%x", md5.Sum([]byte(path)))
key := "file:cache:path:key:" + pathMd5
// 读取缓存
if ret, ok := mk.Load(key); ok && ret != nil {
println("found cache of path " + path)
return ret.([]byte), nil
}
buf, err := os.ReadFile(path)
if err != nil {
return nil, errors.New("读取文件错误")
}
// 写入缓存
mk.Store(key, buf)
return buf, nil
}
写完了上面这个方法,我们只需要小改一下文件服务器声明那一块代码就可以了:
http.Handle("/style/", http.StripPrefix("/style/", new(cssFile)))
要特别注意,如果是用默认的方式去输出css,请求头是这样的:
设置为缓存之后请求头变成了这样
所以得手动把请求头的 Content-Type 设置为 text/css。js比较特殊,如果是在js中有代码引入了css文件,则需要对css单独处理,因此要检查它的文件后缀来判断应该返回什么样的请求头,否则会出现返回的是css文件,但请求头却写着 Content-Type: application/javascript
,这会导致页面样式错乱。
另外,默认情况下浏览器会自动缓存当前网页的css和js文件。只要不强制刷新,你的css和js一直是那一份,通常前端开发要更新这两种文件的时候,都得在它们背后加上一些随机数或者版本号,这样浏览器才会重新拉取,否则如果修改了样式代码,可能用户加载的那一份还是旧的。
<!-- 在后面加版本号或随机数 -->
<link rel="stylesheet" href="/style/style.css?v=0.0.1" />
声明: 因编程语言版本更新较快,当前文章所涉及的语法或某些特性相关的信息并不一定完全适用于您当前所使用的版本,请仔细甄别。文章内容仅作为学习和参考,若有错误,欢迎指正。
开发者
专题·造轮子
Golang·热门
相关文章