如何修复 Echo 和 Angular 的刷新错误

How to fix refreshing error with Echo and Angular

我正在设置一个 Web 服务器,使用 Go(使用 Echo)作为后端,Angular6 作为前端。 我所做的是使用 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/' 时,页面将正确提供,由于 Angular 路由,我可以使用 href 导航,例如:'localhost:3000/home' 页面将正确显示,但如果我尝试刷新它,Echo 将 return 页面内容显示:

{"message":"Not Found"}

我知道我可以像这样手动设置路线:

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 的新手,所以我不知道该怎么做。

这个问题与 Echo 没有严格的关系。 Angular 进行路由的方式是它不从服务器请求页面。它更改了 URL 而没有实际从服务器请求另一个页面。

因此,当您转到“/home”,然后刷新时,您的浏览器将尝试访问服务器并向其请求“/home”(与第一次相反,浏览器请求“/”,这是映射到 "dist/index.html")。在 Echo 路由中找不到或未定义“/home”。因此,您会收到一条“未找到”消息。

我建议您执行以下有关路由的操作

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

并在您的 index.html 请求资源的 URL 之前添加“/dist”。

@Seaskyways 的回答对我来说非常有用,但在深入了解 Echo 之后,我也设法找到了另一种解决方案。 Echo 有一个处理所有未知路由的 NotFoundHandler,所以我所做的就是每次请求未定义的路由时将其设置为 returns 'index.html'。这是我的代码:

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

我不确定这是否是一个好方法,但对于像我一样有同样问题的人来说,这是另一种选择

echo 中的静态中间件也有一个HTML5选项: 例如

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

似乎可以处理 SPA 网页。

将此留在这里作为备选方案,以防有人需要完整示例。使用“/*”将捕获任何以“/”开头的路由或您想要的任何尚未定义的前缀。

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")
}