Skip to content

Commit

Permalink
fix: verify and ensure consistent useStream flag (#1596)
Browse files Browse the repository at this point in the history
* fix: verify and ensure consistent useStream flag

* update sample poc-subapp
  • Loading branch information
jchip authored Apr 10, 2020
1 parent 276a93d commit b73118b
Show file tree
Hide file tree
Showing 19 changed files with 245 additions and 145 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ module.exports = function setup(handlerContext /*, asyncTemplate*/) {

const tokenHandlers = {
[CONTENT_MARKER]: context => {
return context.user.content && context.user.content.html || "";
return (context.user.content && context.user.content.html) || "";
},

[TITLE_MARKER]: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const Template = () => (
name="MainBody"
timestamp
elementId="subapp-mainbody"
streaming
useStream
async
hydrateServerData
serverSideRendering
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ hello
token process module subapp-web/lib/load not found
<!-- require(subapp-web/lib/load) END -->
</div>
<div class="blah" style="background: green;"><!-- BEGIN require(subapp-web/lib/load) props: {"_concurrent":true,"name":"MainBody","timestamp":true,"elementId":"subapp-mainbody","streaming":true,"async":true,"hydrateServerData":true,"serverSideRendering":true} -->
<div class="blah" style="background: green;"><!-- BEGIN require(subapp-web/lib/load) props: {"_concurrent":true,"name":"MainBody","timestamp":true,"elementId":"subapp-mainbody","useStream":true,"async":true,"hydrateServerData":true,"serverSideRendering":true} -->

token process module subapp-web/lib/load not found
<!-- require(subapp-web/lib/load) END -->
Expand Down
2 changes: 1 addition & 1 deletion packages/subapp-pbundle/lib/framework-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class FrameworkLib {
}

renderTo(element, options) {
assert(!options.streaming, "render to stream is not yet supported for preact");
assert(!options.useStream, "render to stream is not yet supported for preact");

assert(!options.suspenseSsr, "suspense is not yet supported for preact");

Expand Down
6 changes: 3 additions & 3 deletions packages/subapp-react/lib/framework-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class FrameworkLib {
}

renderTo(element, options) {
if (options.streaming) {
assert(!options.suspenseSsr, "streaming and suspense SSR together are not supported");
if (options.useStream) {
assert(!options.suspenseSsr, "useStream and suspense SSR together are not supported");
if (options.hydrateServerData) {
return ReactDOMServer.renderToNodeStream(element);
} else {
Expand Down Expand Up @@ -193,7 +193,7 @@ class FrameworkLib {
`subapp ${this.ref.subApp.name} specified useReactRouter without a StartComponent, \
and can't generate it because module react-router-dom with StaticRouter is not found`
);
return props2 =>
return (props2) =>
React.createElement(
ReactRouterDom.StaticRouter,
props2,
Expand Down
5 changes: 5 additions & 0 deletions packages/subapp-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,10 @@
"functions": 100,
"lines": 100,
"cache": true
},
"prettier": {
"printWidth": 100,
"trailingComma": "none",
"arrowParens": "avoid"
}
}
10 changes: 5 additions & 5 deletions packages/subapp-react/test/spec/ssr-framework.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { asyncVerify } = require("run-verify");
const Redux = require("redux");
const { connect } = require("react-redux");

describe("SSR React framework", function() {
describe("SSR React framework", function () {
it("should setup React framework", () => {
expect(lib.React).to.be.ok;
expect(lib.AppContext).to.be.ok;
Expand Down Expand Up @@ -92,7 +92,7 @@ describe("SSR React framework", function() {
expect(res).contains("Hello foo bar");
});

it("should render Component with streaming if enabled", () => {
it("should render Component with stream if enabled", () => {
const framework = new lib.FrameworkLib({
subApp: {
prepare: () => ({ test: "foo bar" }),
Expand All @@ -101,7 +101,7 @@ describe("SSR React framework", function() {
}
},
subAppServer: {},
options: { serverSideRendering: true, streaming: true },
options: { serverSideRendering: true, useStream: true },
context: {
user: {}
}
Expand All @@ -118,7 +118,7 @@ describe("SSR React framework", function() {
);
});

it("should hydrate render Component with streaming if enabled", () => {
it("should hydrate render Component with stream if enabled", () => {
const framework = new lib.FrameworkLib({
subApp: {
prepare: () => ({ test: "foo bar" }),
Expand All @@ -127,7 +127,7 @@ describe("SSR React framework", function() {
}
},
subAppServer: {},
options: { serverSideRendering: true, streaming: true, hydrateServerData: true },
options: { serverSideRendering: true, useStream: true, hydrateServerData: true },
context: {
user: {}
}
Expand Down
9 changes: 4 additions & 5 deletions packages/subapp-server/lib/setup-hapi-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,13 @@ async function setupRoutesFromFile(srcDir, server, pluginOpts) {
});
}

const useStream = routeOptions.useStream !== false;

const routeHandler = ReactWebapp.makeRouteHandler(routeOptions);
const handler = async (request, h) => {
try {
const context = await routeHandler({
content: { html: "", status: 200, useStream: true },
content: { html: "", status: 200, useStream },
mode: "",
request
});
Expand All @@ -185,10 +187,7 @@ async function setupRoutesFromFile(srcDir, server, pluginOpts) {
const status = data.status;

if (status === undefined) {
return h
.response(data)
.type("text/html; charset=UTF-8")
.code(200);
return h.response(data).type("text/html; charset=UTF-8").code(200);
} else if (HttpStatus.redirect[status]) {
return h.redirect(data.path).code(status);
} else if (HttpStatus.displayHtml[status]) {
Expand Down
2 changes: 1 addition & 1 deletion packages/subapp-server/src/index-page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const RenderSubApps = (props, context) => {
_concurrent: true,
elementId,
timestamp: true,
streaming: false,
useStream: false,
async: true,
serverSideRendering: true
},
Expand Down
17 changes: 16 additions & 1 deletion packages/subapp-web/lib/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* - generate code to bootstrap subapp on client
*/

const assert = require("assert");
const Fs = require("fs");
const Path = require("path");
const _ = require("lodash");
Expand Down Expand Up @@ -53,7 +54,7 @@ module.exports = function setup(setupContext, { props: setupProps }) {
// name="Header"
// async=true
// defer=true
// streaming=true
// useStream=true
// serverSideRendering=true
// hydrateServerData=false
// clientSideRendering=false
Expand Down Expand Up @@ -189,10 +190,24 @@ Response: ${err || body}`
loadSubApp();
prepareSubAppJsBundle();

const verifyUseStream = props => {
if (props.useStream) {
const routeStream = setupContext.routeOptions.useStream;
assert(
routeStream !== false,
`subapp '${props.name}' can't set useStream when route options 'useStream' is false.`
);
}
};

verifyUseStream(setupProps);

const clientProps = JSON.stringify(_.pick(setupProps, ["useReactRouter"]));

return {
process: (context, { props }) => {
verifyUseStream(props);

const { request } = context.user;

if (request.app.webpackDev && subAppLoadTime < request.app.webpackDev.compileTime) {
Expand Down
9 changes: 3 additions & 6 deletions samples/poc-subapp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ You can also control how your subapp works from server side to client side for e
Some of the attributes supported:

- `hydrate` - Enable client side hydration of initial state from server. ie: Use `React.hydrate` API.
- `streaming` - Use the streaming SSR APIs. ie: `ReactDomServer.renderToNodeStream`.
- `suspenseSsr` - Support suspense in SSR. No streaming.
- `useStream` - Use the stream SSR APIs. ie: `ReactDomServer.renderToNodeStream`.
- `suspenseSsr` - Support suspense in SSR. No stream support.

## React Router and SPA

Expand Down Expand Up @@ -195,10 +195,7 @@ const mapStateToProps = state => state;

export default reduxLoadSubApp({
name: "Home",
Component: connect(
mapStateToProps,
dispatch => ({ dispatch })
)(Home),
Component: connect(mapStateToProps, dispatch => ({ dispatch }))(Home),
reduxCreateStore(initialState) {
return createStore(reducers, initialState);
}
Expand Down
4 changes: 2 additions & 2 deletions samples/poc-subapp/TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Streaming SSR [ ]
# Streaming SSR [x]

- Enable support for `renderToNodeStream`
- Enable HTTP streaming
Expand All @@ -11,7 +11,7 @@
- Store bundle load status in `window.webSubApps`
- When rendering subapp without bundle yet, dynamically load them

# Dynamic SSR [ ]
# Dynamic SSR [x]

- Allow each route and subapp to dynamically turn on/off SSR for a request

Expand Down
4 changes: 4 additions & 0 deletions samples/poc-subapp/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"use strict";
module.exports = {
extends: "@xarc/app-dev/config/babel/babelrc.js"
};
Loading

0 comments on commit b73118b

Please sign in to comment.