app
- app:1.0 does:
- print the information of request parameters
- demonstrate how CSS modules works when dealing with SSR
- show which manifest and entry are used to perform SSR
- app:2.0 does:
- demonstrate how routes and entries work together
- app:3.0 does:
- show an alternative to historyApiFallback with
react-router
for all kinds of urls
- show an alternative to historyApiFallback with
Basic and single entry app:1.0
1. Build and run it
- npm
- yarn
npm run app:1.0:start
yarn app:1.0:start
2. Check 1.0.development.js
module.exports = {
__VERSION__: "1.0.development",
__ENTRIES__: { "a.node.js": "a.node.<hash>.js" },
__ROUTES__: [
{
pattern: "/a.node",
entry: () => "a.node",
},
],
}
1.0.development.js
lets you locate the server chunks via a stable name. You will need this to generate a static HTML.- If the incoming request url is in
/a.node
, then use the entrya.node.js
to perform SSR.
3. Generate HTML
Assume you want to generate a static page with this url http://127.0.0.1:8080/a.node.
cd examples/app/dist
node -e "require('./' + require('./1.0.development')['__ENTRIES__']['a.node.js']).default({'url': { 'href': '/a.node'}, '__VERSION__': '1.0.development'}).then((result) => console.log(result.body))" > index.html
note
To get this command working, you need to use yarn app:1.0
. yarn app:1.0:start
will write the server chunks to memory file system.
tip
Now you can gernerate all static pages with different input parameters and you do not need to start a web server.
Intermediate and multi entries app:2.0
1. Build and run it
- npm
- yarn
npm run app:2.0:start
yarn app:2.0:start
2. Check 2.0.development.js
module.exports = {
__VERSION__: "2.0.development",
__ENTRIES__: {
"a.node.js": "a.node.<hash>.js",
"b.node.js": "b.node.<hash>.js",
},
__ROUTES__: [
{
pattern: "/:entry",
entry: ({ params }) => params.entry,
},
],
}
2.0.development.js
shows it will handle two routes,/a.node
and/b.node
./a.node
and/b.node
usea.node.js
andb.node.js
respectively to handle the request.If you hit
/c.node
, it will return HTTP 404.note
404 is handled by webpack-dev-server
Advanced and single entry with react-router app:3.0
1. Build and run it
- npm
- yarn
npm run app:3.0:start
yarn app:3.0:start
2. Check 3.0.development.js
module.exports = {
__VERSION__: "3.0.development",
__ENTRIES__: { "index.node.js": "index.node.<hash>.js" },
__ROUTES__: [
{
pattern: "/(.*)",
entry: () => "index.node",
},
],
}
3.0.development.js
shows it will handle all kinds of urls./a.node
,/b.node
and/c.node
use the same entryindex.node.js
to handle the request.If you hit
/c.node
, it will return HTTP 404.note
404 is handled by app logic. See the followings
examples/app/3.0/App.jsxexport function App(props) {
return <StrictMode>
<GlobalStyle />
<Routes>
<Route path="a.node" element={
<DivWrapper flexDirection="column" color="#d63384" align={"center"}>
<Suspense fallback={<div>loading...</div>}>
<Img />
</Suspense>
<Code {...props} to={"b.node"} />
</DivWrapper>
}/>
<Route path="b.node" element={
<DivWrapper flexDirection="row">
<img src={svg} />
<Code {...props} to={"a.node"} />
</DivWrapper>
}/>
<Route path="/*" element={
<NotFound />
}/>
</Routes>
</StrictMode>;
}examples/app/3.0/common.jsxexport function NotFound() {
const statusCode = useContext(StatusCodeContext);
const location = useLocation();
statusCode.current = 404;
return <Pre>
Cannot GET {`${location.pathname}${location.search}`}
</Pre>;
}examples/app/3.0/index.node.jsexport default async (props = {}) => {
const sheet = new ServerStyleSheet();
const statusCode = createRef();
statusCode.current = 200;
const div = renderToString(
sheet.collectStyles(
<StatusCodeContext.Provider value={statusCode}>
<StaticRouter location={props.url.path}>
<App {...props} />
</StaticRouter>
</StatusCodeContext.Provider>
)
);
// there is no point to dynamicially change the head at runtime
// when users share a link, crawler will hit that link again
const body = "<!DOCTYPE html>" + renderToStaticMarkup(<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkqAcAAIUAgUW0RjgAAAAASUVORK5CYII="></link>
<style dangerouslySetInnerHTML={{"__html": __SOURCES__["index.web.css"]}}></style>
<script dangerouslySetInnerHTML={{"__html": `globalThis.props = ${JSON.stringify(props).replace(/</g, "\\u003c")}`}} />
<script dangerouslySetInnerHTML={{"__html": __SOURCES__["index.web.js"]}} />
{sheet.getStyleElement()}
</head>
<body>
<div id="root" dangerouslySetInnerHTML={{"__html": div}} />
<script integrity={__DIGESTS__["vendors.js"]} src={`${__webpack_public_path__}${__FILES__["vendors.js"]}`} crossOrigin="anonymous" />
</body>
</html>);
return {
body,
"statusCode": statusCode.current,
};
};