Как исправить ошибку обновления с помощью 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")
}