Skip to content

Commit

Permalink
feat: Remove all onEnter preload on server side, using client side …
Browse files Browse the repository at this point in the history
…fetch (#473)

* Refactor server architecture

* Separate store files

* Fix move all component data reset to componentWillUnmount

* Add user server provider

* Refactor cluster detail, add VM based and Helm components

* [wip] feat: VM based cluster support addNodes, resizeCluster, deleteNodes

* Fix Helm type cluster detail

* Fix cluster detail store
  • Loading branch information
sunnywx authored Oct 9, 2018
1 parent 7e1ff11 commit ebc5ac7
Show file tree
Hide file tree
Showing 97 changed files with 2,783 additions and 2,470 deletions.
3 changes: 0 additions & 3 deletions lib/log.js

This file was deleted.

16 changes: 7 additions & 9 deletions lib/request.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import agent from 'superagent';
import _ from 'lodash';

const debug = require('debug')('app');

const agentOptions = {
header: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
timeout: {
response: 10000,
deadline: 15000
response: 20000,
deadline: 30000
}
};

Expand Down Expand Up @@ -60,14 +62,10 @@ class HttpAgent {
.set(headers)
[method === 'get' ? 'query' : 'send'](params);

let resp = (res && res.body) || {};

if (resp.success && resp.redirect) {
location.href = resp.redirect;
}

return resp;
return !_.isEmpty(res) && res.body ? res.body : {};
} catch (err) {
debug(`res err: %O`, err.message);

if (err.timeout) {
return {
err: `Response timeout of ${agentOptions.timeout.response}ms exceeded`,
Expand Down
36 changes: 28 additions & 8 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ const yaml = require('js-yaml');
const appRoot = require('app-root-path');
const chokidar = require('chokidar');
const deepmerge = require('deepmerge');
const log = require('./log');

const debug = require('debug')('app');

// when node_modules is linked, app-root-path will fail to detect root dir
const appRootDir = (function() {
Expand Down Expand Up @@ -56,26 +57,45 @@ const getServerConfig = (key = '') => {
return key ? serverConfig[key] : serverConfig;
};

const cleanServerConfig = () => {
const cleanConfig = () => {
serverConfig = {};
};

const watchServerConfig = () => {
const watchConfig = () => {
const watcher = chokidar.watch([root('server/config.yml'), root('server/local_config.yml')], {
ignored: /(^|[/\\])\../
});

log('watching config files..');
watcher.on('all', (event, path) => {
log(`${event}: ${path}`);
cleanServerConfig();
debug(`${event}: ${path}`);
cleanConfig();
});
};

const watchServer = shouldWatch => {
if (shouldWatch) {
// watch server w/ lib change
const watcher = chokidar.watch([root('server'), root('lib')]);

watcher.on('ready', () => {
watcher.on('all', () => {
debug('Clearing */server/*, */lib/* module cache from server');

Object.keys(require.cache).forEach(function(id) {
if (/dashboard[\/\\](server|lib)[\/\\]/.test(id)) {
debug(`remove cache of %s`, id);
delete require.cache[id];
}
});
});
});
}
};

module.exports = {
root,
loadYaml,
getServerConfig,
cleanServerConfig,
watchServerConfig
watchConfig,
watchServer
};
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@
},
"scripts": {
"dev:client": "rimraf build && NODE_ENV=development webpack --config webpack.dev.js --progress",
"server": "DEBUG=op-dash BABEL_ENV=server NODE_ENV=development node server/server.js",
"pack:server": "webpack --config webpack.server.js --progress",
"server": "DEBUG_DEPTH=5 DEBUG=app BABEL_ENV=server NODE_ENV=development nodemon -w lib -w server server/server.js",
"dev:watch": "npm run dev:client -- --watch",
"dev": "rimraf build && npm run dev:client && npm run server",
"prod:build": "rimraf dist && NODE_ENV=production webpack -p --config webpack.prod.js",
"prod:serve": "NODE_ENV=production DEBUG=op-dash node dist/server.js",
"prod:serve": "NODE_ENV=production DEBUG=app node dist/server.js",
"prod": "npm run prod:build && npm run prod:serve",
"lint": "eslint . --fix",
"test:single": "NODE_ENV=testing jest --config jest.config.json -u",
Expand Down Expand Up @@ -79,7 +80,7 @@
"babel-jest": "^22.0.6",
"babel-loader": "7.1.1",
"babel-plugin-css-modules-transform": "^1.5.0",
"babel-plugin-lodash": "^3.3.2",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-module-resolver": "^3.0.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-react-remove-prop-types": "^0.4.5",
Expand Down Expand Up @@ -109,6 +110,7 @@
"koa-webpack": "^2.0.3",
"lint-staged": "^7.0.4",
"node-sass": "^4.5.3",
"nodemon": "^1.18.4",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "2.0.6",
Expand Down
11 changes: 4 additions & 7 deletions server/middleware/auth.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
const debug = require('debug')('op-dash');
const debug = require('debug')('app');

const authPages = ['dashboard', 'runtimes', 'purchased', 'profile', 'ssh_keys', 'store'];

module.exports = async (ctx, next) => {
const { cookies } = ctx;

// filter non-asset types
if (ctx.url.endsWith('.map')) {
return;
Expand All @@ -13,12 +15,7 @@ module.exports = async (ctx, next) => {
const page = (ctx.params.page || '').split('/')[0];
const needAuth = authPages.indexOf(page) > -1;

const brokenCookie = () => {
let cookies = ctx.cookies;
return !(cookies.get('user') && cookies.get('access_token'));
};

if (needAuth && brokenCookie()) {
if (needAuth && !(cookies.get('user') && cookies.get('access_token'))) {
// not login
ctx.redirect('/login?url=' + ctx.params.page);
}
Expand Down
2 changes: 1 addition & 1 deletion server/middleware/gzip.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const debug = require('debug')('op-dash');
const debug = require('debug')('app');

module.exports = async (ctx, next) => {
if (ctx.url.endsWith('.js') || ctx.url.endsWith('.css')) {
Expand Down
63 changes: 8 additions & 55 deletions server/middleware/render.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,21 @@
// if (process.env.COMPILE_CLIENT) {
// process.env.BABEL_ENV = 'server';
// }

const React = require('react');
const { renderToString } = require('react-dom/server');
const { StaticRouter } = require('react-router-dom');
const { matchRoutes, renderRoutes } = require('react-router-config');
const { Provider } = require('mobx-react');
const get = require('lodash/get');

const renderPage = require('../render-page');

const App = require('src/App').default;
const routes = require('src/routes').default;

const isProd = process.env.NODE_ENV === 'production';

const i18n = require('../i18n');
const { I18nextProvider } = require('react-i18next');

module.exports = async (ctx, next) => {
const branches = matchRoutes(routes, ctx.url);

// fix ssr notifications store not sync
ctx.store.notifications = [];

const promises = branches.map(
({ route, match }) =>
route.component.onEnter
? route.component.onEnter(ctx.store, match.params)
: Promise.resolve(null)
);

await Promise.all(promises);

const context = {};

try {
// const components = isProd
// ? renderToString(
// <I18nextProvider i18n={i18n}>
// <Provider rootStore={ctx.store} sock={null}>
// <StaticRouter location={ctx.url} context={context}>
// <App>{renderRoutes(routes)}</App>
// </StaticRouter>
// </Provider>
// </I18nextProvider>
// )
// : null;

// disable ssr
const components = null;


if (context.url) {
ctx.redirect(context.url);
ctx.body = '<!DOCTYPE html>redirecting';
return await next();
}
if (context.url) {
ctx.redirect(context.url);
ctx.body = '<!DOCTYPE html>redirecting';
return await next();
}

try {
ctx.body = renderPage({
isProd,
isProd: process.env.NODE_ENV === 'production',
title: get(ctx.store, 'config.app.title'),
children: components,
children: null,
state: JSON.stringify(ctx.store)
});
} catch (err) {
Expand Down
71 changes: 23 additions & 48 deletions server/middleware/store.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,40 @@
const url = require('url');
const { useStaticRendering } = require('mobx-react');
const { getServerConfig } = require('lib/utils');
const RootStore = require('stores/RootStore').default;

useStaticRendering(true);

const rootStore = new RootStore();
rootStore.registerStores();
// initial state for client app store
const store = {};

/**
* Middleware for creating the store
* @param ctx
* @param next
*/
module.exports = async (ctx, next) => {
try {
const config = getServerConfig();

// Create state for SSR
ctx.store = rootStore;

ctx.store.config = config;

// attach api server to ctx
let serverUrl = process.env.serverUrl || config.serverUrl;
// local config for server
const { config } = ctx.app;

let apiVer = process.env.apiVersion || config.apiVersion || 'v1';
let serverUrl = process.env.serverUrl || config.serverUrl;

// attach socket server
let socketUrl = process.env.socketUrl || config.socketUrl;
let apiVer = process.env.apiVersion || config.apiVersion || 'v1';

if (!serverUrl.startsWith('http')) {
serverUrl = 'http://' + serverUrl;
}
let socketUrl = process.env.socketUrl || config.socketUrl;

if (!socketUrl.startsWith('ws://')) {
socketUrl = 'ws://' + socketUrl;
}

const clientId = process.env.clientId || config.clientId;
const clientSecret = process.env.clientSecret || config.clientSecret;
// url.resolve need first string starts with http
ctx.store.apiServer = url.resolve(serverUrl, apiVer);
ctx.store.socketUrl = socketUrl;
ctx.store.clientId = clientId;
ctx.store.clientSecret = clientSecret;
if (!serverUrl.startsWith('http')) {
serverUrl = 'http://' + serverUrl;
}
if (!socketUrl.startsWith('ws://')) {
socketUrl = 'ws://' + socketUrl;
}

// attach login user info to store
const user = decodeURIComponent(ctx.cookies.get('user') || '{}');
const role = decodeURIComponent(ctx.cookies.get('role') || '');
try{
ctx.store.user = JSON.parse(user);
}catch(err){}
// url.resolve need first string starts with http
Object.assign(store, {
config,
socketUrl,
apiServer: url.resolve(serverUrl, apiVer),
clientId: process.env.clientId || config.clientId,
clientSecret: process.env.clientSecret || config.clientSecret
});

if (role === 'user') {
ctx.store.user.isDev = false;
ctx.store.user.isNormal = true;
}
ctx.store = store;

await next();
} catch (err) {
ctx.app.reportErr(err, ctx);
}
await next();
};
5 changes: 0 additions & 5 deletions server/models/roles.json

This file was deleted.

5 changes: 0 additions & 5 deletions server/models/users.json

This file was deleted.

2 changes: 1 addition & 1 deletion server/render-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const renderPage = (options = {}) => {
<noscript>You need to enable JavaScript to run this app</noscript>
<div id="root">
${options.children ? `<div id="root">${options.children}</div>` : `<div id="root"></div>`}
${options.children ? options.children : ''}
</div>
<script>
Expand Down
Loading

0 comments on commit ebc5ac7

Please sign in to comment.