Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ COPY . .
# Copt the frontend build into the expected folder
COPY --from=build-frontend /build/dist ./frontend/dist

RUN CGO_ENABLED=0 go build -buildvcs=false -o ./bin/go-vite ./main.go
RUN CGO_ENABLED=0 ENV=prod go build -buildvcs=false -o ./bin/go-vite ./main.go

FROM alpine:3.14

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
build:
cd frontend && yarn build
go build -buildvcs=false -o ./bin/go-vite ./main.go
ENV=prod go build -buildvcs=false -o ./bin/go-vite ./main.go

dev:
cd frontend && yarn dev & air && fg
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,66 @@ Using `make build`, will build frontend assets and then compile the golang binar
### Build a dockerfile

Using `docker build -t go-vite .`, will use a multistage dockerfile to build the vite frontend code using a node image, then the golang using a golang image, the put the single binary into an alpine image.

## Hot Reloading

Instead of serving static assets from go when we running in dev mode, we will setup a proxy from echo that will route the requests to a running vite dev server, unless the path is prefixed with `/api`, this will allow for the HMR and live reloading to happen just as if you were running `vite dev` but it will also allow for api paths to be served.

All the changes required to take the initial project and support hot module reloading can be found in the [pull request](https://github.com/danhawkins/go-vite-react-example/pull/1)

### Step 1

Change the [package.json](frontend/package.json) to run the standard `vite` instead of the `tsc && vite build --watch`

## Step 2

Update the [frontend.go](frontend/frontend.go) so that when we are running in dev mode we proxy requests to the vite dev server

Import a `.env` file using dotenv which just has `ENV=dev` inside

```golang
import(
_ "github.com/joho/godotenv/autoload"
)
```

If we are running in dev mode, setup the dev proxy

```golang
func RegisterHandlers(e *echo.Echo) {
if os.Getenv("ENV") == "dev" {
log.Println("Running in dev mode")
setupDevProxy(e)
return
}
// Use the static assets from the dist directory
e.FileFS("/", "index.html", distIndexHTML)
e.StaticFS("/", distDirFS)
}

func setupDevProxy(e *echo.Echo) {
url, err := url.Parse("http://localhost:5173")
if err != nil {
log.Fatal(err)
}
// Setep a proxy to the vite dev server on localhost:5173
balancer := middleware.NewRoundRobinBalancer([]*middleware.ProxyTarget{
{
URL: url,
},
})
e.Use(middleware.ProxyWithConfig(middleware.ProxyConfig{
Balancer: balancer,
Skipper: func(c echo.Context) bool {
// Skip the proxy if the prefix is /api
return len(c.Path()) >= 4 && c.Path()[:4] == "/api"
},
}))
}
```

## Step 3

Run `make dev` to start the vite dev server and air for the golang server, changes in the frontend app will now be reflected immediatly.

**IMPORTANT: The go build will faile if frontend/dist/index.html is not available, so even if you are running in dev mode, make sure to run `make build` initially to populate the folder**
30 changes: 30 additions & 0 deletions frontend/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ package frontend

import (
"embed"
"log"
"net/url"
"os"

_ "github.com/joho/godotenv/autoload"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)

var (
Expand All @@ -18,7 +23,32 @@ var (
)

func RegisterHandlers(e *echo.Echo) {
if os.Getenv("ENV") == "dev" {
log.Println("Running in dev mode")
setupDevProxy(e)
return
}
// Use the static assets from the dist directory
e.FileFS("/", "index.html", distIndexHTML)
e.StaticFS("/", distDirFS)
}

func setupDevProxy(e *echo.Echo) {
url, err := url.Parse("http://localhost:5173")
if err != nil {
log.Fatal(err)
}
// Setep a proxy to the vite dev server on localhost:5173
balancer := middleware.NewRoundRobinBalancer([]*middleware.ProxyTarget{
{
URL: url,
},
})
e.Use(middleware.ProxyWithConfig(middleware.ProxyConfig{
Balancer: balancer,
Skipper: func(c echo.Context) bool {
// Skip the proxy if the prefix is /api
return len(c.Path()) >= 4 && c.Path()[:4] == "/api"
},
}))
}
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "tsc && vite build --watch",
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ module github.com/danhawkins/go-vite-react-example

go 1.21.0

require github.com/labstack/echo/v4 v4.11.1
require (
github.com/joho/godotenv v1.5.1
github.com/labstack/echo/v4 v4.11.1
)

require (
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4=
github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
Expand Down