嵌入 SvelteKit 到 Golang 二进制文件中。

3
我正在尝试使用embedd来包含SvelteKit网站的单个二进制文件。我使用Chi作为我的路由器。但是我无法让它工作。我得到了以下其中一种选项。据我所知,embedd的all:选项确保包括以_为前缀的文件。我还尝试了在主V1中的StripPrefix方法中的不同变体:/uibuild/uibuild/等等...
有人能给我一些指导吗? 示例存储库
  1. 目录列表(在我的情况下是`uibuild`)
  2. 在chrome控制台上,根路径"/"显示空白页面,但是嵌套文件返回404
  3. 主页"/"返回404。

Svelte 配置:
import preprocess from "svelte-preprocess";
import adapter from "@sveltejs/adapter-static";

/** @type {import('@sveltejs/kit').Config} */
const config = {
  kit: {
    adapter: adapter({
      pages: "./../server/uibuild",
      assets: "./../server/uibuild",
      fallback: "index.html",
    }),
  },

  preprocess: [
    preprocess({
      postcss: true,
    }),
  ],
};

export default config;

Main.go V1:

这会导致错误3。

package main

import (
    "embed"
    "log"
    "net/http"

    chi "github.com/go-chi/chi/v5"
)

//go:embed all:uibuild
var svelteStatic embed.FS

func main() {

    r := chi.NewRouter()

    r.Handle("/", http.StripPrefix("/uibuild", http.FileServer(http.FS(svelteStatic))))

    log.Fatal(http.ListenAndServe(":8082", r))
}

Main.go V2:

这将会产生错误2。

static, err := fs.Sub(svelteStatic, "uibuild")
    if err != nil {
        panic(err)
    }

r := chi.NewRouter()
r.Handle("/", http.FileServer(http.FS(static)))

log.Fatal(http.ListenAndServe(":8082", r))

文件结构:
.
├── go.mod
├── go.sum
├── main.go
└── uibuild
    ├── _app
    │   ├── immutable
    │   │   ├── assets
    │   │   │   ├── 0.d7cb9c3b.css
    │   │   │   └── _layout.d7cb9c3b.css
    │   │   ├── chunks
    │   │   │   ├── index.6dba6488.js
    │   │   │   └── singletons.b716dd01.js
    │   │   ├── entry
    │   │   │   ├── app.c5e2a2d5.js
    │   │   │   └── start.58733315.js
    │   │   └── nodes
    │   │       ├── 0.ba05e72f.js
    │   │       ├── 1.f4999e32.js
    │   │       └── 2.ad52e74a.js
    │   └── version.json
    ├── favicon.png
    └── index.html
1个回答

1
令人沮丧的是,“Main.go V2”的工作只需添加一个字符。您正在使用:
```go r.Handle("/", http.FileServer(http.FS(static))) ```
从文档中可以看到:
``` func (mx *Mux) Handle(pattern string, handler http.Handler) ```
每个路由方法接受一个URL模式和一系列处理程序。URL模式支持命名参数(例如/users/{userID})和通配符(例如/admin/)。在运行时,可以通过调用chi.URLParam(r, "userID")来获取命名参数的URL参数,并通过调用chi.URLParam(r, "")来获取通配符参数。
因此,您将“/”作为“pattern”进行传递;这将匹配/,但不匹配其他任何内容;要修复,请使用:
r.Handle("/*", http.FileServer(http.FS(static)))
// or
r.Mount("/", http.FileServer(http.FS(static)))

我用我的一个瘦身应用程序进行了测试,表现良好。你可能要考虑的一个改进是将任何请求不存在的文件重定向到/(否则,如果用户使用路径收藏页面,加载将失败)。有关信息,请参阅此答案
除上述之外-为了演示我在评论中所说的,请在ui/src/routes/+page.svelte的末尾添加<a href="/about">About</a>并重新构建(同时重建svelte和go应用程序)。然后,您将能够导航到about页面(先加载主页,然后点击“关于”)。这由客户端路由器处理(因此可能不会看到任何对go服务器的请求)。有关如何在直接访问页面时使其正常工作(例如/about),请参阅链接的答案中的信息。
这里是一个快速(有点粗糙)的例子,它将从嵌入式文件系统中提供所需的位,并返回主要的index.html以满足其他所有请求(以便Svelte路由器可以显示所需的页面)。
package main

import (
    "embed"
    "fmt"
    "io/fs"
    "log"
    "net/http"

    "github.com/go-chi/chi/v5"
)

//go:embed all:uibuild
var svelteStatic embed.FS

func main() {

    s, err := fs.Sub(svelteStatic, "uibuild")
    if err != nil {
        panic(err)
    }

    staticServer := http.FileServer(http.FS(s))

    r := chi.NewRouter()

    r.Handle("/", staticServer) // Not really needed (as the default will pick this up)
    r.Handle("/_app/*", staticServer)      // Need to serve any app components from the embedded files
    r.Handle("/favicon.png", staticServer) // Also serve favicon :-)

    r.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) { // Everything else returns the index
        r.URL.Path = "/" // Replace the request path
        staticServer.ServeHTTP(w, r)
    })

    fmt.Println("Running on port: 8082")
    log.Fatal(http.ListenAndServe(":8082", r))
}

谢谢!这个让我能够进入主页,但是例如/about页面我仍然得到一个404错误。我尝试在go:embedd中添加/*,但仍然没有成功。我已经更新了帖子,并附上了一个示例存储库。 - RemcoE33
从初始页面转到关于页面应该在Web应用程序内部处理(无需HTTP请求;纯客户端)。如我在回答中提到的,如果您想直接导航到内部页面(例如/about),那么您需要为这些请求路径返回索引(或者,如我链接的答案中所述,任何没有匹配文件的路径)。 - Brits
从初始页面转到关于页面应该在Web应用程序内部处理(无需HTTP请求;纯客户端)。如我在回复中提到的,如果您想直接导航到内部页面(例如/about),那么您需要为这些请求路径返回索引(或者,如我链接的答案中所述,任何没有匹配文件的路径)。 - Brits
谢谢。我现在已经把它全部搞定了。 - RemcoE33
谢谢。我现在已经全部搞定了。 - RemcoE33
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接