You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

261 lines
5.9 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. package govue
  2. //go-bindata-assetfs --pkg=govue govue-runtime/...
  3. import (
  4. "fmt"
  5. "git.ouxuan.net/3136352472/go-service-template/jsruntime"
  6. "git.ouxuan.net/3136352472/go-service-template/pool"
  7. "github.com/elazarl/go-bindata-assetfs"
  8. "io/ioutil"
  9. "log"
  10. "net/http"
  11. "os"
  12. "path/filepath"
  13. "strings"
  14. "time"
  15. )
  16. type GoVue struct {
  17. StaticPath string
  18. UseJsPath string
  19. ErrorPage404 string
  20. Resources *assetfs.AssetFS
  21. IsDebugMode bool
  22. jsRuntimePool *pool.JsRuntimePool
  23. CacheSec int64
  24. }
  25. func NewGoVueDefaultConfig(debug bool) (gv *GoVue, err error) {
  26. gv = &GoVue{
  27. Resources: assetFS(),
  28. IsDebugMode: debug,
  29. }
  30. err = gv.initRender(debug)
  31. return
  32. }
  33. func NewGoVue(useJsPath string, staticPath string, debug bool) (gv *GoVue, err error) {
  34. gv = &GoVue{
  35. StaticPath: staticPath,
  36. UseJsPath: useJsPath,
  37. Resources: assetFS(),
  38. IsDebugMode: debug,
  39. }
  40. err = gv.initRender(debug)
  41. return
  42. }
  43. func (gv *GoVue) SetCacheSec(cacheSec int64) {
  44. gv.CacheSec = cacheSec
  45. }
  46. func (gv *GoVue) SetErrorPage404(page string) {
  47. gv.ErrorPage404 = page
  48. }
  49. func SetPoolConfig(config pool.Config) {
  50. pool.DefaultConfig = config
  51. }
  52. func (gv *GoVue) initRender(debug bool) (err error) {
  53. if gv.StaticPath == "" {
  54. gv.StaticPath = filepath.Join(getSelfFilePath(), "static")
  55. }
  56. if gv.UseJsPath == "" {
  57. gv.UseJsPath = filepath.Join(gv.StaticPath, "use.js")
  58. }
  59. govueScriptFile := "govue-release.js"
  60. if gv.IsDebugMode {
  61. govueScriptFile = "govue-dev.js"
  62. }
  63. //polyfill, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "polyfill.js"))
  64. //if err != nil {
  65. // return
  66. //}
  67. //
  68. //headerScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "header.js"))
  69. //if err != nil {
  70. // return
  71. //}
  72. //
  73. //govueScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", govueScriptFile))
  74. //if err != nil {
  75. // return
  76. //}
  77. //
  78. //mainScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "runtime.js"))
  79. //if err != nil {
  80. // return
  81. //}
  82. polyfill, err := gv.Resources.Asset(filepath.Join("govue-runtime", "polyfill.js"))
  83. if err != nil {
  84. return
  85. }
  86. headerScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "header.js"))
  87. if err != nil {
  88. return
  89. }
  90. govueScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", govueScriptFile))
  91. if err != nil {
  92. return
  93. }
  94. mainScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "runtime.js"))
  95. if err != nil {
  96. return
  97. }
  98. gv.jsRuntimePool = pool.NewJsRuntimePool(string(mainScript), gv.UseJsPath, gv.StaticPath, jsruntime.Relys{
  99. jsruntime.Rely{
  100. Src: string(polyfill),
  101. },
  102. jsruntime.Rely{
  103. Src: string(headerScript),
  104. },
  105. jsruntime.Rely{
  106. Src: string(govueScript),
  107. },
  108. }, jsruntime.ModeSync, debug)
  109. return
  110. }
  111. func (gv *GoVue) PoolLog() {
  112. gv.jsRuntimePool.Log()
  113. }
  114. func (gv *GoVue) StartPoolLog() {
  115. go func() {
  116. defer func() {
  117. recover()
  118. log.Println("统计协程异常")
  119. }()
  120. lastidle := 0
  121. lastactive := 0
  122. for {
  123. all, idle, active := gv.jsRuntimePool.NumInfo()
  124. if idle != lastidle || active != lastactive {
  125. fmt.Println("渲染协程数量变动变动:所有:", all, "空闲:", idle, "活动:", active)
  126. }
  127. lastidle = idle
  128. lastactive = active
  129. time.Sleep(time.Second)
  130. }
  131. }()
  132. }
  133. func (gv *GoVue) LoadStaticResources(request *http.Request, goExtDataS ...interface{}) (result []byte, err error) {
  134. cacheKey := fmt.Sprintf("%s|%s", request.URL.Path, request.URL.RawQuery)
  135. if gv.CacheSec > 0 {
  136. html := GetCache(cacheKey)
  137. if html != "" {
  138. //log.Println("加载缓存")
  139. return []byte(html), nil
  140. }
  141. }
  142. //log.Println("非缓存", cacheKey)
  143. var staticDir string
  144. var filePath = request.URL.Path
  145. if gv.StaticPath == "" {
  146. staticDir = filepath.Join(getSelfFilePath(), "static")
  147. } else {
  148. staticDir = gv.StaticPath
  149. }
  150. filePath = filepath.Join(staticDir, filePath)
  151. fi, err := os.Stat(filePath)
  152. if err == nil {
  153. if fi.IsDir() {
  154. defaultPath := []string{"index.vue", "index.html"}
  155. for e := range defaultPath {
  156. path := filepath.Join(filePath, defaultPath[e])
  157. _, err := os.Stat(path)
  158. if err == nil {
  159. filePath = path
  160. break
  161. }
  162. }
  163. }
  164. } else {
  165. if filepath.Ext(filePath) == ".html" {
  166. split := strings.Split(filePath, ".")
  167. split[len(split)-1] = "vue"
  168. vuePath := strings.Join(split, ".")
  169. _, err := os.Stat(vuePath)
  170. if err == nil {
  171. filePath = vuePath
  172. }
  173. }
  174. }
  175. result, err = ioutil.ReadFile(filePath)
  176. govueDebug := request.URL.Query().Get("govue_debug")
  177. if govueDebug == "1" {
  178. return
  179. }
  180. if err != nil {
  181. result, err = gv.renderErrPage(404, request, goExtDataS...)
  182. if gv.CacheSec > 0 {
  183. SetCache(cacheKey, string(result), gv.CacheSec)
  184. }
  185. return
  186. } //
  187. if filepath.Ext(filePath) != ".html" && filepath.Ext(filePath) != ".vue" {
  188. return
  189. }
  190. var goExtData interface{}
  191. if len(goExtDataS) > 0 {
  192. goExtData = goExtDataS[0]
  193. }
  194. err = gv.jsRuntimePool.JsRuntimeCall(func(jr *jsruntime.JsRuntime) {
  195. if filepath.Ext(filePath) == ".vue" {
  196. jr.SetVariable("IS_VUE_SSR", true)
  197. } else {
  198. jr.SetVariable("IS_VUE_SSR", false)
  199. }
  200. err = jr.Render(filePath, fmt.Sprintf("http://%s%s", request.Host, request.RequestURI), string(result), goExtData, func(data string) {
  201. result = []byte(data)
  202. if gv.CacheSec > 0 {
  203. SetCache(cacheKey, string(result), gv.CacheSec)
  204. }
  205. })
  206. if err != nil {
  207. result = []byte(err.Error())
  208. }
  209. })
  210. return
  211. }
  212. func (gv *GoVue) renderErrPage(errCode int, request *http.Request, goExtDataS ...interface{}) (result []byte, err error) {
  213. filePath := gv.ErrorPage404
  214. if filePath == "" {
  215. return []byte("页面不存在"), err
  216. }
  217. result, _ = ioutil.ReadFile(filePath)
  218. var goExtData interface{}
  219. if len(goExtDataS) > 0 {
  220. goExtData = goExtDataS[0]
  221. }
  222. err = gv.jsRuntimePool.JsRuntimeCall(func(jr *jsruntime.JsRuntime) {
  223. err = jr.Render(filePath, fmt.Sprintf("http://%s%s", request.Host, request.RequestURI), string(result), goExtData, func(data string) {
  224. result = []byte(data)
  225. })
  226. })
  227. return
  228. }