Skip to content

Commit 5529155

Browse files
committed
Draft version of the client-side initialization code
1 parent e4f317e commit 5529155

File tree

8 files changed

+101
-9
lines changed

8 files changed

+101
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ only need to call `adopt-dev-deps` again if you update
6363
the specified aspect ratio regardless the width you set.
6464

6565
### <a name="utilities">Utilities</a>
66+
- [**Client**](docs/client.md) &mdash; Client-side initialization code.
6667
- [**Config**](docs/config.md) &mdash; Isomorphic app config;
6768
- [**Global Styles**](docs/global-styles.md) &mdash; Global styles necessary for
6869
a generic application;

__tests__/__snapshots__/index.js.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Object {
88
"Link": [Function],
99
"NavLink": [Function],
1010
"ScalableRect": [Function],
11+
"client": [Function],
1112
"config": undefined,
1213
"isomorphy": Object {
1314
"buildTimestamp": [Function],
@@ -115,6 +116,7 @@ Object {
115116
"Link": [Function],
116117
"NavLink": [Function],
117118
"ScalableRect": [Function],
119+
"client": [Function],
118120
"config": Config {
119121
"SECRET": Object {
120122
"dummySecretKey": "Dummy Secret Value",

docs/client.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Client
2+
Client-side intialization code.
3+
4+
*Documentation will be added here*

package-lock.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"request-ip": "^2.0.2",
2929
"serialize-javascript": "^1.4.0",
3030
"serve-favicon": "^2.5.0",
31+
"shortid": "^2.2.8",
3132
"url-parse": "^1.2.0",
3233
"winston": "^2.4.0"
3334
},
@@ -105,5 +106,5 @@
105106
"prepublishOnly": "npm run build",
106107
"test": "npm run lint && npm run jest"
107108
},
108-
"version": "0.3.0"
109+
"version": "0.3.1"
109110
}

src/client/index.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/client/index.jsx

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* Initialization of client-side code.
3+
*/
4+
5+
/* global BUILD_INFO document window */
6+
7+
import forge from 'node-forge';
8+
import React from 'react';
9+
import ReactDom from 'react-dom';
10+
import shortId from 'shortid';
11+
import { Provider } from 'react-redux';
12+
import { BrowserRouter } from 'react-router-dom';
13+
14+
/**
15+
* Renders given application into DOM, providing it with Redux store, if given.
16+
* @param {Function} Application Root ReactJS component of the app.
17+
* @param {Object} store Optional. Redux store.
18+
*/
19+
function render(Application, store) {
20+
let app = <BrowserRouter><Application /></BrowserRouter>;
21+
if (store) app = <Provider store={store}>{app}</Provider>;
22+
ReactDom.hydrate(app, document.getElementById('react-view'));
23+
}
24+
25+
/**
26+
* Initializes the code at client side. It takes care about receiving the data
27+
* injected at the server-side, and also about setting up client side of hot
28+
* module reloading (HMR).
29+
* @param {Object} options Parameters accepted by the function.
30+
* @param {Function} options.Application Root component of the application to be
31+
* rendered at the client side.
32+
* @param {String} options.appModulePath Optional. Path to the root module of
33+
* the application. It should be provided to setup HMR.
34+
* @param {Function} options.customInit Optional. A custom function to be called
35+
* before initial client-side rendering. It should return a promise that
36+
* resolves to an object with the following params:
37+
* - store {Object} - Optional. Redux store to be used.
38+
*/
39+
export default async function Init(options) {
40+
/* Injection of build-time data information into the client-side bundle. */
41+
window.TRU_BUILD_INFO = BUILD_INFO;
42+
window.TRU_FRONT_END = true;
43+
44+
/* Removes data injection script out of the document. */
45+
const block = document.querySelector('script[id="inj"]');
46+
document.getElementsByTagName('body')[0].removeChild(block);
47+
48+
/* Decodes data injected at the server side. */
49+
const { key } = window.TRU_BUILD_INFO;
50+
let data = forge.util.decode64(window.INJ);
51+
const decipher = forge.cipher.createDecipher('AES-CBC', key);
52+
decipher.start({ iv: data.slice(0, 32) });
53+
decipher.update(forge.util.createBuffer(data.slice(32)));
54+
decipher.finish();
55+
data = JSON.parse(forge.util.decodeUtf8(decipher.output.data));
56+
57+
window.CONFIG = data.CONFIG;
58+
window.ISTATE = data.ISTATE;
59+
60+
let store;
61+
if (options.customInit) ({ store } = await options.customInit());
62+
render(options.Application, store);
63+
64+
if (module.hot && options.appModulePath) {
65+
module.hot.accept(
66+
options.appModulePath,
67+
() => render(options.Application, store),
68+
);
69+
70+
/* HMR of CSS code each time webpack hot middleware updates the code. */
71+
/* eslint-disable no-underscore-dangle */
72+
const hotReporter = window.__webpack_hot_middleware_reporter__;
73+
/* eslint-enable no-underscore-dangle */
74+
const hotSuccess = hotReporter.success;
75+
hotReporter.success = () => {
76+
const stamp = shortId();
77+
const links = document.querySelectorAll('link[rel=stylesheet]');
78+
for (let i = 0; i < links.length; i += 1) {
79+
links[i].href = `${links[i].href.match(/[^?]*/)}?v=${stamp}`;
80+
}
81+
hotSuccess();
82+
};
83+
}
84+
}

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import client from 'client';
12
import Avatar from 'components/Avatar';
23
import Button from 'components/Button';
34
import Link from 'components/Link';
@@ -13,6 +14,7 @@ const server = utils.isomorphy.isServerSide() ?
1314
requireWeak('topcoder-react-utils/dist/server') : null;
1415

1516
module.exports = {
17+
client,
1618
Avatar,
1719
Button,
1820
Link,

0 commit comments

Comments
 (0)