embedded Single Page Application(单页面应用)

目录结构

主目录embeddedSPA

  1. —— main.go
  2. —— main_test.go
  3. —— public
  4. —— css
  5. —— main.css
  6. —— index.html
  7. —— app.js

示例代码

main.go

  1. package main
  2. import (
  3. "github.com/kataras/iris"
  4. )
  5. // $ go get -u github.com/shuLhan/go-bindata/...
  6. // $ go-bindata ./public/...
  7. // $ go build
  8. // $ ./embedded-single-page-application
  9. var page = struct {
  10. Title string
  11. }{"Welcome"}
  12. func newApp() *iris.Application {
  13. app := iris.New()
  14. app.RegisterView(iris.HTML("./public", ".html").Binary(Asset, AssetNames))
  15. app.Get("/", func(ctx iris.Context) {
  16. ctx.ViewData("Page", page)
  17. ctx.View("index.html")
  18. })
  19. assetHandler := iris.StaticEmbeddedHandler("./public", Asset, AssetNames, false) //如果使用`go-bindata`工具,请保持false。
  20. //作为SPA的替代方案,您可以查看/routing/dynamic-path/root-wildcard
  21. //也是例子
  22. // 要么
  23. // app.StaticEmbedded如果您不想在index.html上重定向并且简单地为您的SPA应用程序提供服务(推荐)。
  24. // public / index.html是一个动态视图,它由root手工绘制,
  25. //我们不希望作为原始数据显示,所以我们会
  26. //'app.SPA`的返回值来修改`IndexNames`;
  27. app.SPA(assetHandler).AddIndexName("index.html")
  28. return app
  29. }
  30. func main() {
  31. app := newApp()
  32. // http://localhost:8080
  33. // http://localhost:8080/index.html
  34. // http://localhost:8080/app.js
  35. // http://localhost:8080/css/main.css
  36. app.Run(iris.Addr(":8080"))
  37. }
  38. //请注意,将执行app.Use/UseGlobal/Done
  39. //仅限于注册的路由,如我们的app.Get("/",..)。
  40. //文件服务器将不受限制,但你仍然可以通过修饰它的assetHandler来添加中间件。
  41. //使用此方法,与静态Web("/",'./ public')不同,后者不再按设计工作,
  42. //所有自定义http错误和所有路由都可以正常使用已注册的文件服务器
  43. //到服务器的根路径

main_test.go

  1. package main
  2. import (
  3. "io/ioutil"
  4. "path/filepath"
  5. "runtime"
  6. "strings"
  7. "testing"
  8. "github.com/kataras/iris/httptest"
  9. )
  10. type resource string
  11. func (r resource) contentType() string {
  12. switch filepath.Ext(r.String()) {
  13. case ".js":
  14. return "application/javascript"
  15. case ".css":
  16. return "text/css"
  17. default:
  18. return "text/html"
  19. }
  20. }
  21. func (r resource) String() string {
  22. return string(r)
  23. }
  24. func (r resource) strip(strip string) string {
  25. s := r.String()
  26. return strings.TrimPrefix(s, strip)
  27. }
  28. func (r resource) loadFromBase(dir string) string {
  29. filename := r.String()
  30. if filename == "/" {
  31. filename = "/index.html"
  32. }
  33. fullpath := filepath.Join(dir, filename)
  34. b, err := ioutil.ReadFile(fullpath)
  35. if err != nil {
  36. panic(fullpath + " failed with error: " + err.Error())
  37. }
  38. result := string(b)
  39. if runtime.GOOS != "windows" {
  40. // result = strings.Replace(result, "\n", "\r\n", -1)
  41. }
  42. return result
  43. }
  44. var urls = []resource{
  45. "/",
  46. "/index.html",
  47. "/app.js",
  48. "/css/main.css",
  49. }
  50. func TestSPAEmbedded(t *testing.T) {
  51. app := newApp()
  52. e := httptest.New(t, app)
  53. for _, u := range urls {
  54. url := u.String()
  55. contents := u.loadFromBase("./public")
  56. contents = strings.Replace(contents, "{{ .Page.Title }}", page.Title, 1)
  57. e.GET(url).Expect().
  58. Status(httptest.StatusOK).
  59. ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()).
  60. Body().Equal(contents)
  61. }
  62. }

/public/app.js

  1. window.alert("app.js loaded from \"/");

/public/index.html

  1. <html>
  2. <head>
  3. <title>{{ .Page.Title }}</title>
  4. </head>
  5. <body>
  6. <h1> Hello from index.html </h1>
  7. <script src="/app.js"> </script>
  8. </body>
  9. </html>

/public/css/main.css

  1. body {
  2. background-color: black;
  3. }