Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bd1b774

Browse files
Merge pull request #26 from kodakyellow/nodeStreaming
inserted renderToNodeStream code
2 parents 085f964 + 64785f2 commit bd1b774

File tree

5 files changed

+158
-48
lines changed

5 files changed

+158
-48
lines changed

‎SSRtest/ModifiedReact.js‎

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,7 +2204,8 @@ var ReactDOMServerRenderer = function () {
22042204
// TODO: type this more strictly:
22052205

22062206

2207-
ReactDOMServerRenderer.prototype.read = function read(bytes, cache) {
2207+
ReactDOMServerRenderer.prototype.read = function read(bytes, cache, isStreaming,
2208+
streamingStart) {
22082209
/*
22092210
--- Component caching variables ---
22102211
start: Tracks start index in output string and templatization data for cached components
@@ -2304,7 +2305,13 @@ var ReactDOMServerRenderer = function () {
23042305
else r = this.render(child, frame.context, frame.domNamespace);
23052306

23062307
// For simple (non-template) caching, save start index of component in output string
2307-
if (!isTemplate) start[cacheKey] = out.length;
2308+
if (!isTemplate) {
2309+
if (isStreaming) {
2310+
// streamingStart[cacheKey] = out.length;
2311+
streamingStart[cacheKey] = streamingStart.sliceStartCount + out.length;
2312+
console.log("finalcount", streamingStart.finalSliceStart);
2313+
} else start[cacheKey] = out.length;
2314+
}
23082315
} else { // Component found in cache
23092316
if (isTemplate) {
23102317
restoredTemplate = restoreProps(reply, realProps, lookup);
@@ -2326,47 +2333,53 @@ var ReactDOMServerRenderer = function () {
23262333
/*
23272334
--- After initial render of cacheable components, recover from output string and store in cache ---
23282335
*/
2329-
for (let component in start) {
2330-
let tagStack = [];
2331-
let tagStart;
2332-
let tagEnd;
2333-
let componentStart = (typeof start[component] === 'object') ? start[component].startIndex : start[component];
2334-
2335-
do {
2336-
if (!tagStart) tagStart = componentStart;
2337-
else tagStart = (out[tagEnd] === '<') ? tagEnd : out.indexOf('<', tagEnd);
2338-
tagEnd = out.indexOf('>', tagStart) + 1;
2339-
// Skip stack logic for void/self-closing elements and HTML comments
2340-
// Note: Does not account for tags inside HTML comments
2341-
if (out[tagEnd - 2] !== '/' && out[tagStart + 1] !== '!') {
2342-
// Push opening tags onto stack; pop closing tags off of stack
2343-
if (out[tagStart + 1] !== '/') tagStack.push(out.slice(tagStart, tagEnd));
2344-
else tagStack.pop();
2336+
if (!isStreaming) {
2337+
for (let component in start) {
2338+
let tagStack = [];
2339+
let tagStart;
2340+
let tagEnd;
2341+
let componentStart = (typeof start[component] === 'object') ? start[component].startIndex : start[component];
2342+
2343+
do {
2344+
if (!tagStart) tagStart = componentStart;
2345+
else tagStart = (out[tagEnd] === '<') ? tagEnd : out.indexOf('<', tagEnd);
2346+
tagEnd = out.indexOf('>', tagStart) + 1;
2347+
// Skip stack logic for void/self-closing elements and HTML comments
2348+
// Note: Does not account for tags inside HTML comments
2349+
if (out[tagEnd - 2] !== '/' && out[tagStart + 1] !== '!') {
2350+
// Push opening tags onto stack; pop closing tags off of stack
2351+
if (out[tagStart + 1] !== '/') tagStack.push(out.slice(tagStart, tagEnd));
2352+
else tagStack.pop();
2353+
}
2354+
} while (tagStack.length !== 0);
2355+
// Cache component by slicing 'out'
2356+
const cachedComponent = out.slice(componentStart, tagEnd);
2357+
if (typeof start[component] === 'object') {
2358+
saveTemplates.push(start[component]);
2359+
start[component].endIndex = tagEnd;
23452360
}
2346-
} while (tagStack.length !== 0);
2347-
// Cache component by slicing 'out'
2348-
const cachedComponent = out.slice(componentStart, tagEnd);
2349-
if (typeof start[component] === 'object') {
2350-
saveTemplates.push(start[component]);
2351-
start[component].endIndex = tagEnd;
2361+
cache.set(component, cachedComponent);
23522362
}
2353-
cache.set(component, cachedComponent);
2354-
}
23552363

2356-
// After caching all cacheable components, restore props to templates
2357-
if (saveTemplates) {
2358-
let outCopy = out;
2359-
out = '';
2360-
let bookmark = 0;
2361-
saveTemplates.sort((a, b) => a.startIndex - b.startIndex);
2362-
// Rebuild output string with actual props
2363-
saveTemplates.forEach(savedTemplate => {
2364-
out += outCopy.substring(bookmark, savedTemplate.startIndex);
2365-
bookmark = savedTemplate.endIndex;
2366-
out += restoreProps(outCopy.slice(savedTemplate.startIndex, savedTemplate.endIndex),
2367-
savedTemplate.realProps, savedTemplate.lookup);
2368-
});
2369-
out += outCopy.substring(bookmark, outCopy.length);
2364+
// After caching all cacheable components, restore props to templates
2365+
if (saveTemplates) {
2366+
let outCopy = out;
2367+
out = '';
2368+
let bookmark = 0;
2369+
saveTemplates.sort((a, b) => a.startIndex - b.startIndex);
2370+
// Rebuild output string with actual props
2371+
saveTemplates.forEach(savedTemplate => {
2372+
out += outCopy.substring(bookmark, savedTemplate.startIndex);
2373+
bookmark = savedTemplate.endIndex;
2374+
out += restoreProps(outCopy.slice(savedTemplate.startIndex, savedTemplate.endIndex),
2375+
savedTemplate.realProps, savedTemplate.lookup);
2376+
});
2377+
out += outCopy.substring(bookmark, outCopy.length);
2378+
}
2379+
} else {
2380+
// console.log(out.length, streamingStart);
2381+
streamingStart.sliceStartCount += out.length;
2382+
console.log("rolling count", streamingStart["sliceStartCount"]);
23702383
}
23712384
return out;
23722385
};
@@ -2653,21 +2666,29 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function"
26532666
var ReactMarkupReadableStream = function (_Readable) {
26542667
_inherits(ReactMarkupReadableStream, _Readable);
26552668

2656-
function ReactMarkupReadableStream(element, makeStaticMarkup) {
2669+
function ReactMarkupReadableStream(element, makeStaticMarkup,cache,streamingStart) {
26572670
_classCallCheck1ドル(this, ReactMarkupReadableStream);
26582671

26592672
var _this = _possibleConstructorReturn(this, _Readable.call(this, {}));
26602673
// Calls the stream.Readable(options) constructor. Consider exposing built-in
26612674
// features like highWaterMark in the future.
26622675

2663-
2676+
_this.cache = cache;
2677+
_this.streamingStart = streamingStart;
26642678
_this.partialRenderer = new ReactDOMServerRenderer(element, makeStaticMarkup);
26652679
return _this;
26662680
}
26672681

26682682
ReactMarkupReadableStream.prototype._read = function _read(size) {
26692683
try {
2670-
this.push(this.partialRenderer.read(size));
2684+
this.push(
2685+
this.partialRenderer.read(
2686+
size,
2687+
this.cache,
2688+
true,
2689+
this.streamingStart
2690+
)
2691+
);
26712692
} catch (err) {
26722693
this.emit('error', err);
26732694
}
@@ -2682,8 +2703,13 @@ var ReactMarkupReadableStream = function (_Readable) {
26822703
*/
26832704

26842705

2685-
function renderToNodeStream(element) {
2686-
return new ReactMarkupReadableStream(element, false);
2706+
function renderToNodeStream(element, cache, streamingStart) {
2707+
return new ReactMarkupReadableStream(
2708+
element,
2709+
false,
2710+
cache,
2711+
streamingStart
2712+
);
26872713
}
26882714

26892715
/**

‎SSRtest/src/server/cacheStream.js‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Transform } from "stream";
2+
import { create } from "domain";
3+
4+
const createCacheStream = (cache, streamingStart) => {
5+
const bufferedChunks = [];
6+
return new Transform({
7+
// transform() is called with each chunk of data
8+
transform(data, enc, cb) {
9+
// We store the chunk of data (which is a Buffer) in memory
10+
bufferedChunks.push(data);
11+
// Then pass the data unchanged onwards to the next stream
12+
cb(null, data);
13+
},
14+
15+
// flush() is called when everything is done
16+
flush(cb) {
17+
// We concatenate all the buffered chunks of HTML to get the full HTML
18+
// then cache it at "key"
19+
20+
// console.log(cache);
21+
// console.log(bufferedChunks.join());
22+
// cache.set(key, Buffer.concat(bufferedChunks));
23+
// console.log("final", streamingStart.finalSliceStart);
24+
//joinedChunks = bufferedChunks.join("");
25+
let html = bufferedChunks.join("");
26+
delete streamingStart.sliceStartCount;
27+
28+
for (let component in streamingStart) {
29+
let tagStack = [];
30+
let tagStart;
31+
let tagEnd;
32+
33+
do {
34+
if (!tagStart) tagStart = streamingStart[component];
35+
else
36+
tagStart =
37+
html[tagEnd] === "<" ? tagEnd : html.indexOf("<", tagEnd);
38+
tagEnd = html.indexOf(">", tagStart) + 1;
39+
// Skip stack logic for void/self-closing elements
40+
if (html[tagEnd - 2] !== "/") {
41+
// Push opening tags onto stack; pop closing tags off of stack
42+
if (html[tagStart + 1] !== "/")
43+
tagStack.push(html.slice(tagStart, tagEnd));
44+
else tagStack.pop();
45+
}
46+
} while (tagStack.length !== 0);
47+
//console.log(html.slice(streamingStart[component], tagEnd));
48+
// cache component by slicing 'html'
49+
cache.storage.set(component, html.slice(streamingStart[component], tagEnd));
50+
}
51+
//console.log("to be saved:", bufferedChunks.join(""));
52+
//console.log(cache);
53+
cb();
54+
}
55+
});
56+
};
57+
58+
export default createCacheStream;

‎SSRtest/src/server/index.js‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,36 @@ import flushChunks from 'webpack-flush-chunks';
77

88
import App from '../shared/App';
99

10+
import createCacheStream from "./cacheStream";
1011
// can pass in max-size, otherwise defaults to 1 million
1112
const cache = new ReactCC.ComponentCache();
13+
// Force NodeStream
14+
15+
const htmlStart =
16+
'<html><head><title>Page</title></head><body><div id="react-root">';
17+
const htmlEnd = "</div></body></html>";
18+
19+
20+
const streamingStart = {
21+
sliceStartCount: htmlStart.length,
22+
};
1223
/**
1324
* @param clientStats Parameter passed by hot server middleware
1425
*/
1526
export default ({ clientStats }) => async (req, res) => {
27+
// Need To Come back To If Statement
28+
if(true){
29+
const cacheStream = createCacheStream(cache, streamingStart);
30+
cacheStream.pipe(res);
31+
cacheStream.write(htmlStart);
32+
33+
const stream = ReactCC.renderToNodeStream(<App />, cache, streamingStart);
34+
stream.pipe(cacheStream, { end: false });
35+
stream.on("end", () => {
36+
cacheStream.end(htmlEnd);
37+
});
38+
}
39+
else{
1640
const app = <App />;
1741
const start_cached = process.hrtime();
1842
// const appString = ReactCC.renderToStaticMarkup(app, cache);
@@ -32,4 +56,6 @@ export default ({ clientStats }) => async (req, res) => {
3256
styles,
3357
cssHash
3458
});
59+
}
60+
3561
};

‎SSRtest/src/shared/App.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ export default class App extends Component {
1818
<div>
1919
<h1>THIS IS AN APP</h1>
2020
<Button cache />
21-
<BlogPost day="Monday" cachetemplatized="day" />
22-
<BlogPost day="Tuesday" cache templatized="day" />
21+
<BlogPost cache />
22+
<BlogPost cache />
2323

2424
<List />
2525

‎SSRtest/src/shared/List.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default class List extends Component {
1212
let bunchOfProducts = [];
1313
const templatizedProps = ["name", "description", "price"];
1414
for (let i=0; i<100; i++) {
15-
bunchOfProducts.push(<ProductInfo key={i} name={`Thing ${i}`} description="This product is awesome!" price={i * 10} nonTemplatized="THIS TEXT SHOULD NEVER CHANGE" cache templatized={templatizedProps} />);
15+
bunchOfProducts.push(<ProductInfo key={i} name={`Thing ${i}`} description="This product is awesome!" price={i * 10} nonTemplatized="THIS TEXT SHOULD NEVER CHANGE" cache />);
1616
}
1717
return (
1818
<div>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /