Embedding a React Application in Go Binary
Mar 22, 2021
Go 1.16 has come out with a feature which I waited for quite some time. With Embed we will be able to add static files into the go binary at build time. It also makes accessing the files as simple as dealing with File System APIs.
This has opened up a whole new world on building and deploying web applications. Now we can embed static web apps along with the API server built in Go. In this article, we are going to explore how we can embed a React application in Go binary at build time.
First, let us create a React application using Create-React-App.
npx create-react-app react-app
Once the application is created, we will have the default App
component which
shows the React icon. We are not going to change it. We are just going to use it
as it is and embed. So let’s build the app, so that we can get the static files
from the build
folder.
npm run build
Create a folder in which we are going to code the Go application. Copy the
build
folder into the newly created folder.
/
|-build
| |- React build files here
|-main.go
package main
import (
"embed"
"fmt"
"io/fs"
"net/http"
)
//go:embed build
var embeddedFiles embed.FS
func main() {
fmt.Println("Starting Server")
http.Handle("/", http.FileServer(getFileSystem()))
http.ListenAndServe(":9000", nil)
}
func getFileSystem() http.FileSystem {
// Get the build subdirectory as the
// root directory so that it can be passed
// to the http.FileServer
fsys, err := fs.Sub(embeddedFiles, "build")
if err != nil {
panic(err)
}
return http.FS(fsys)
}
Notice the directive go:embed build
. The variable embeddedFiles
will be initialized with a reference to the File System containing the build
folder
as a subdirectory.
go build main.go
Now build the Go application, get the binary and run it wherever you
want and go to http://localhost:9000
, you will see the React appliation. It
is a single binary containing all the static assets. Easy to deploy or distribute.
This open’s up a lot of possibilities. We can embed multiple small frontend applications into a Go binary and they can work together. Everything that can be done on nginx can be very well done using Go while still having all assets packed together.