Как исправить ошибку обновления с помощью Echo и Angular

Я настраиваю веб-сервер с Go (используя Echo) в качестве бэкэнда и Angular 6 в качестве внешнего интерфейса. Что я делаю, так это создаю простое приложение, используя Angular-cli 'ng new my-app', добавляю компонент helloworld и маршрут '/helloworld', а затем встраиваю его в производство с помощью 'ng build --prod', которое выдает как 'dist папка. Структура папки:

dist
├── assets
│   ├── icons
│   └── logo.png
├── favicon.ico
├── index.html
├── main.js
├── polyfills.js
├── runtime.js
└── styles.css

Затем я хочу, чтобы Go обслуживал статические файлы в этой папке dist с помощью следующего кода main.go

func main() {
    e := echo.New()
    e.Static("/", "dist")
    e.File("/", "dist/index.html")
    e.Start(":3000")
}

Теперь, когда я использую браузер и перехожу на "localhost:3000/", страница будет работать правильно, я могу перемещаться по href благодаря угловой маршрутизации, например: "localhost:3000/home", страница будет отображаться правильно но если я попытаюсь обновить его, то Echo вернет содержимое страницы, которое показывает:

{"Сообщение не найдено"}

Я знаю, что могу настроить маршрут вручную следующим образом:

e.File("/home","dist/index.html")

Однако, если у меня есть намного больше маршрутов, то довольно сложно сделать все это.

Что мне нужно, так это то, что любой маршрут, который не определен для Echo, будет отображен в "index.html". Я попробовал с:

e.File("/*", "dist/index.html")

а также

e.GET("/*", func(c echo.Context) 
    return c.File("dist/index.html")
})

но тогда я получаю пустую страницу с ошибкой

"Uncaught SyntaxError: Unexpected token <  " 

со всеми 3 файлами main.js, polyfill.js и runtime.js

Я новичок в Echo, поэтому я не знаю, как это сделать.

4 ответа

Решение

Проблема не связана строго с Эхо. Angular выполняет маршрутизацию так, что он НЕ запрашивает страницу с сервера. Он изменяет URL-адрес без фактического запроса другой страницы с сервера.

Таким образом, когда вы переходите к "/home", а затем обновляетесь, ваш браузер пытается связаться с сервером и запрашивает "/home" (в отличие от первого раза, браузер запрашивает "/", который сопоставлен с "dist /"). index.html "). "/home" не найден или не определен в маршрутизации Echo. Следовательно, вы получаете сообщение Not Found.

Что я рекомендую вам сделать, это сделать следующее в отношении маршрутизации

e.Static("/dist", "dist")
e.File("/*", "dist/index.html")
e.Start(":3000")

И внутри вашего index.html добавьте "/ dist" перед URL запрошенных ресурсов.

Также есть HTML5 опция в статическом промежуточном программном обеспечении в echo: например

e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
        Root:   "dist",
        Index: "index.html",
        Browse: true,
        HTML5:  true,
    }))

который, кажется, обрабатывает веб-страницы SPA.

Ответ @Seaskyways отлично работает для меня, но мне также удалось найти другое решение после более подробного изучения Echo. У Echo есть NotFoundHandler, который обрабатывает все неизвестные маршруты, поэтому я просто заставляю его возвращать "index.html" каждый раз, когда запрашиваются неопределенные маршруты. Вот мой код:

echo.NotFoundHandler = func(c echo.Context) 
    return c.File("dist/index.html")
}
e := echo.New()
e.Static("/", "dist")
e.Start(":3000")

Я не уверен, что это хороший способ сделать это, но это еще один вариант для тех, у кого такая же проблема, как у меня

Оставив это здесь в качестве альтернативы, на случай, если кому-то понадобится полный пример. Использование «/*» зафиксирует все маршруты, начинающиеся с «/» или любого другого префикса, который не был определен.

      package main

import (
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

const (
    HTTP_PORT = ":1234"
)

func main() {
    e := echo.New()

    // Logger Middleware
    e.Use(middleware.Logger())

    // Setup routes
    SetupRoutes(e)

    e.Logger.Fatal(e.Start(HTTP_PORT))
}

func SetupRoutes(e *echo.Echo) {
    // Catpure route /
    e.GET("/", getWebApp)
    
    // Catpure route /test
    e.GET("/test", getTest)
    
    // Catpure all routes starting with / that haven't been defined 
    e.GET("/*", getWebApp)
    
    // Use e.Any() for all request methods GET, PUT, POST, PATCH and DELETE
    e.Any("/*", getWebApp)
}

func getWebApp(ctx echo.Context) error {
    return ctx.File("../website_src/index.html")
}

func getTest(ctx echo.Context) error {
    return ctx.String(http.StatusOK, "Hello")
}
Другие вопросы по тегам