iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 11
0

template

基本上大部分的資料都可以在前端靠js處理,但是搜尋引擎是不會渲染JS的,只會讀最一開始的HTML文本,所以SEO要把哪些是第一時間讓別人查到的資料,又或者有些資料想讓JS渲染但不想分批傳,可以利用go的HTML渲染package,重複利用template,再把資料送到前端。

先建立view資料夾,在裡面建立html, js, css, img等資料夾,在html建立meta與componment兩個資料夾,在meta建立index.html,寫入

{{define "index"}}
    <!DOCTYPE html>
    <html lang="zh-TW">
    <head>
        {{template "head" .}}
    </head>
    <body>
	    <div id="meta">
		{{ .meta }}
	    </div>
    </body>

    </html>
{{end}}

解釋:

  • {{define "index"}}{{end}}是一起的,表示這段內容命名為index
  • {{ .meta }}之後在go可以指定對meta這裡渲染上我們要的內容
  • {{template "head" .}}會將名為"head"的template放到這裡,後面加"."代表可以把渲染內容也傳進去

創建head.html寫入

{{ define "head"}}
    <title>{{ .title }}</title>

    <meta charset="utf-8">
    <meta name="description" content="{{.description}}">
    <meta name="author" content="{{.nickname}}">

{{end}}

在router/main.go補上

r.LoadHTMLGlob("view/html/**/*")

讓gin知道我們HTML檔案的位置

現在回去改serve/main.go的GetOwner function

func GetOwner(c *gin.Context) {
	// check project exist
	ownerData, err := database.GetOwner(c.Param("owner"))
	if err != nil {
		log.Warn(c, apperr.ErrPermissionDenied, err, "Sorry, something error", "database error of getting owner")
		return
	}

	// drop uid
	ownerData.Uid = 0

	meta, err := json.Marshal(ownerData)
	if err != nil {
		log.Warn(c, apperr.ErrPermissionDenied, err, "Sorry, something error", "parse json error")
		return
	}

	// return owner with blog
	c.HTML(http.StatusOK, "index", gin.H{
		"meta":        string(meta),
		"title":       ownerData.Nickname,
		"description": ownerData.Description,
		"list":        true,
	})
}

在資料庫的owner加一行資料後跑起來應該就能看到網頁了。

現在有個問題,gin提供的HTML只能傳值,沒辦法動態決定要組合的檔案,這樣我們沒辦法把user上傳的文章合併進來,所以需要自己寫一個parser,在util建立file package,創建file.go寫入

package file

import (
	"io"
	"html/template"
)

// parse template to html file
func ParseTmpl(writer io.Writer, data interface{}, file ...string) error {
	tmpl, err := template.ParseGlob("view/html/**/*")
	if err != nil {
		return err
	}

	if len(file) != 0 {
		tmpl, err = tmpl.ParseFiles(file...)
	}
	if err != nil {
		return err
	}

	err = tmpl.ExecuteTemplate(writer, "index", data)
	if err != nil {
		return err
	}
	return nil
}

解釋:

  • tmpl.ParseFiles會讀取指定的檔案,tmpl.ExecuteTemplate將執行渲染寫到io.Writer

今天就到這裡,明天會提到blog的處理

目前的工作環境

.
├── app
│   ├── apperr
│   │   ├── error.go
│   │   └── handle.go
│   ├── common
│   │   └── cookie.go
│   ├── config
│   │   └── app
│   │       ├── app.yaml
│   │       └── error.yaml
│   ├── database
│   │   ├── connect.go
│   │   ├── error.go
│   │   ├── main.go
│   │   └── scheme.go
│   ├── go.mod
│   ├── go.sum
│   ├── log
│   │   ├── logger.go
│   │   └── logging.go
│   ├── main.go
│   ├── middleware
│   │   ├── error.go
│   │   └── log.go
│   ├── router
│   │   ├── host_switch.go
│   │   └── main.go
│   ├── serve
│   │   ├── main.go
│   │   └── main_test.go
│   ├── setting
│   │   └── setting.go
│   ├── util
│   │   ├── debug
│   │   │   ├── stack.go
│   │   │   └── stack_test.go
│   │   └── file
│   │       └── file.go
│   └── view
│       ├── css
│       │   └── style.css
│       ├── html
│       │   ├── component
│       │   └── meta
│       │       ├── head.html
│       │       └── index.html
│       └── js
├── config
│   └── app
│       ├── app.yaml
│       └── error.yaml
└── database
    └── maindata

上一篇
Day10 Owner API串接
下一篇
Day12 Blog CRUD Procedure
系列文
從coding到上線-打造自己的blog系統31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言