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
.
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!
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.
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.
Assuming a folder structure like below
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.html
looks 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)
}
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)
})
I wrote this little package that mimics parts of the standard fs.go
functionality and use it.
https://github.com/amirhosseinab/sfs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With