How to serve a NextJs frontend using Golang (Go) and gorilla/mux?
Asked Answered
S

1

6

I followed this example for serving a NextJs front end single-page application using Golang and the native net/http package:

import (
    "embed"
    "io/fs"
    "log"
    "net/http"
    "runtime/pprof"
)

//go:embed nextjs/dist
//go:embed nextjs/dist/_next
//go:embed nextjs/dist/_next/static/chunks/pages/*.js
//go:embed nextjs/dist/_next/static/*/*.js
var nextFS embed.FS

func main() {
    // Root at the `dist` folder generated by the Next.js app.
    distFS, err := fs.Sub(nextFS, "nextjs/dist")
    if err != nil {
        log.Fatal(err)
    }

    // The static Next.js app will be served under `/`.
    http.Handle("/", http.FileServer(http.FS(distFS)))
    // The API will be served under `/api`.
    http.HandleFunc("/api", handleAPI)

    // Start HTTP server at :8080.
    log.Println("Starting HTTP server at http://localhost:8080 ...")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

and it works. Now I want to use gorilla/mux instead of the native net/http package. So now my main function looks like this:

func main() {

    // Root at the `dist` folder generated by the Next.js app.
    distFS, err := fs.Sub(nextFS, "nextjs/dist")
    if err != nil {
        log.Fatal(err)
    }

    r := mux.NewRouter()
    r.Handle("/", http.FileServer(http.FS(distFS)))

    srv := &http.Server{
        Handler: r,
        Addr:    "0.0.0.0:8080",
        // Good practice: enforce timeouts for servers you create!
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }

    log.Fatal(srv.ListenAndServe())
}

This works for serving the index.html file when I navigate to localhost:8080 in the browser, but the page has no styling, no images, and no JavaScript.

I tried using the instructions at gorilla/mux for serving SPAs, but for this Next.js application, it could not find the files and the browser would error out with a connection reset error.

What else do I need to do to for the CSS, JavaScript, and images to be available when the page is loaded?

Symposium answered 29/12, 2021 at 4:25 Comment(1)
The stdlib Handle function works with a prefix (note the terminating slash), whereas gorilla mux Handle deals with patterns. So the pattern / will match exactly that. Try `r.PathPrefix("/").Handle(...))Thornhill
U
4

Please, try

    r.PathPrefix("/").Handler(http.FileServer(http.FS(distFS)))

gorilla/mux interprets the first argument of the Handle function as a template: https://pkg.go.dev/github.com/gorilla/mux#Route.Path.

Please, mind the order when adding routes: when two routes match the same path, the first added one wins.

Unparliamentary answered 31/12, 2021 at 5:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.