Authored by 陈峰

commit

... ... @@ -19,16 +19,12 @@ const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const favicon = require('serve-favicon');
const yohoLib = require('yoho-node-lib');
const session = require('express-session');
const redis = require('connect-redis');
const pkg = require('./package.json');
const devtools = require('./doraemon/middleware/devtools');
const _ = require('lodash');
const uuid = require('uuid');
const RedisStore = redis(session);
// 全局注册library
yohoLib.global(config);
... ... @@ -38,103 +34,90 @@ global.doraemon = path.resolve('./doraemon');
exports.createApp = async (app) => {
// 向模板注入变量
app.locals.devEnv = app.get('env') === 'development';
app.locals.proEnv = app.get('env') === 'production';
app.locals.version = pkg.version;
app.locals.devEnv = app.get('env') === 'development';
app.locals.proEnv = app.get('env') === 'production';
app.locals.version = pkg.version;
const logger = global.yoho.logger;
const logger = global.yoho.logger;
if (app.locals.devEnv) {
app.use(devtools());
}
if (app.locals.devEnv) {
app.use(devtools());
}
app.use('/crm/common/ok.jsp', (req, res) => {
res.status(200).end();
});
app.head('*', (req, res) => {
res.status(200).end();
});
app.use('/crm/common/ok.jsp', (req, res) => {
res.status(200).end();
});
app.head('*', (req, res) => {
res.status(200).end();
});
app.use(favicon(path.join(__dirname, '/favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(favicon(path.join(__dirname, '/favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
// 添加请求上下文
app.use(global.yoho.httpCtx());
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: path.join(__dirname, 'doraemon/views'),
partialsDir: path.join(__dirname, 'doraemon/views/partial'),
views: path.join(__dirname, 'doraemon/views'),
helpers: _.assign(global.yoho.helpers, require('./utils/helpers'))
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use(session({
proxy: true,
resave: false,
saveUninitialized: true,
unset: 'destroy',
secret: '82dd7e724f2c6870472c89dfa43cf48d',
name: 'yohoblk_session2',
cookie: {
domain: 'yohoblk.com',
httpOnly: false
},
store: new RedisStore(config.redis.session)
}));
app.use((req, res, next) => {
req.user = {}; // 全局的用户数据
req.yoho = {}; // req和res绑定yoho对象,用于传递全局数据, 如req.yoho.channel等
if (!req.sessionID) {
req.sessionID = uuid.v4();
}
next();
});
app.use(global.yoho.httpCtx());
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: path.join(__dirname, 'doraemon/views'),
partialsDir: path.join(__dirname, 'doraemon/views/partial'),
views: path.join(__dirname, 'doraemon/views'),
helpers: _.assign(global.yoho.helpers, require('./utils/helpers'))
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use((req, res, next) => {
req.user = {}; // 全局的用户数据
req.yoho = {}; // req和res绑定yoho对象,用于传递全局数据, 如req.yoho.channel等
if (!req.sessionID) {
req.sessionID = uuid.v4();
}
next();
});
// dispatcher
try {
const user = require('./doraemon/middleware/user');
const setYohoData = require('./doraemon/middleware/set-yoho-data');
const errorHanlder = require('./doraemon/middleware/error-handler');
const setPageInfo = require('./doraemon/middleware/set-pageinfo');
const ssrApi = require('./doraemon/middleware/ssr-api');
const layoutTools = require('./doraemon/middleware/layout-tools');
try {
const user = require('./doraemon/middleware/user');
const setYohoData = require('./doraemon/middleware/set-yoho-data');
const errorHanlder = require('./doraemon/middleware/error-handler');
const setPageInfo = require('./doraemon/middleware/set-pageinfo');
const ssrApi = require('./doraemon/middleware/ssr-api');
const layoutTools = require('./doraemon/middleware/layout-tools');
// YOHO 前置中间件
app.use(setYohoData());
app.use(user());
app.use(setPageInfo());
app.use(ssrApi());
app.use(layoutTools());
app.use(setYohoData());
app.use(user());
app.use(setPageInfo());
app.use(ssrApi());
app.use(layoutTools());
await require('./doraemon/middleware/ssr')(app);
require('./dispatch')(app);
await require('./doraemon/middleware/ssr')(app);
require('./dispatch')(app);
app.all('*', errorHanlder.notFound()); // 404
app.all('*', errorHanlder.notFound()); // 404
// YOHO 后置中间件
app.use(errorHanlder.serverError());
app.use(errorHanlder.serverError());
// listener
app.listen(config.port, function() {
logger.info(`worker is started at ${config.port}`);
});
} catch (err) {
logger.error(err);
app.listen(config.port, function() {
logger.info(`worker is started at ${config.port}`);
});
} catch (err) {
logger.error(err);
process.exit(1); //eslint-disable-line
}
}
};
... ...
... ... @@ -9,143 +9,144 @@ const logger = global.yoho.logger;
const {createBundleRenderer} = require('vue-server-renderer');
const routes = [
{
route: /product\/\d+/,
cache: true,
{
route: /product\/\d+/,
cache: true,
// disable: true
},
{
route: '/channel',
cacheRule: 'pathname',
cache: true
},
{
route: '/channel/search',
cacheRule: 'pathname',
cache: true
},
{
route: '/channel/men',
cacheRule: 'pathname',
cache: true
},
{
route: '/channel/women',
cacheRule: 'pathname',
cache: true
},
{
route: '/about',
cacheRule: 'pathname',
cache: true
},
},
{
route: '/channel',
cacheRule: 'pathname',
cache: true
},
{
route: '/channel/search',
cacheRule: 'pathname',
cache: true
},
{
route: '/channel/men',
cacheRule: 'pathname',
cache: true
},
{
route: '/channel/women',
cacheRule: 'pathname',
cache: true
},
{
route: '/about',
cacheRule: 'pathname',
cache: true
},
];
const isDev = process.env.NODE_ENV === 'development' || !process.env.NODE_ENV;
let renderer;
let template = fs.readFileSync(path.join(__dirname, '../../index.html'), 'utf-8');
const templatePath = isDev ? '../../src/index.html' : '../../index.html';
let template = fs.readFileSync(path.join(__dirname, templatePath), 'utf-8');
const microCache = LRU({ // eslint-disable-line
max: 1000,
maxAge: 2000
max: 1000,
maxAge: 2000
});
const getContext = (req) => {
return {
url: req.url,
title: 'BLK!',
user: req.user,
env: {
isApp: req.yoho.isApp,
isiOS: req.yoho.isiOS,
isAndroid: req.yoho.isAndroid,
isYohoBuy: req.yoho.isYohoBuy,
channel: req.yoho.channel,
clientIp: req.yoho.clientIp
}
};
return {
url: req.url,
title: 'BLK!',
user: req.user,
env: {
isApp: req.yoho.isApp,
isiOS: req.yoho.isiOS,
isAndroid: req.yoho.isAndroid,
isYohoBuy: req.yoho.isYohoBuy,
channel: req.yoho.channel,
clientIp: req.yoho.clientIp
}
};
};
const render = ({cache, cacheRule}) => {
return (req, res, next) => {
const reqUrl = url.parse(req.url);
return (req, res, next) => {
const reqUrl = url.parse(req.url);
if (cache && reqUrl[cacheRule]) {
const html = microCache.get(reqUrl[cacheRule]);
if (cache && reqUrl[cacheRule]) {
const html = microCache.get(reqUrl[cacheRule]);
if (html) {
console.log('cache', req.url);
return res.send(html);
}
}
let context = getContext(req);
if (html) {
console.log('cache', req.url);
return res.send(html);
}
}
let context = getContext(req);
renderer.renderToString(context, (err, html) => {
if (err) {
renderer.renderToString(context, (err, html) => {
if (err) {
// TODO 处理错误类型
return next(err);
}
if (cache && reqUrl[cacheRule]) {
microCache.set(reqUrl[cacheRule], html);
}
return res.send(html);
});
};
return next(err);
}
if (cache && reqUrl[cacheRule]) {
microCache.set(reqUrl[cacheRule], html);
}
return res.send(html);
});
};
};
const devRender = () => {
return (req, res, next) => {
let context = getContext(req);
process.send({action: 'ssr_request', context});
let event = msg => {
process.removeListener('message', event);
if (msg.action === 'ssr_request') {
if (msg.err) {
try {
const err = JSON.parse(msg.err);
if (err.code === 404) {
return next();
}
return next(err);
} catch (e) {
return next({
code: 500,
message: msg.err
});
}
}
return res.end(msg.html);
return (req, res, next) => {
let context = getContext(req);
process.send({action: 'ssr_request', context});
let event = msg => {
process.removeListener('message', event);
if (msg.action === 'ssr_request') {
if (msg.err) {
try {
const err = JSON.parse(msg.err);
if (err.code === 404) {
return next();
}
};
process.on('message', event);
return next(err);
} catch (e) {
return next({
code: 500,
message: msg.err
});
}
}
return res.end(msg.html);
}
};
process.on('message', event);
};
};
const loadBundle = async (errorCount = 0) => {
if (!isDev) {
if (errorCount > 5) {
throw {
code: 9999,
message: 'ssr bundle download faild 5!'
};
}
await Promise.all([
rp(`http://cdn.yoho.cn/yohoblk-wap/bundle/yoho-ssr-server-${pkg.version}.json`, {json: true}),
rp(`http://cdn.yoho.cn/yohoblk-wap/bundle/yoho-ssr-client-${pkg.version}.json`, {json: true}),
]).then(results => {
logger.warn('ssr file is loaded');
renderer = createBundleRenderer(results[0], {
runInNewContext: false,
template,
clientManifest: results[1]
});
}).catch(() => {
return loadBundle(errorCount + 1);
});
if (!isDev) {
if (errorCount > 5) {
throw {
code: 9999,
message: 'ssr bundle download faild 5!'
};
}
await Promise.all([
rp(`http://cdn.yoho.cn/yohoblk-wap/bundle/yoho-ssr-server-${pkg.version}.json`, {json: true}),
rp(`http://cdn.yoho.cn/yohoblk-wap/bundle/yoho-ssr-client-${pkg.version}.json`, {json: true}),
]).then(results => {
logger.warn('ssr file is loaded');
renderer = createBundleRenderer(results[0], {
runInNewContext: false,
template,
clientManifest: results[1]
});
}).catch(() => {
return loadBundle(errorCount + 1);
});
// const serverBundle = require(`../../public/dist/yohoblk-wap/bundle/yoho-ssr-server-${pkg.version}.json`);
// const clientManifest = require(`../../public/dist/yohoblk-wap/bundle/yoho-ssr-client-${pkg.version}.json`);
... ... @@ -155,16 +156,16 @@ const loadBundle = async (errorCount = 0) => {
// template,
// clientManifest
// });
}
}
};
const ssrRender = options => isDev ? devRender(options) : render(options);
module.exports = async (app) => {
await loadBundle();
_.each(routes, r => {
if (!r.disable) {
app.get(r.route, ssrRender(r));
}
});
await loadBundle();
_.each(routes, r => {
if (!r.disable) {
app.get(r.route, ssrRender(r));
}
});
};
... ...
This diff could not be displayed because it is too large.
... ... @@ -55,14 +55,14 @@
"vue-html-loader": "^1.2.4",
"vue-infinite-scroll": "^2.0.1",
"vue-lazyload": "^1.0.6",
"vue-loader": "=13.7.0",
"vue-loader": "^13.7.0",
"vue-router": "=3.0.1",
"vue-server-renderer": "=2.5.13",
"vue-style-loader": "^3.0.3",
"vue-swipe": "^2.0.3",
"vue-template-compiler": "^2.5.13",
"vue-template-compiler": "=2.5.13",
"vue-touch": "2.0.0-beta.3",
"vuex": "=3.0.1",
"vuex": "^3.0.1",
"winston": "^2.2.0",
"yoho-cookie": "1.2.0",
"yoho-jquery": "^2.2.4",
... ... @@ -130,9 +130,10 @@
"url-loader": "^0.5.9",
"webpack": "3.3",
"webpack-bundle-analyzer": "^2.9.1",
"webpack-cli": "=2.0.15",
"webpack-dashboard": "^0.1.8",
"webpack-dev-middleware": "^1.12.0",
"webpack-dev-server": "^3.1.4",
"webpack-dev-server": "2.11.1",
"webpack-hot-middleware": "^2.18.2",
"webpack-merge": "^4.1.0",
"webpack-node-externals": "^1.6.0",
... ...
This diff could not be displayed because it is too large.