Serving Static Sites with Go
Tags: go, react, tutorial
Published: 2021-05-16 15:59:34

---
title: Serving Static Sites with Go
published: true
description: Serving static sites with go using a static bundle.
tags: go, react, tutorial
cover_image: https://images.unsplash.com/photo-1595045051853-05ef47bdfdbe?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80
---

During a team meeting this week, I was given the task to see if we could bundle and serve our static react code inside of a Go server and produce a single binary that would be placed inside a docker container and can be run at any point to serve our site.

* [Link](https://github.com/esslamben/golang-react) to the Github repository if you just want to have a look at structure.

## Prerequisite
* Go
* Docker

## Folder Structure
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwnql7x7uqaxpcmtqtk7.png)

What you want to do first is create an empty folder with your project name in your go path. For the purpose of keeping this guide simple I will keep all the code very basic and only have two top level folders as the point of the article is to explain how to link these individual tools.

My two top level folders will be `cmd` which will contain all my go code and will be the main entry point for the application. The second will be web which will contain my JavaScript code.

## The Go Side
Let’s start by going inside of our cmd folder and creating a new folder with our project name, mine will be called golang-react.

Inside of this folder you want to create a `main.go` file which will be the entry point for our server and will be the code that we use to create the binary.
Before copying the below code you will want to install two go packages

* echo which is a high performance, minimalist Go web framework which you can install by running.`go get -u. github.com/labstack/echo/...`

* `go.rice` which makes working with resources such as html, JS, CSS, images, templates very easy. `go get github.com/GeertJohan/go.rice` `github.com/GeertJohan/go.rice/rice`

The basic idea here is that we are using the rice box package to find our react build folder and generates a single Go source file called `rice-box.go`. The generated go file contains all assets. The Go tool compiles this into the binary and allows us to serve our web application as a single binary.

## The React Side
I think a better name for this section could be The JavaScript Side as it really doesn’t matter what framework/no framework setup you have as long as you are able to produce a static bundle. However due to the current eco system and the fact that I use react at work I will create our bundle using create react app.

What you want to do first is `cd` into the web folder within our application and create a new folder and name it whatever your react app is called. You can then run `npx create-react-app` to create a react application within the current folder which will create a boiler plate react application for us.

## How to run it
At this point we have everything we need to get started and we can actually create a go binary with our assets bundled and run it. We should still be in our web/projectname folder in our terminal so you can just run yarn build which will produce a static bundle for us.

You should now navigate to your cmd/projectname in our terminal and run our go.rice build command `rice embed-go` which will find our asset references and compile them so that they can be bundled alongside our final binary. This will create a rice-box.go file in the same folder.

For the final step we just want to run `go build .` to create a binary in our current location. It should create a binary with your project name which you can run by typing `./projectname` in your terminal which should serve our application.

## The Docker Side (Optional)
This part is optional as we’ve already created our binary. What this step will let you do is create the binary and run it as a docker container.

The basics of the code below is we split our our image build process in three steps.

1. The first step is we spin up a node container that has access to `npm` and `yarn`, copy over our react code including our `package.json` and `yarn.lock` file so that we persist package versions, we run a `yarn` to pull all our packages and finally run a `yarn build` to build a static version of the site

2. The second step spins up a go server and copies all our local code to the equivalent path on our go server. It then copies our frontend build folder in to the `/web/frontend/` folder ready for us to compile it. We then change our `WORKDIR` to our `cmd/golang-react` folder and run our `rice embed-go` and `GOOS=linux GOARCH=amd64 go build -o golang-react.linux.x86_64 .` to create a linux binary.

3. The final step creates a very simple alpine server. We copy our binary to the new container and set the entry path.

Only thing left to do is set up our `docker-compose.yml` and expose the port to our local port equivalent so we can view the website.

Run `docker-compose up` --build to build and spin up our new container. You should see the following in your terminal.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhz6dncrrgivfqa8bg49.png)

You can now visit `http://localhost:1323` and you should see your new react application.