美文网首页
golang取代nginx布置前端项目(vue),mime问题,

golang取代nginx布置前端项目(vue),mime问题,

作者: 哆啦在这A梦在哪 | 来源:发表于2020-07-03 14:56 被阅读0次

    前言:某些原因,想直接使用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的错误,不过只有正式线上才有,本地不会有,所以浪费了很多时间),也就是说ServeFile函数第二个参数指向的是你需要反馈的html文件地址

    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的资源路径配合
    //这里的第二个参数就是你要反馈的资源地址,也就是类似index.html的完整路径
            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,就是这个,使用起来也简单,这里就不多说了

    相关文章

      网友评论

          本文标题:golang取代nginx布置前端项目(vue),mime问题,

          本文链接:https://www.haomeiwen.com/subject/bzirqktx.html