Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static file server by Golang for serving Vue.js app

Tags:

go

vue.js

I want to create a simple file server in Go for serving static files of a Vue.js app.

By default Vue.js has its own runner using npm run dev or npm run build.

The point is when I run Vue.js app by its own tooling system, it falls back 404 error to index.html. So Vue-router can handle the rest.

How can I handle that in Go?

I tried httprouter and its NotFound method as the documentation mentioned, but it only serves static files if there is no defined route on the Router.

like image 496
amirhosseinab Avatar asked Jan 19 '18 18:01

amirhosseinab


People also ask

Does Vuejs need a server?

But Vue doesn't use any server-side language! It's - after your ran npm run build - just a bunch of JavaScript and CSS files as well as the index. html file. You don't need a Node server for that!

Which database is best for Vue?

Django is a python-based framework that could be a very reliable choice for the Vuejs backend. Particularly, you can consider Django for Vue JS applications that need good load time and security. Besides, Django comes with a database, ORM, authentication libraries, and a templating engine as part of its core.

Can Vue run locally?

Running the app locallyThe Vue CLI comes with a built-in development server. This allows you to run your app locally so you can test it easily without needing to configure a server yourself.


3 Answers

Assuming a folder structure like below

enter image description here

You can use the following golang code to serve the static files. I've added an extra api to show how we could have that as well. gorilla-mux is used for URL routing.

I've taken the built distribution to serve via golang. And index.htmllooks like this

<!DOCTYPE html>
<html>

<head>
  <meta charset=utf-8>
  <link rel=stylesheet href=static/normalize.css>
  <title>vue-spa</title>
  <link href=./static/css/app.6fde27bf4e24b3395514fd5ee0329156.css rel=stylesheet>
</head>

<body>
  <div id=app></div>
  <script type=text/javascript src=./static/js/manifest.6fd2c38fc83e93a893ff.js></script>
  <script type=text/javascript src=./static/js/vendor.bc5a61acb9e2b4c6e037.js></script>
  <script type=text/javascript src=./static/js/app.c8f0b049292d256d1e93.js></script>
</body>

</html>

Note that it's base for static files is ./static

package main

import (
    "encoding/json"
    "net/http"
    "os"
    "time"
    "log"
    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter()
    // It's important that this is before your catch-all route ("/")
    api := r.PathPrefix("/api/").Subrouter()
    api.HandleFunc("/users", GetUsersHandler).Methods("GET")
    // Serve static assets directly.
    r.PathPrefix("/static").Handler(http.FileServer(http.Dir("dist/")))
    // Catch-all: Serve our JavaScript application's entry-point (index.html).
    r.PathPrefix("/").HandlerFunc(IndexHandler("dist/index.html"))


srv := &http.Server{
        Handler: handlers.LoggingHandler(os.Stdout, r),
        Addr:    "127.0.0.1:8088",
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }
    log.Fatal(srv.ListenAndServe())
}

func IndexHandler(entrypoint string) func(w http.ResponseWriter, r *http.Request) {
    fn := func(w http.ResponseWriter, r *http.Request) {
        http.ServeFile(w, r, entrypoint)
    }
    return http.HandlerFunc(fn)
}

func GetUsersHandler(w http.ResponseWriter, r *http.Request) {
    data := map[string]interface{}{
        "id": "123",
        "timeStamp": time.Now().Format(time.RFC3339),
    }
    b, err := json.Marshal(data)
    if err != nil {
        http.Error(w, err.Error(), 400)
        return
    }
    w.Write(b)
}
like image 165
Anuruddha Avatar answered Oct 21 '22 10:10

Anuruddha


This is how I serve our Vue.js single page app

router := mux.NewRouter()
// we have a single page application
// we need to catch all routes and redirect them to the app's entrypoing (index.html)
wwwFiles := http.Dir("./static/www")
wwwPath := "/"
wwwHandler := http.FileServer(wwwFiles)
wwwRouter := router.PathPrefix(wwwPath).Handler(http.StripPrefix(wwwPath, wwwHandler))
// define a Matcher host in case you want to use the '/' path to serve other content
// the regex is for eventual dev/qa/... environments
wwwRouter.Host("www{_:|[a-z]*}.my.app")
// redirect all requests starting with '/' to the 'www' path which index.html will catch
wwwRouter.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, wwwFiles)
})
like image 45
leonardo Avatar answered Oct 21 '22 12:10

leonardo


I wrote this little package that mimics parts of the standard fs.go functionality and use it.

https://github.com/amirhosseinab/sfs

like image 1
amirhosseinab Avatar answered Oct 21 '22 11:10

amirhosseinab