Одна из самых крутых возможностей Go. Встраивание ReactJS в двоичный файл с помощью Go

Сегодня мы попытаемся встроить приложение React в двоичный файл Go. Пожалуйста, посмотрите видео на youtube ниже, чтобы узнать больше о потрясающих вещах. Мы создадим REST API Golang с помощью Echo и React-приложение с помощью Vite. После этого мы создадим один двоичный файл/исполняемый файл, содержащий как API, так и веб-приложение.

Предварительные условия

  • 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-приложение!

Оцените статью
devanswers.ru
Добавить комментарий