Я создаю приложение веб-сервера, используя Go для сервера, и реагирую на пользовательский интерфейс. Я хотел использовать создать реагирующее приложение, которое помогает настраивать приложения React и экономит нам время на выяснении конфигураций и зависимостей библиотек JS.

Есть много статей о каждом независимом компоненте, но не так много статей о том, как развернуть приложение create react на сервере Go. Попробовав различные решения, описанные в различных документах и ​​статьях, я, наконец, сделал следующее.

Вот какова окончательная структура каталогов:

src/                # contains Go source files
   app/
      server.go       # go server file
      server          # binary executable server file
         client/       # create react app root directory
            build/
               index.html   
               static/
                  css/
                  js/
             node_modules/
                  public/
                  src/

Внешний интерфейс

Каталог нашего приложения содержит нашу программу веб-сервера Go, server.go. Чтобы настроить наше реагирующее приложение, в каталоге приложения запустите

npm create-react-app client

Наш сервер Go будет обслуживать статические файлы из нашего приложения React. Чтобы связать статические файлы, в каталоге клиентского проекта запустите:

npm run build 

Это создаст каталог сборки с мини-файлами JS и CSS. Файл index.html также находится в каталоге сборки.

  • Примечание о пакетах JS. Сборщики JS — это библиотеки JS, которые помещают наш код JS и его зависимости в один файл. Нам нужны сборщики JS, потому что не существует стандарта для указания зависимостей в файлах JS. Мы могли бы записать весь наш JS-код в один гигантский файл. Но если нам нужно разделить наш код на отдельные файлы, нам нужен способ импорта и экспорта кода JS для указания зависимостей. Приложение Create React использует сборщик веб-пакетов для создания и минимизации статических файлов, которые мы затем можем обслуживать с нашего сервера Go. (Подробнее о сборщиках JavaScript)

Бэкэнд

После того, как мы создадим наши статические файлы пользовательского интерфейса, нам нужно обслуживать каталог сборки и статические файлы в build/static.

func main() {
    r := mux.NewRouter()
    buildPath := path.Clean("client/build")
    buildURL := fmt.Sprintf("/%s/", buildPath)
    r.Handle("/", http.FileServer(http.Dir(buildPath)))
r.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("client/build/static"))))
    http.ListenAndServe(":8080", nil)
}

Давайте сломаем это. Функция handle регистрирует шаблон URL-адреса в обработчике, который обрабатывает http-запрос. В первом дескрипторе мы обслуживаем каталог сборки. Мы сообщаем FileServer, что файлы находятся в корневом каталоге client/build. Затем, когда сервер получит запрос на /manifest.json, мы будем обслуживать файл manifest.json с корнем в client/build.

Вторая функция дескриптора обслуживает статические файлы. StripPrefix удаляет указанный префикс из запроса, а затем передает запрос файловому серверу. Поэтому, когда мы получаем запрос на «/static/file.txt», StripPrefrix удаляет «/static/» из пути, а затем перенаправляет обработку запроса на FileServer. Теперь FileServer ищет «App.js» в каталоге «client/build/static». Другой способ увидеть это — удалить указанный префикс и соединить его с корневым каталогом — в этом случае обработчик вернет содержимое в «client/build/static/App.js».

Обработка index.html

Чтобы добраться до файла client/build/index.html, мы добавляем к основной функции еще одну функцию-обработчик. Когда сервер получает запрос на «/index», сервер записывает содержимое «client/build/index.html».

func handleIndex(w http.ResponseWriter, r *http.Request) {
    err := templates.Execute(w, "client/build/index.html")
    if err != nil {
        fmt.Println(err.Error()) . 
        http.Redirect(w, r, "/", http.StatusTemporaryRedirect) 
        return
    }
}
func main() {
    ...
    ...
    r.HandleFunc("/index", handleIndex)
    http.ListenAndServe(":8080", nil)
}

В client/build/index.html есть тег скрипта, src которого — «/static/js/main.js». Наш сервер обработает запрос «/static/js/main.js» и вернет файл в «client/build/static/js/main.js».

Запрос на прокси

Как описано в этом сообщении, нам нужно проксировать запрос на порт на локальном хосте, на котором работает наш сервер Go. (Это связано с тем, что по умолчанию, когда мы запускаем npm start, мы запускаем сервер узла, и реагирующее приложение отправит запрос на сервер узла.) В нашей основной функции наш сервер работает и прослушивает порт 8080. Чтобы проксировать запрос, в package.json, расположенном в каталоге приложения реакции, укажите прокси:

"proxy": "http://localhost:8080/"

Минусы

Приложения React настроены на создание горячей перезагрузки приложения реагирования — приложение перезагружается всякий раз, когда изменяются статические файлы приложения. Однако мы не можем использовать это. Каждый раз, когда мы вносим изменения, мы должны запускать npm run build для сборки пакета JS. После этого мы будем обслуживать обновленные файлы JS в каталоге сборки.