Сегодня мы попытаемся встроить приложение React в двоичный файл Go. Пожалуйста, посмотрите видео на youtube ниже, чтобы узнать больше о потрясающих вещах. Мы создадим REST API Golang с помощью Echo и React-приложение с помощью Vite. После этого мы создадим один двоичный файл/исполняемый файл, содержащий как API, так и веб-приложение.
- Предварительные условия
- Создание нашего проекта Go
- Создание базовой конечной точки маршрута API с помощью echo
- Создание нашего React-приложения с помощью Vite
- Изменение файла package.json
- Обслуживание наших статических файлов с помощью Echo
- Импорт нашей веб-функции RegisterHandlers в файл main.go
- Теперь, если вы зайдете на сайт http://localhost:8080 в браузере, вы должны увидеть React-приложение vite по умолчанию.
- Выполнение запроса к серверу Go API из React
- Если мы зайдем на сайт http://localhost:8080, вас должно встретить сообщение «Hello world», которое приходит с сервера Go API.
- Действительно плохой опыт разработки
- Компиляция двоичных файлов
- Поздравляем! Вы создали один двоичный файл go, который содержит как ваш API, так и ваше React-приложение!
Предварительные условия
- Go версии
1.18.3
- Yarn версии
1.22.18
- Node версия
v16.15.1
Создание нашего проекта Go
Сначала мы создадим наш Go-проект.
mkdir go-react-demo
cd go-react-demo
touch main.go
Затем мы хотим установить Echo, который является веб-фреймворком (аналогичным Gin, Fiber и т.д.).
go get github.com/labstack/echo/v4
Создание базовой конечной точки маршрута API с помощью echo
В вашем файле main.go
напишите:
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/api", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":8080"))
}
Это создаст базовую конечную точку API, которая возвращает Hello, World!
после отправки запроса GET
на адрес http://localhost:8080/api
Мы также можем проверить это, выполнив:
curl http:localhost:8080/api # <-- Should output "Hello, World!"
Если все работает нормально, далее мы создадим наше React приложение с помощью Vite
Создание нашего React-приложения с помощью Vite
Убедитесь, что вы находитесь в корневом каталоге проекта, затем запустите:
yarn create vite
# Set the "project name" to "web"
# Set the "web framework" to "react" & "react-ts"
После того, как Vite
закончит загрузку нашего проекта, давайте убедимся, что все зависимости установлены
cd web
yarn install
Изменение файла package.json
Мы немного изменим файл package.json
, а именно команду dev
. Мы не хотим обслуживать приложение react с помощью сервера по умолчанию vite
. Мы хотим сами обслуживать статические файлы с помощью Go. Мы хотим, чтобы vite
пересоздавал статические файлы только после внесения изменений (live-reload).
"scripts": {
"dev": "tsc && vite build --watch", <-- Change dev script to this
"build": "tsc && vite build",
"preview": "vite preview"
},
Изменение команды dev
на tsc && vite build --watch
говорит vite
пересобрать статические файлы после внесения в них изменений.
Попробуйте запустить yarn dev
в каталоге web
, чтобы сгенерировать статические файлы, расположенные в каталоге dist
.
# In go-react-demo/web
yarn run dev
На данном этапе структура папок будет выглядеть следующим образом:
go-react-demo/
├─ web/
│ ├─ dist/
│ ├─ public/
│ ├─ src/
| ├─ ...
├─ main.go
├─ go.sum
├─ go.mod
Обслуживание наших статических файлов с помощью Echo
Мы создадим файл web.go
в каталоге web
.
// In go-react-demo/web/web.go
package web
import (
"embed"
"github.com/labstack/echo/v4"
)
var (
//go:embed all:dist
dist embed.FS
//go:embed dist/index.html
indexHTML embed.FS
distDirFS = echo.MustSubFS(dist, "dist")
distIndexHtml = echo.MustSubFS(indexHTML, "dist")
)
func RegisterHandlers(e *echo.Echo) {
e.FileFS("/", "index.html", distIndexHtml)
e.StaticFS("/", distDirFS)
}
Здесь мы создаем маршрут /
и обслуживаем статические файлы, созданные Vite, включая web/index.html
и сопровождающие его статические активы.
Импорт нашей веб-функции RegisterHandlers
в файл main.go
Вернемся к нашему файлу main.go
. Импортируем функцию RegisterHandlers
, которую мы открыли в пакете web
.
package main
import (
"net/http"
"go-react-demo/web" # <--- INCLUDE THIS
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
web.RegisterHandlers(e) # <-- INCLUDE THIS
e.GET("/api", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello world!")
})
e.Logger.Fatal(e.Start(":8080"))
}
Теперь давайте протестируем go-сервер, чтобы проверить, правильно ли он обслуживает статические активы нашего react-приложения. Перейдите в корневой каталог проекта & run:
go run main.go
Теперь, если вы зайдете на сайт http://localhost:8080 в браузере, вы должны увидеть React-приложение vite по умолчанию.
Выполнение запроса к серверу Go API из React
Теперь давайте попробуем сделать GET
запрос к серверу Go API из нашего приложения React, которое также обслуживается сервером Go… Похоже, что здесь происходит что-то непонятное. Пожалуйста, добавьте следующее:
// In go-react-demo/web/src/App.tsx
import { useState, useEffect } from "react";
import "./App.css";
function App() {
const [data, setData] = useState("");
useEffect(() => {
const fetchData = async () => {
const response = await fetch("http://localhost:8080/api");
const data = await response.text();
setData(data);
};
fetchData().catch((err) => console.log(err));
}, []);
return (
<div className="App">
<h1>{data}</h1>
</div>
);
}
export default App;
Теперь нам нужно перегенерировать статические файлы React, поскольку мы внесли изменения.
# assuming you're currently at the rootDirectory (go-react-demo)
cd web && yarn run dev # Generates the new static assets
Затем нам нужно запустить сервер go для обслуживания файлов
cd .. && go run main.go
Если мы зайдем на сайт http://localhost:8080, вас должно встретить сообщение «Hello world», которое приходит с сервера Go API.
Действительно плохой опыт разработки
Я уверен, что вы заметили, что постоянный запуск двух терминалов с разными процессами — это очень плохой опыт разработки, но не бойтесь, у меня есть решение!
Мы собираемся установить air. air
— это что-то вроде nodemon
, но для go
. air
позволяет нам иметь горячую перезагрузку с помощью go, так что нам не нужно вручную выполнять команду go run main.go
каждый раз, когда мы вносим изменения.
Чтобы установить air
, выполните следующие действия.
go install github.com/cosmtrek/air@latest
Затем необходимо создать файл конфигурации для air
, что просто делается через run:
#You should be in the root directory of the go-react-demo project
air init # Should output a `.air.toml`
Теперь последний шаг в создании лучшего опыта разработки. Если вы используете wsl
Создайте файл dev.sh
в корневом каталоге вашего проекта
touch dev.sh # creates the file
Измените сценарий dev.sh
таким образом, чтобы он содержал
#!/bin/sh
cd web && yarn dev & air && fg
Это позволит запустить оба go api сервера & vite build server параллельно в одном терминале.
Компиляция двоичных файлов
Теперь, момент истины: для компиляции двоичных файлов, содержащих React-приложение, просто выполните команду
go build main.go
Если вы пытаетесь собрать двоичные файлы windows из WSL:
env GOOS=windows GOARCH=amd64 go build main.go
# You may have a different $GOARCH so please do some research
Поздравляем! Вы создали один двоичный файл go, который содержит как ваш API, так и ваше React-приложение!