Browse Source

fix

tags/v0.9.2
郑荣升 5 years ago
parent
commit
b5afb504df
  1. 1
      .gitignore
  2. 35
      govue/bindata.go
  3. 2
      govue/cmd/main.go
  4. 30
      govue/govue-js-src/build.js
  5. 117914
      govue/govue-js-src/dist/index.js
  6. 14
      govue/govue-js-src/package.json
  7. 12
      govue/govue-js-src/predo.js
  8. 9
      govue/govue-js-src/replace.tp
  9. 1
      govue/govue-js-src/replace2.tp
  10. 74
      govue/govue-js-src/src/browser.js
  11. 104
      govue/govue-js-src/src/goruntime.js
  12. 118
      govue/govue-js-src/src/index.js
  13. 54852
      govue/govue-runtime/govue.js
  14. 105
      govue/govue-runtime/header.js
  15. 7203
      govue/govue-runtime/polyfill.js
  16. 57
      govue/govue-runtime/runtime.js
  17. 8959
      govue/govue-runtime/vuessr.js
  18. 108
      govue/govue.go
  19. 108
      jsruntime/runtime.go
  20. 36
      jsruntime/timeout.go
  21. 6
      pool/pool.go
  22. 49
      static/index.html
  23. 23
      static/use.js

1
.gitignore

@ -13,3 +13,4 @@
*.out
.idea
build
*.json

35
govue/bindata.go
File diff suppressed because it is too large
View File

2
govue/cmd/main.go

@ -69,7 +69,7 @@ func main() {
govue.SetPoolConfig(config.Pool)
gv, err := govue.NewGoVue(config.UseJsFile, config.StaticDir)
gv, err := govue.NewGoVue(config.UseJsFile, config.StaticDir, mode == "debug")
if errorPage404 != "" {
config.ErrorPage404 = errorPage404

30
govue/govue-js-src/build.js

@ -2,22 +2,20 @@ var fs = require("fs");
var envify = require('envify/custom')
var browserify = require("browserify");
browserify("./src/index.js")
.transform("babelify", {
plugins: [
'@babel/preset-env',
"@babel/preset-es2015"
],
plugins: [
'@babel/plugin-transform-modules-commonjs',
'@babel/plugin-transform-object-assign',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread'
]
}).transform(
// 用来处理 `node_modules` 文件
{ global: true },
envify({ NODE_ENV: 'production' })
)
// .transform("babelify", {
// plugins: [
// '@babel/plugin-transform-modules-commonjs',
// '@babel/plugin-transform-object-assign',
// '@babel/plugin-proposal-class-properties',
// '@babel/plugin-transform-property-mutators',
// "transform-remove-strict-mode"
// ]
// })
// .transform(
// // 用来处理 `node_modules` 文件
// { global: true },
// envify({ NODE_ENV: 'production' })
// )
.bundle()
.pipe(fs.createWriteStream("./dist/index.js"));

117914
govue/govue-js-src/dist/index.js
File diff suppressed because it is too large
View File

14
govue/govue-js-src/package.json

@ -1,19 +1,24 @@
{
"name": "govue-template",
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-transform-modules-commonjs": "^7.9.6",
"@babel/plugin-transform-object-assign": "^7.8.3",
"@babel/preset-env": "^7.9.6",
"@babel/preset-es2015": "^7.0.0-beta.53",
"axios": "^0.19.2",
"domino": "^2.1.5",
"babel-plugin-transform-remove-strict-mode": "^0.0.2",
"envify": "^4.1.0",
"es6-promise": "^4.2.8",
"esprima": "^4.0.1",
"jquery-bbq": "^1.0.0",
"qs": "^6.9.4",
"through": "^2.3.8",
"vue": "^2.6.11",
"vue-axios": "^2.1.5",
"vue-router": "^3.1.6"
"vue-router": "^3.2.0"
},
"scripts": {
"build": "node build.js && node predo.js"
"build": "node build.js && node predo.js && cp ./dist/index.js ../govue-runtime/govue.js"
},
"browser": {
"vue": "vue/dist/vue.common.js"
@ -31,6 +36,7 @@
"@babel/preset-es2015": "^7.0.0-beta.53",
"@babel/preset-react": "^7.9.4",
"babel-cli": "^6.26.0",
"babel-plugin-transform-remove-strict-mode": "^0.0.2",
"babelify": "^10.0.0",
"browserify": "^16.5.1"
}

12
govue/govue-js-src/predo.js

@ -1,15 +1,9 @@
var fs = require("fs");
var retemp = fs.readFileSync("./replace.tp")
var retemp2 = fs.readFileSync("./replace2.tp")
var content = fs.readFileSync("./dist/index.js")
retemp = retemp.toString().replace(/\r\n/g,"\n")
var test = content.toString().indexOf(retemp)
console.log(test)
// content = content.toString().replace(`_m("`, `this._m("`).replace(`var isHTMLTag = `, `var isHTMLTag = makeMap('html,body,base,head,link,meta,style,title');var _isHTMLTag = `)
// fs.writeFileSync("./dist/index.js", content)
content = content.toString().replace(retemp, `NodeList`).replace(retemp2, ``)
fs.writeFileSync("./dist/index.js", content)

9
govue/govue-js-src/replace.tp

@ -1,9 +0,0 @@
class NodeList extends Array {
constructor(a) {
super((a && a.length) || 0);
if (a) {
for (var idx in a) { this[idx] = a[idx]; }
}
}
item(i) { return this[i] || null; }
}

1
govue/govue-js-src/replace2.tp

@ -1 +0,0 @@
throw new Error("NotYetImplemented");

74
govue/govue-js-src/src/browser.js

@ -1,74 +0,0 @@
console.log("浏览器端")
Promise = require('es6-promise').Promise;
window.Vue = require('vue');
window.VueRouter = require('vue-router');
Vue.use(VueRouter)
window.$ = window.jQuery = require('jquery');
require('jquery-bbq');
window.axios = require('axios');
import VueAxios from 'vue-axios'
window.Vue.use(VueAxios, window.axios)
window.GoQuery = location.search;
window.GoParam = jQuery.deparam(GoQuery);
window.GoUse = function (cb) {
var path = location.pathname
if (path.indexOf(".html") < 0) {
if (path[path.length - 1] == "/" && path.length > 1) {
path = path + "index.html"
} else {
path = path + ".html"
}
}
if (cb) cb(path, location.search)
}
window.GoUseRegistered = function (id, cb) {
var govueId = "";
if (document.getElementsByTagName("html").length > 0) {
govueId = document.getElementsByTagName("html")[0].getAttribute("govue-id")
}
var path = location.pathname
if (path.indexOf(".html") < 0) {
if (path[path.length - 1] == "/" && path.length > 1) {
path = path + "index.html"
} else {
path = path + ".html"
}
}
if (govueId == id || path == id) {
if (cb) cb(location.search)
}
};
window.GoUseCall = function (e) {
// console.log("GoUseCall", 2)
var id = e["id"];
var path = e["path"];
var query = e["query"];
if (useRoute[id]) {
console.log(useRoute[id])
useRoute[id](query);
return
}
// console.log("GoUseCall", 3)
if (useRoute[path]) {
useRoute[path](query);
return
}
console.log("路由未找到:", id, "-", path)
}

104
govue/govue-js-src/src/goruntime.js

@ -1,104 +0,0 @@
domino = require('domino');
window = domino.createWindow("", "http://127.0.0.1/");
document = window.document;
location = window.location;
Promise = require('es6-promise').Promise;
Vue = require('vue');
$ = jQuery = require('jquery');
require('jquery-bbq');
qs = require('qs');
axios = require('axios');
var buildURL = require('axios/lib/helpers/buildURL');
var buildFullPath = require('axios/lib/core/buildFullPath');
var settle = require('axios/lib/core/settle');
var createError = require('axios/lib/core/createError');
function transformResponse(mpResponse, config, mpRequestOption) {
var headers = mpResponse.header || mpResponse.headers;
var status = mpResponse.statusCode || mpResponse.status;
var statusText = '';
if (status === 200) {
statusText = 'OK';
}
else if (status === 400) {
statusText = 'Bad Request';
}
var response = {
data: mpResponse.data,
status: status,
statusText: statusText,
headers: headers,
config: config,
request: mpRequestOption
};
return response;
}
axios.defaults.adapter = function (config) {
return new Promise(function (resolve, reject) {
// console.log("resolve", JSON.stringify(resolve));
// console.log("reject", JSON.stringify(reject));
// console.log("config", JSON.stringify(config));
// console.log("axios.defaults.headers", JSON.stringify(axios.defaults.headers));
var mpRequestOption = {
url: buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer),
method: config["method"].toUpperCase(),
data: config["data"],
header: config["headers"],
timeout: config["timeout"],
success: function (mpResponse) {
// console.log("success");
// console.log(JSON.stringify(mpResponse));
var response = transformResponse(mpResponse, config, mpRequestOption);
settle(resolve, reject, response);
},
fail: function (error) {
reject(createError(error.data));
},
};
net.request(mpRequestOption)
})
};
useRoute = {};
GoUseRegistered = function (id, cb) {
useRoute[id] = cb
};
goUseCallCache
GoUseCall = function (e) {
// console.log("GoUseCall", 1)
if (goUseCallCache) {
goUseCallCache(e)
}
// console.log("GoUseCall", 2)
var id = e["id"];
var path = e["path"];
var query = e["query"];
if (useRoute[id]) {
// console.log(useRoute[id])
useRoute[id](query);
return
}
// console.log("GoUseCall", 3)
if (useRoute[path]) {
useRoute[path](query);
return
}
// console.log("路由未找到:", id, "-", path)
}
GoUse = function (cb) {
goUseCallCache = cb
}

118
govue/govue-js-src/src/index.js

@ -1,8 +1,118 @@
domino = require('../domino/lib/index');
window = domino.createWindow("", "http://127.0.0.1/");
document = window.document;
location = window.location;
if (window) {
Intl = require('./Intl');
require("./browser")
} else {
require("./goruntime")
Vue = require('vue');
VueRouter = require('vue-router');
Vue.use(VueRouter)
vuessr = require('vue-server-renderer')
$ = jQuery = require('jquery');
require('jquery-bbq');
qs = require('qs');
Promise = require('es6-promise').Promise;
axios = require('axios');
var buildURL = require('axios/lib/helpers/buildURL');
var buildFullPath = require('axios/lib/core/buildFullPath');
var settle = require('axios/lib/core/settle');
var createError = require('axios/lib/core/createError');
function transformResponse(mpResponse, config, mpRequestOption) {
var headers = mpResponse.header || mpResponse.headers;
var status = mpResponse.statusCode || mpResponse.status;
var statusText = '';
if (status === 200) {
statusText = 'OK';
}
else if (status === 400) {
statusText = 'Bad Request';
}
var response = {
data: mpResponse.data,
status: status,
statusText: statusText,
headers: headers,
config: config,
request: mpRequestOption
};
return response;
}
axios.defaults.adapter = function (config) {
return new Promise(function (resolve, reject) {
// console.log("resolve", JSON.stringify(resolve));
// console.log("reject", JSON.stringify(reject));
// console.log("config", JSON.stringify(config));
// console.log("axios.defaults.headers", JSON.stringify(axios.defaults.headers));
var mpRequestOption = {
url: buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer),
method: config["method"].toUpperCase(),
data: config["data"],
header: config["headers"],
timeout: config["timeout"],
success: function (mpResponse) {
// console.log("success");
// console.log(JSON.stringify(mpResponse));
var response = transformResponse(mpResponse, config, mpRequestOption);
settle(resolve, reject, response);
},
fail: function (error) {
reject(createError(error.data));
},
};
net.request(mpRequestOption)
})
};
useRoute = {};
GoUseRegistered = function (id, cb) {
useRoute[id] = cb
};
goUseCallCache
GoUseCall = function (e) {
// console.log("GoUseCall", 1)
if (goUseCallCache) {
goUseCallCache(e)
}
// console.log("GoUseCall", 2)
var id = e["id"];
var path = e["path"];
var query = e["query"];
if (useRoute[id]) {
// console.log(useRoute[id])
useRoute[id](query);
return
}
// console.log("GoUseCall", 3)
if (useRoute[path]) {
useRoute[path](query);
return
}
// console.log("路由未找到:", id, "-", path)
}
GoUse = function (cb) {
goUseCallCache = cb
}
for (var i in global) {
window[i] = global[i]
}

54852
govue/govue-runtime/govue.js
File diff suppressed because it is too large
View File

105
govue/govue-runtime/header.js

@ -1,9 +1,17 @@
var domino, window, document, location, Vue, VueRouter, navigator, axios, Promise, GoUseCall, GoUse, GoUseRegistered,
govueId, useRoute, goUseCallCache, $, jQuery, GoParam, qs;
var domino, window, document, location, Vue, VueRouter, vuessr, navigator, axios, Promise, GoUseCall, GoUse,
GoUseRegistered,
govueId, useRoute, goUseCallCache, $, jQuery, GoParam, qs, Intl;
var global = this;
global.Vue = Vue;
global.VueRouter = VueRouter;
global.Intl = Intl;
navigator = {
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 a/537.36 "
};
var net = {
request: function (c) {
var url = c["url"];
@ -37,10 +45,6 @@ var net = {
url = $.param.querystring(url, data);
data = ""
} else {
// console.log("data:");
// console.log(JSON.stringify(header["Content-Type"]));
// console.log(JSON.stringify(data));
if (typeof (data) == "object") {
if (header["Content-Type"].indexOf("application/json") > -1 || header["content-type"].indexOf("application/json") > -1) {
data = JSON.stringify(data);
@ -70,20 +74,52 @@ var net = {
}
if (statusCode == 200) {
success({
success && success({
data: result,
statusCode: statusCode,
});
} else {
fail({
fail && fail({
data: result,
statusCode: statusCode,
})
}
complete && complete({
data: result,
statusCode: statusCode,
})
}
};
function GoVueRender(template, app, context) {
var raw = GoReadFile(template);
var renderer = vuessr.createRenderer({
template: raw
});
// 第 3 步:将 Vue 实例渲染为 HTML
renderer.renderToString(app, context, function (err, html) {
if (err) throw err;
GoReturn(html);
// => <div data-server-rendered="true">Hello World</div>
})
}
function LoadPage(src, href) {
window = domino.createWindow(src, href);
document = window.document;
location = window.location;
for (var i in global) {
window[i] = global[i]
}
}
/**
* 获取页面Id
@ -129,10 +165,11 @@ function RunInlineCode() {
}
for (var i in jsInlineFiles) {
if (jsInlineFiles[i]["file"]) {
console.log("load file", jsInlineFiles[i]["file"]);
GoRunCodeByFile(jsInlineFiles[i]["file"]);
}
if (jsInlineFiles[i]["src"]) {
eval(jsInlineFiles[i]["src"]);
GoRunCode(jsInlineFiles[i]["src"]);
}
}
}
@ -167,20 +204,24 @@ var GoVueIgnore = function () {
gv_ignore_tag_map[i] = gv_ignore[i].innerHTML;
gv_ignore[i].outerHTML = "<gv-ignore-" + i + "></gv-ignore-" + i + ">";
}
var gv_ignore_class = document.getElementsByClassName("gv-ignore");
var gv_ignore_class = document.querySelectorAll("[gv-ignore]");
gv_ignore_class_len = gv_ignore_class.length;
// console.log("gv_ignore_class_len",gv_ignore_class_len)
for (var i = 0; i < gv_ignore_class_len; i++) {
if (!gv_ignore_class_map[i]) {
gv_ignore_class_map[i] = {};
}
var a = gv_ignore_class[i].attributes;
var len = gv_ignore_class[i].attributes.length;
var ignoreVal = gv_ignore_class[i].getAttribute("gv-ignore");
for (var k = len - 1; k >= 0; k--) {
if (!ignoreVal || ignoreVal == "" || ignoreVal.split("|").includes(a.item(k).name)) {
gv_ignore_class_map[i][a.item(k).name] = a.item(k).value;
gv_ignore_class[i].removeAttribute(a.item(k).name);
}
gv_ignore_class[i].setAttribute("class", "gv-ignore-" + i)
}
gv_ignore_class[i].removeAttribute("gv-ignore");
gv_ignore_class[i].setAttribute("gv-ignore-val", "gv-ignore-" + i)
}
};
@ -192,18 +233,52 @@ var GoVueIgnore = function () {
for (i = 0; i < gv_ignore_len; i++) {
gv_restore = document.getElementsByTagName("gv-ignore-" + i);
for (k = 0; k < gv_restore.length; k++) {
gv_restore[k].innerHTML = gv_ignore_tag_map[i];
gv_restore[k].outerHTML = gv_ignore_tag_map[i];
}
}
for (i = 0; i < gv_ignore_class_len; i++) {
gv_restore = document.getElementsByClassName("gv-ignore-" + i);
gv_restore = document.querySelectorAll("[gv-ignore-val='gv-ignore-" + i + "']");
for (k = 0; k < gv_restore.length; k++) {
for (j in gv_ignore_class_map[i]) {
gv_restore[k].setAttribute(j, gv_ignore_class_map[i][j]);
}
gv_restore[k].removeAttribute("gv-ignore-val");
}
}
}
};
//自动替换事件属性,不成熟实用性不足,不启用
var GoVueIgnoreOnEvent = function () {
var all = document.querySelectorAll('*');
all.forEach(function (el) {
var len = el.attributes.length;
var arr = [];
var arr2 = [];
for (var i = 0; i < len; i++) {
var name = el.attributes.item(i).name;
if (name[0] == "@" || name.indexOf("v-on:") == 0) {
arr.push({
name: name.replace("v-on:", "gv-on:").replace("@", "gv-on:"),
value: el.attributes.item(i).value,
});
arr2.push({
name: ":data-" + name.replace("v-on:", "gv-on:").replace("@", "gv-on:"),
value: el.attributes.item(i).value.match(/\((.+?)\)/g),
});
// el.setAttribute("gv-on:" + name, el.attributes.item(i).value);
// el.setAttribute(":gv-on-data:" + name, el.attributes.item(i).value.match(/\((.+?)\)/g));
}
}
for (var i in arr) {
console.log(JSON.stringify(arr[i]));
el.setAttribute(arr[i].name, arr[i].value);
el.setAttribute(arr2[i].name, arr2[i].value);
}
})
};

7203
govue/govue-runtime/polyfill.js
File diff suppressed because it is too large
View File

57
govue/govue-runtime/runtime.js

@ -1,34 +1,69 @@
window = domino.createWindow(GoHtmlSrc, GoHref);
document = window.document;
location = window.location;
if (!IS_VUE_SSR) {
try {
LoadPage(GoHtmlSrc, GoHref);
} catch (e) {
console.log("LoadPage:" + e);
}
try {
var govueId = GetGoVueId();
} catch (e) {
console.log("GetGoVueId:" + e);
}
LoadGoParam();
try {
var goVueIgnore = new GoVueIgnore();
goVueIgnore.ignore();
} catch (e) {
console.log("goVueIgnore.ignore:" + e);
}
try {
GoUseCall({
id: govueId,
path: GoPath,
query: jQuery.deparam(GoQuery)
});
} catch (e) {
console.log("GoUseCall:" + e);
}
try {
RunInlineCode();
} catch (e) {
console.log("RunInlineCode:" + e);
}
goVueIgnore.restore()
try {
goVueIgnore.restore();
} catch (e) {
console.log("VM Uncaught:", e);
console.log("goVueIgnore.restore:" + e);
}
// console.log(document.innerHTML);
try {
GoReturn(document.innerHTML);
} catch (e) {
console.log("GoReturn:" + e)
}
} else {
try {
LoadPage(GoHtmlSrc, GoHref);
} catch (e) {
console.log("LoadPage:" + e);
}
try {
GoUseCall({
path: GoPath,
query: jQuery.deparam(GoQuery)
});
} catch (e) {
console.log("GoUseCall:" + e);
}
}

8959
govue/govue-runtime/vuessr.js
File diff suppressed because it is too large
View File

108
govue/govue.go

@ -12,6 +12,7 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
@ -23,22 +24,22 @@ type GoVue struct {
jsRuntimePool *pool.JsRuntimePool
}
func NewGoVueDefaultConfig() (gv *GoVue, err error) {
func NewGoVueDefaultConfig(debug bool) (gv *GoVue, err error) {
gv = &GoVue{
Resources: assetFS(),
}
err = gv.initRender()
err = gv.initRender(debug)
return
}
func NewGoVue(useJsPath string, staticPath string) (gv *GoVue, err error) {
func NewGoVue(useJsPath string, staticPath string, debug bool) (gv *GoVue, err error) {
gv = &GoVue{
StaticPath: staticPath,
UseJsPath: useJsPath,
Resources: assetFS(),
}
err = gv.initRender()
err = gv.initRender(debug)
return
}
@ -50,7 +51,7 @@ func SetPoolConfig(config pool.Config) {
pool.DefaultConfig = config
}
func (gv *GoVue) initRender() (err error) {
func (gv *GoVue) initRender(debug bool) (err error) {
if gv.StaticPath == "" {
gv.StaticPath = filepath.Join(getSelfFilePath(), "static")
}
@ -59,42 +60,63 @@ func (gv *GoVue) initRender() (err error) {
gv.UseJsPath = filepath.Join(gv.StaticPath, "use.js")
}
//mainScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "runtime.js"))
//if err != nil {
// return
//}
//headerScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "header.js"))
//if err != nil {
// return
//}
//govueScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-js-src", "dist", "index.js"))
//if err != nil {
// return
//}
vuessr, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "vuessr.js"))
if err != nil {
return
}
polyfill, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "polyfill.js"))
if err != nil {
return
}
mainScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "runtime.js"))
mainScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "runtime.js"))
if err != nil {
return
}
headerScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "header.js"))
headerScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-runtime", "header.js"))
if err != nil {
return
}
govueScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "govue.js"))
govueScript, err := ioutil.ReadFile(filepath.Join("govue", "govue-js-src", "dist", "index.js"))
if err != nil {
return
}
//mainScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "runtime.js"))
//if err != nil {
// return
//}
//govueScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "govue.js"))
//if err != nil {
// return
//}
//headerScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "header.js"))
//if err != nil {
// return
//}
//vueScript, err := ioutil.ReadFile(filepath.Join("static", "js", "vue.js"))
//if err != nil {
// return
//}
gv.jsRuntimePool = pool.NewJsRuntimePool(string(mainScript), gv.UseJsPath, gv.StaticPath, jsruntime.Relys{
jsruntime.Rely{
Src: string(polyfill),
},
jsruntime.Rely{
Src: string(headerScript),
},
jsruntime.Rely{
Src: string(vuessr),
},
jsruntime.Rely{
Src: string(govueScript),
},
}, jsruntime.ModeSync)
}, jsruntime.ModeSync, debug)
return
}
@ -123,7 +145,7 @@ func (gv *GoVue) StartPoolLog() {
}
func (gv *GoVue) LoadStaticResources(request *http.Request, goExtDataS ...interface{}) (result []byte, err error) {
var path string
var staticDir string
var filePath = request.URL.Path
if gv.StaticPath == "" {
@ -132,21 +154,38 @@ func (gv *GoVue) LoadStaticResources(request *http.Request, goExtDataS ...interf
staticDir = gv.StaticPath
}
path = filepath.Join(staticDir, filePath)
filePath = filepath.Join(staticDir, filePath)
fi, err := os.Stat(path)
if err != nil {
return gv.renderErrPage(404, request, goExtDataS...)
} else if fi.IsDir() {
filePath = filepath.Join(filePath, "index.html")
path = filepath.Join(staticDir, filePath)
fi, err := os.Stat(filePath)
if err == nil {
if fi.IsDir() {
defaultPath := []string{"index.vue", "index.html"}
for e := range defaultPath {
path := filepath.Join(filePath, defaultPath[e])
_, err := os.Stat(path)
if err == nil {
filePath = path
break
}
}
}
} else {
if filepath.Ext(filePath) == ".html" {
split := strings.Split(filePath, ".")
split[len(split)-1] = "vue"
vuePath := strings.Join(split, ".")
_, err := os.Stat(vuePath)
if err == nil {
filePath = vuePath
}
}
}
result, err = ioutil.ReadFile(path)
if !pathExists(path) || err != nil {
result, err = ioutil.ReadFile(filePath)
if err != nil {
return gv.renderErrPage(404, request, goExtDataS...)
}
if filepath.Ext(path) != ".html" {
if filepath.Ext(filePath) != ".html" && filepath.Ext(filePath) != ".vue" {
return
}
@ -155,6 +194,11 @@ func (gv *GoVue) LoadStaticResources(request *http.Request, goExtDataS ...interf
goExtData = goExtDataS[0]
}
err = gv.jsRuntimePool.JsRuntimeCall(func(jr *jsruntime.JsRuntime) {
if filepath.Ext(filePath) == ".vue" {
jr.SetVariable("IS_VUE_SSR", true)
} else {
jr.SetVariable("IS_VUE_SSR", false)
}
err = jr.Render(filePath, fmt.Sprintf("http://%s%s", request.Host, request.RequestURI), string(result), goExtData, func(data string) {
result = []byte(data)
})

108
jsruntime/runtime.go

@ -4,13 +4,15 @@ import (
"crypto/md5"
"fmt"
"github.com/dop251/goja"
"github.com/go-errors/errors"
"html"
"io/ioutil"
"log"
"net/url"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
)
type JsRuntime struct {
@ -21,6 +23,8 @@ type JsRuntime struct {
TimeoutSec int64
runtime *goja.Runtime
mutex sync.Mutex
RenderCallBackFun func(string)
IsDebugModel bool
}
type Rely struct {
@ -55,14 +59,29 @@ func NewJsRuntime(mainScript string, extFileDir string, rels Relys, mode RunMode
jr.EnableConsoleFun()
jr.SetVariable("GoReadFile", func(filePath string) string {
code, err := ioutil.ReadFile(filepath.Join(jr.ExtFileDir, filePath))
if err != nil {
jr.PrintError(fmt.Sprintln("GoRunCodeByFile Read Error:", err.Error()), string(code))
}
return string(code)
})
jr.SetVariable("GoRunCode", func(code string) {
err = jr.RunCode(string(code))
if err != nil {
jr.PrintError(fmt.Sprintln("GoRunCode Run Error:", err.Error()), code)
}
})
jr.SetVariable("GoRunCodeByFile", func(filePath string) {
code, err := ioutil.ReadFile(filepath.Join(jr.ExtFileDir, filePath))
if err != nil {
log.Println("GoRunCodeByFile Read Error:", err)
jr.PrintError(fmt.Sprintln("GoRunCodeByFile Read Error:", err.Error()), string(code))
}
err = jr.RunCode(string(code))
if err != nil {
log.Println("GoRunCodeByFile Run Error:", err)
jr.PrintError(fmt.Sprintln("GoRunCodeByFile Run Error:", err.Error()), string(code))
}
})
err = jr.InitJsCode()
@ -73,6 +92,67 @@ func NewJsRuntime(mainScript string, extFileDir string, rels Relys, mode RunMode
return jr, nil
}
func (jr *JsRuntime) PrintError(msg string, code string) {
if !jr.IsDebugModel {
log.Println(msg)
}
var errLine string
var line = -1
evalErr := strings.Split(msg, "<eval>")
if len(evalErr) > 1 {
evalErr = strings.Split(evalErr[1], ":")
if len(evalErr) > 1 {
line, _ = strconv.Atoi(evalErr[1])
}
}
if line == -1 {
evalErr = strings.Split(msg, ": Line ")
if len(evalErr) > 1 {
evalErr = strings.Split(evalErr[1], ":")
if len(evalErr) > 0 {
line, _ = strconv.Atoi(evalErr[0])
}
}
}
//log.Println("error line", line,evalErr)
if line > -1 {
lines := strings.Split(string(code), "\n")
linesStart := line - 15
linesEnd := line + 15
if linesStart < 0 {
linesStart = 0
}
if len(lines)-1 < linesEnd {
linesEnd = len(lines)
}
log.Println("error line linesEnd", linesEnd)
//linesEnd = linesStart + linesEnd
for e := range lines[linesStart:linesEnd] {
if e+linesStart+1 == line {
lines[linesStart:linesEnd][e] = fmt.Sprintf(`%2d: >>>>>> %s`, e+linesStart, lines[linesStart:linesEnd][e])
} else {
lines[linesStart:linesEnd][e] = fmt.Sprintf(`%2d: %s`, e+linesStart, lines[linesStart:linesEnd][e])
}
}
errLine = strings.Join(lines[linesStart:linesEnd], "\n")
}
if jr.RenderCallBackFun != nil {
jr.RenderCallBackFun(fmt.Sprintf(`
<body style="background: #eeeeee;padding: 5%%;width:85%%;">
<h3 style="color: red;">%s</h3>
<div style="background: #fff;">
<pre style="width:95%%;font-size: 14px; padding: 2%%; ">%s<pre>
</div>
</body>
`, html.EscapeString(msg), html.EscapeString(errLine)))
jr.RenderCallBackFun = func(s string) {
}
}
}
func (jr *JsRuntime) InitJsCode() error {
for e := range jr.Relys {
@ -82,7 +162,6 @@ func (jr *JsRuntime) InitJsCode() error {
//log.Println(e, "加载时间:", end-start)
if err != nil {
log.Println("initjscode", err)
return err
}
}
@ -108,6 +187,7 @@ func (jr *JsRuntime) RunCode(code string) error {
if !ok {
pro, err := goja.Compile("", code, false)
if err != nil {
log.Println("Compile Error")
return err
}
codeMap.Store(id, pro)
@ -116,10 +196,12 @@ func (jr *JsRuntime) RunCode(code string) error {
program := p.(*goja.Program)
_, err := jr.runtime.RunProgram(program)
//log.Println("RunCode result", result)
return err
}
func (jr *JsRuntime) Render(filePath, href, tplSrc string, GoExtData interface{}, cb func(data string)) (err error) {
jr.RenderCallBackFun = cb
jr.mutex.Lock()
defer jr.mutex.Unlock()
@ -140,18 +222,18 @@ func (jr *JsRuntime) Render(filePath, href, tplSrc string, GoExtData interface{}
if useSrc != "" {
err = jr.RunCode(useSrc)
if err != nil {
return errors.New(err.Error() + "1")
return err
}
}
url, err := url.Parse(href)
if err != nil {
return errors.New(err.Error() + "2")
return err
}
url2, err := url.Parse(strings.Replace(filePath, `\`, "/", -1))
if err != nil {
return errors.New(err.Error() + "3")
return err
}
runtime.Set("GoExtData", GoExtData)
@ -165,11 +247,19 @@ func (jr *JsRuntime) Render(filePath, href, tplSrc string, GoExtData interface{}
runtime.Set("GoPath", url2.Path)
runtime.Set("GoReturn", func(data string) {
cb(data)
jr.RenderCallBackFun(data)
})
t := time.AfterFunc(time.Duration(jr.TimeoutSec), func() {
jr.runtime.Interrupt("time out")
jr.runtime.ClearInterrupt()
})
defer t.Stop()
err = jr.RunCode(mainSrc)
if err != nil {
return errors.New(err.Error() + "4")
return err
}
return

36
jsruntime/timeout.go

@ -2,29 +2,13 @@ package jsruntime
import (
"github.com/dop251/goja"
"log"
)
func (jr *JsRuntime) EnableTimeoutFunc() {
//
//var funs []func()
//var task func()
//task = func() {
// recover()
// go task()
// for ; ; {
// l := len(funs)
// if len(funs) > 0 {
// fun := funs[l-1]
// funs = funs[:l-1]
// fun()
// }
// time.Sleep(time.Second / 100)
// }
//}
//go task()
jr.runtime.Set("setTimeout", func(call goja.FunctionCall) goja.Value {
//log.Println("setTimeout")
//log.Println(call.Argument(0))
if fn, ok := goja.AssertFunction(call.Argument(0)); ok {
//delay := call.Argument(1).ToInteger()
var args []goja.Value
@ -33,22 +17,12 @@ func (jr *JsRuntime) EnableTimeoutFunc() {
}
//time.Sleep(time.Duration(delay) * time.Millisecond)
fn(nil, args...)
//
//time.AfterFunc(time.Duration(delay) * time.Millisecond, func(){
// fn(nil, args...)
//})
//funs = append(funs, func() {
// time.Sleep(time.Duration(delay) * time.Millisecond)
// fn(nil, args...)
//})
//log.Println("setTimeout ok")
fn(nil, args...)
}
return jr.runtime.ToValue(123124512)
})
jr.runtime.Set("clearTimeout", func(i int64) {
//log.Println("clearTimeout")
log.Println("clearTimeout暂未支持")
})
}

6
pool/pool.go

@ -24,16 +24,18 @@ var DefaultConfig Config
var useSrc string
func NewJsRuntimePool(mainScript string, useFileName string, staticPath string, relys jsruntime.Relys, mode jsruntime.RunMode) (jrp *JsRuntimePool) {
func NewJsRuntimePool(mainScript string, useFileName string, staticPath string, relys jsruntime.Relys, mode jsruntime.RunMode, debug bool) (jrp *JsRuntimePool) {
jrp = &JsRuntimePool{}
factory := pool.NewPooledObjectFactorySimple(
func(context.Context) (interface{}, error) {
render, err := jsruntime.NewJsRuntime(mainScript, staticPath, relys, mode)
if err == nil {
render.IsDebugModel = debug
render.UseSrcFun = func() string {
return useSrc
}
}
return render, err
})

49
static/index.html

@ -4,26 +4,50 @@
<meta charset="utf-8">
<meta name="keywords" content="">
<link rel="stylesheet" href="css/main.css">
<script src="js/vue.min.js"></script>
<script src="js/vue.js" gv-src></script>
</head>
<body>
<div id="app" class="content">
<my-title></my-title>
<a>{{desc}}</a>
</div>
<div id="demo" class="content">
<h3>{{title}}</h3>
<a v-on:click="click" class="gv-ignore" >触发事件</a>
<div id="demo">
<div>searchShops</div>
</div>
</body>
<script src="index.js" gv-src></script>
<script gv-src gv-common>
new Vue({
<script gv-src>
a = function () {
this.m5 = function () {
this.m(this.c)
};
this.m2 = (new Function("with(this){m(c)}"))
this.m3 = (new Function("with(this){m4('hello')}"))
};
a.prototype.c = "hello";
a.prototype.m = function () {
console.log("c:", this.c)
};
a.prototype.m4 = function (a) {
console.log(this);
console.log("c:", a)
};
b = new a();
b.m5();
b.m3();
b.m2();
</script>
<script gv-src>
var a = new Vue({
el: "#demo",
data: {
title: "两端通用加载"
title: "两端通用加载",
categoryList: [],
swiperList: [],
searchShops: "123",
},
methods: {
click: function () {
@ -34,5 +58,4 @@
</script>
</html>

23
static/use.js

@ -1,21 +1,5 @@
//公用
GoUse(function () {
if (GoExtData){
console.log("GoExtData",JSON.stringify(GoExtData))
}
// 定义一个名为 button-counter 的新组件
document.title = "govue";
document
.getElementsByName("keywords")[0]
.setAttribute("content", "govue,服务端渲染,ssr");
Vue.component('my-title', {
template: '<h1 id="title">govue</h1>'
});
});
@ -26,11 +10,4 @@ GoUse(function () {
//分页面
GoUseRegistered("index", function (query) {
new Vue({
el: "#app",
data: {
"desc": "基础golang开发的一套vue服务端渲染方案"
},
});
});
Loading…
Cancel
Save