Authored by 陈峰

兼容wkwebview的defer不生效,延迟js加载

... ... @@ -14,7 +14,6 @@ const watcher = {
let renderer;
let realyPromise;
let template = fs.readFileSync(path.join(__dirname, './apps/index.html'), 'utf-8');
if (cluster.isMaster) {
const masterApp = express();
... ... @@ -22,7 +21,7 @@ if (cluster.isMaster) {
realyPromise = devServer(masterApp, params => {
renderer = createBundleRenderer(params.bundle, Object.assign(params.options, {
runInNewContext: false,
template
inject: false
}));
});
let childWorker = cluster.fork();
... ... @@ -34,7 +33,12 @@ if (cluster.isMaster) {
if (err) {
console.error(err);
}
worker.send({action: 'ssr_request', html, err: err && JSON.stringify(err)});
const styles = msg.context.renderStyles();
const scripts = msg.context.renderScripts();
const resources = msg.context.renderResourceHints();
const states = msg.context.renderState();
worker.send({action: 'ssr_request', html, styles, scripts, resources, states, err: err && JSON.stringify(err)});
});
});
}
... ...
... ... @@ -9,6 +9,7 @@ const routes = require('../../config/ssr-routes');
const redis = require('../../utils/redis');
const routeEncode = require('../../utils/route-encode');
const {createBundleRenderer} = require('vue-server-renderer');
const Handlebars = require('handlebars');
const logger = global.yoho.logger;
const config = global.yoho.config;
... ... @@ -18,8 +19,11 @@ let renderer;
let serverBundle;
let degradeHtml;
const hbs = fs.readFileSync(path.join(__dirname, '../views/index.hbs'), 'utf-8');
const template = Handlebars.compile(hbs);
if (!isDev) {
const template = fs.readFileSync(path.join(__dirname, '../../index.html'), 'utf-8');
degradeHtml = fs.readFileSync(path.join(__dirname, '../../degrade.html'), 'utf-8');
... ... @@ -28,11 +32,28 @@ if (!isDev) {
renderer = createBundleRenderer(serverBundle, {
runInNewContext: false,
template,
clientManifest
clientManifest,
inject: false
});
}
const REG_SCRIPT = /src="([^"]+)"/g;
const asyncLoadScripts = (renderScripts) => {
let match;
const scripts = [];
while ((match = REG_SCRIPT.exec(renderScripts))) {
scripts.push({
src: match[1],
index: scripts.length
});
}
return scripts;
};
const getContext = (req) => {
return {
url: req.url,
... ... @@ -103,13 +124,33 @@ const render = (route) => {
let context = getContext(req);
renderer.renderToString(context, (err, html) => {
if (err) {
return handlerError(err, req, res, next);
}
const styles = context.renderStyles();
let scripts = context.renderScripts();
const resources = context.renderResourceHints();
const states = context.renderState();
let asyncScripts;
if (req.yoho.isiOS) {
asyncScripts = asyncLoadScripts(scripts);
}
const result = template({
html,
styles,
scripts,
asyncScripts,
resources,
states
});
if (config.useCache && route.cache && ck) {
redis.setex(ck, route.cacheTime || 60, html);
redis.setex(ck, route.cacheTime || 60, result);
}
return res.send(html);
return res.send(result);
});
} catch (error) {
return next(error);
... ... @@ -158,10 +199,21 @@ const devRender = (route) => {
} catch (error) {} // eslint-disable-line
return handlerError(err, req, res, next);
}
let {styles, scripts, resources, states, html} = msg;
const result = template({
html,
styles,
scripts,
resources,
states
});
if (config.useCache && route.cache && ck) {
redis.setex(ck, route.cacheTime || 60, msg.html);
redis.setex(ck, route.cacheTime || 60, result);
}
return res.end(msg.html);
return res.end(result);
}
};
... ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<meta name="keywords" content="">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="telephone=no" name="format-detection">
<meta content="email=no" name="format-detection">
{{{resources}}}
{{{styles}}}
<script type="text/javascript">
(function(d,c){var e=d.documentElement,a="orientationchange" in window?"orientationchange":"resize",b=function(){var f=e.clientWidth;if(!f){return}if(f>=750){e.style.fontSize="40px"}else{e.style.fontSize=40*(f/750)+"px"}};if(!d.addEventListener){return}b();c.addEventListener(a,b,false);d.addEventListener("DOMContentLoaded",b,false)})(document,window);
</script>
</head>
<body>
{{{html}}}
<div id="degrade-app"></div>
<div id="main-wrap">
<div id="no-download"></div>
</div>
{{{states}}}
{{#if asyncScripts}}
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded')
setTimeout(function() {
var s = document.getElementsByTagName("script")[0];
{{# asyncScripts}}
var hm{{index}} = document.createElement("script");
hm{{index}}.async = true;
hm{{index}}.src = "{{src}}";
s.parentNode.insertBefore(hm{{index}}, s);
{{/ asyncScripts}}
}, 200)
})
</script>
{{^}}
{{{scripts}}}
{{/if}}
<script>
setTimeout(function() {
(function(w, d, s, j, f) {
var a = d.createElement(s);
var m = d.getElementsByTagName(s)[0];
w.YohoAcquisitionObject = f;
w[f] = function() {
w[f].p = arguments;
};
a.async = 1;
a.src = j;
m.parentNode.insertBefore(a, m);
}(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//cdn.yoho.cn/yas-jssdk/2.4.18/yas.js', '_yas'));
var _hmt = _hmt || [];
(function() {
function getUid() {
var uid,
name = 'app_uid',
cookies = (document.cookie && document.cookie.split(';')) || [];
for (var i = 0; i < cookies.length; i++) {
if (cookies[i].indexOf(name) > -1) {
uid = decodeURIComponent(cookies[i].replace(name + '=', '').trim());
break;
}
}
if (!uid) return 0;
uid = uid.split('::');
if (!uid || uid.length < 4) {
return 0;
}
return uid[1];
}
function queryString() {
var vars = {},
hash,
i;
var hashes = window.location.search.slice(1).split('&');
for (i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars[hash[0]] = hash[1];
}
return vars;
}
var uid = getUid() || queryString().uid;
uid = uid === 0 ? '' : uid;
window._ozuid = uid; // 暴露ozuid
if (window._yas) {
window._yas(1 * new Date(), '2.4.16', 'yohoappweb', uid, '', '');
}
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?65dd99e0435a55177ffda862198ce841";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
}());
}, 500);
</script>
</body>
</html>
... ...