golang取代nginx佈置前端項目(vue),mime問題,Resource interpreted as Stylesheet but transfe...
前言:某些原因,想直接使用go編譯生成的可執行文件+前端編譯好的靜態文件,直接佈置項目,不用依賴於nginx。
想看結果的同學直接拉到最下面看代碼和總結
開始探索:
首先想到的是golang路由中指向靜態資源
知識點:http中的ServeFile方法和FileServe,這兩個很像,這裏使用第一個,區分自己去查,這個一般
只需要在你的HandlerFunc中指向你的資源地址,就可以反饋,這裏本地使用了一個測試html,結果沒問題
http.ServeFile(w, r, "./test.html")
你以爲成功了,不不不,實際佈置後馬上給你出問題了
正式環境是這樣的,因爲靜態資源放在同一級目錄
http.ServeFile(w, r, "./dist/index.html")
問題發現(出現新問題):
訪問地址,啥也沒有~~~,檢查問題,發現
image.png
這兩句話:
Resource interpreted as Stylesheet but transferred with MIME type text/plain: "http://localhost:5001/css/app.5e843a4a.css". localhost/:1 Resource interpreted as Stylesheet but transferred with MIME type text/plain: "http://localhost:5001/css/chunk-vendors.43fc3011.css".
他說的大概意思是這個css解析的不對,直接變成文本傳輸的了,然後就發現mime這個是啥呢,查了一下資料,叫“多用途互聯網郵件擴展類型”,就是文件類型解析的時候對應哪一個類型來解析,比如說這裏,“.css”文件應該用“text/css”來解析,但是他用錯了,所以變成了文本。
繼續查資料。
看到了一句話,說是加一句
w.Header().Add("Content-Type", "text/plain")
這樣不對,反饋的直接變成文本了,雖然錯誤沒了,但是我要的是html顯示啊~~~~,排除
image.png
問題發現,與mime相關(出現新問題)
終於,找到了原因,查閱相關資料得出,nginx有自己的mime文件,所以不會有問題,
使用go的程序執行時,調用的是系統的mime文件,可能會出現問題。
找到問題了,當然就知道怎麼做了,直接搜索,golang mime,看看有沒有解決辦法,還真的有這個包“mime”,內容也簡單,就幾個函數,具體的就不說了,就說這裏用到的。
func init() { mime.AddExtensionType(".js", "text/javascript") mime.AddExtensionType(".css", "text/css; charset=utf-8") }
在init中增加這個方法,意思是,告訴他,這個類型的文件,用後面這種方式去解析,別搞錯了,他就知道了。繼續測試,看看是否成功呢!
果然不出所料,還是不行(如果是線上服務器環境,這裏可能會有404資源錯誤)~~~
image.png
問題解決(方法正確):
爲什麼呢,想不通~~~,繼續查資料,擦查了好久都沒有發現問題,突然,看到了這個路由,聯想到剛剛出現的404,突然想到,方法是對了,可能資源路徑不對吧。
http://localhost:3000/css/chunk-vendors.43fc3011.css
就像上面出現的這個路徑,他肯定不對啊,肯定沒有這個資源啊,懷着試一試的態度,調整一下自己的路由,加上下面這個代碼
if paths[0] == "css" || paths[0] == "js" || paths[0] == "fonts" { str, err := os.Getwd() if err != nil { logrus.WithFields(logrus.Fields{"path": err.Error()}).Warn("getwd") return } http.ServeFile(w, r, filepath.Join(str, "dist", paths[0], paths[len(paths)-1])) return }
測試了一下,居然成功了,哇哇哇哇,哈哈哈哈哈
image.png
最後總結一下:
1.完整資源佈置需要的幾步
1.1.需要自己調節url的資源訪問路徑,並將它們用ServeFile指向你的index.html,css,js等資源(這一步很難想到,中間可能會有404的錯誤,不過只有正式線上纔有,本地不會有,所以浪費了很多時間)
1.2.使用mime包,使得go程序可以正確解析靜態資源文件類型
2.測試總代碼(我這裏vue生成的dist文件夾放在可執行文件同一級,你們需要注意自己的路徑):
package main import ( "mime" "net/http" "net/url" "os" "path/filepath" "strings" "github.com/Sirupsen/logrus" ) func init() { mime.AddExtensionType(".js", "text/javascript") mime.AddExtensionType(".css", "text/css; charset=utf-8") } func main() { http.Handle("/", http.HandlerFunc(httpProcess)) http.ListenAndServe(":5001", nil) } func httpProcess(w http.ResponseWriter, r *http.Request) { if r.URL.String() == "/" { str, err := os.Getwd() if err != nil { logrus.WithFields(logrus.Fields{"path": err.Error()}).Warn("getwd") return } http.ServeFile(w, r, filepath.Join(str, "dist", "index.html")) //反饋靜態主頁,需要下面css,和js以及fonts的資源路徑配合 return } paths, err := parsePaths(r.URL) //這裏的path反饋工作元素內容待定 if err != nil { logrus.Error(err) w.WriteHeader(http.StatusBadRequest) w.Write(nil) return } if paths[0] == "css" || paths[0] == "js" || paths[0] == "fonts" { str, err := os.Getwd() if err != nil { logrus.WithFields(logrus.Fields{"path": err.Error()}).Warn("getwd") return } http.ServeFile(w, r, filepath.Join(str, "dist", paths[0], paths[len(paths)-1])) return } } //解析url func parsePaths(u *url.URL) ([]string, error) { paths := []string{} pstr := u.EscapedPath() for _, str := range strings.Split(pstr, "/")[1:] { s, err := url.PathUnescape(str) if err != nil { return nil, err } paths = append(paths, s) } return paths, nil } l
附錄:還可以使用一個縮小包,來減少靜態資源中的大小 github.com/tdewolff/minify
,就是這個,使用起來也簡單,這裏就不多說了
歡迎關注我們的微信公衆號,每天學習Go知識