Skip to content

Commit aa5b65c

Browse files
committed
README: Restructure content, update the 'Performance' section. Client: Add CSR benchmarks.
1 parent 7353831 commit aa5b65c

18 files changed

+441
-257
lines changed

README.md

+117-47
Large diffs are not rendered by default.

client/config/spa.config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ Each SPA has:
1212
fallback behavior required by all SPAs and implemented in webpack-dev-server
1313
using the 'historyApiFallback' setting. One and only one SPA must have this
1414
flag set to avoid redirection ambiguity.
15-
- SSR flag. If set to true, the SPA landing page will be prerendered at the
15+
- SSR flag. Controls build-time SSR also called prerendering or static
16+
generation. If set to true, the SPA landing page will be prerendered at the
1617
build time e.g. its HTML will be generated and inserted into the <body> of
1718
the .html file.
1819
Any SPA can have this flag set. When the flag is not set, the <body>

client/package.json

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "crisp-react-client",
3-
"version": "1.2.1",
3+
"version": "1.4.0",
44
"description": "Client for the crisp-react project",
55
"author": "winwiz1 <winwiz@gmail.com> (https://github.com/winwiz1/)",
66
"contributors": [
77
"winwiz1 <winwiz@gmail.com> (https://github.com/winwiz1/)"
88
],
99
"license": "MIT",
10-
"homepage": "https://winwiz1.github.io/crisp-react/",
10+
"homepage": "https://github.com/winwiz1/crisp-react/",
1111
"repository": {
1212
"type": "git",
1313
"url": "https://github.com/winwiz1/crisp-react.git"
@@ -39,7 +39,8 @@
3939
"copy": "copyfiles -f dist/* ../server/build/client/",
4040
"prettier": "prettier --no-config --write ./dist/*.html",
4141
"build:jamstack": "webpack --env prod --env jamstack",
42-
"postbuild:jamstack": "yarn postbuild:prod"
42+
"postbuild:jamstack": "yarn postbuild:prod",
43+
"benchmark:SSR": "cross-env TS_NODE_PROJECT=tsconfig.ssr.json node -r ts-node/register -r tsconfig-paths/register src/utils/postprocess/postProcess.ts"
4344
},
4445
"dependencies": {
4546
"@emotion/react": "^11.4.1",
@@ -98,5 +99,8 @@
9899
"webpack-dev-server": "^4.0.0",
99100
"webpack-node-externals": "^3.0.0",
100101
"webpack-subresource-integrity": "5.0.0"
102+
},
103+
"engines" : {
104+
"node" : ">=12.22.5"
101105
}
102106
}

client/src/components/Lighthouse.tsx

+10-8
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,16 @@ const Description: React.FC = _props => {
7070
<p>
7171
The performance figures could look promising but at the same time prompting a
7272
question what will happen when the functionality is extended and the client
73-
codebase grows. Some considerations on this subject can be found <a
74-
href="https://winwiz1.github.io/crisp-react/docs/benchmarks/PERFORMANCE.html#future-considerations"
75-
target="_blank" rel="noopener noreferrer">here</a>. Additionally, it's important
76-
to <a href="https://winwiz1.github.io/crisp-react/#custom-domain-and-cdn"
77-
target="_blank" rel="noopener noreferrer">ensure</a> CDN caches everything
78-
except for API responses thus allowing your webserver(s) to serve static
79-
assets to various CDN datacenters around the globe (there could be hundreds
80-
of those) rather than to the end users.
73+
codebase grows causing the script bundle size to increase. Crisp React addresses
74+
this issue by allowing a React application to be split into several SPAs each
75+
rendered by its own and smaller bundle. Dynamic imports with lazy loading are
76+
complimentary.<br/>Additionally, it's important
77+
to ensure a CDN caches everything except for API responses thus allowing your
78+
webserver to serve static assets to various CDN datacenters around the
79+
globe (there could be hundreds of those) rather than to the end users. The
80+
CDN related instructions are provided in the <a
81+
href="https://github.com/winwiz1/crisp-react/#readme"
82+
target="_blank" rel="noopener noreferrer">README</a>.
8183
</p>
8284
</Container>
8385
</section>

client/src/utils/postprocess/postProcess.ts

+35-15
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { postProcess as postProcessSSR } from "./postProcessSSR";
77
import { postProcess as postProcessCSS } from "./postProcessCSS";
88

99
const workDir = "./dist/";
10+
const workDirExists = fs.existsSync(workDir);
1011

1112
// stackoverflow.com/a/16060619
1213
function requireUncached(module: string) {
@@ -19,6 +20,14 @@ export async function postProcess(): Promise<void> {
1920

2021
if (ssrSpaNames.length > 0) {
2122
const getEntrypoints = require("../../../config/spa.config").getEntrypoints;
23+
const { performance, PerformanceObserver} = require("perf_hooks");
24+
const observer = new PerformanceObserver((items: any) => {
25+
items.getEntries().forEach((item:any) => {
26+
console.log(`Build-time SSR for SPA '${item.name}' took ${Math.round(item.duration)} msec`);
27+
});
28+
performance.clearMarks();
29+
});
30+
observer.observe({entryTypes: ["measure"]});
2231

2332
const performSsr = async (ssrSpaName: any) => {
2433
type SSRTuple = [string, string];
@@ -66,31 +75,42 @@ Please check the 4-step sequence (provided in the comments at the top of each en
6675
process.exit(1);
6776
}
6877

69-
const writeFile = promisify(fs.writeFile);
70-
71-
try {
72-
await writeFile(path.join(workDir, tp[0]), asString());
73-
await postProcessSSR(workDir, ssrSpaName);
74-
} catch (e) {
75-
console.error(`Failed to create pre-built SSR file, exception: ${e}`);
76-
process.exit(1);
78+
const perfLiterals = ["start", "end"];
79+
performance.mark(perfLiterals[0]);
80+
const ssrContent = asString();
81+
performance.mark(perfLiterals[1]);
82+
performance.measure(ssrSpaName, perfLiterals[0], perfLiterals[1]);
83+
84+
if (workDirExists) {
85+
try {
86+
const writeFile = promisify(fs.writeFile);
87+
await writeFile(path.join(workDir, tp[0]), ssrContent);
88+
await postProcessSSR(workDir, ssrSpaName);
89+
} catch (e) {
90+
console.error(`Failed to create pre-built SSR file, exception: ${e}`);
91+
process.exit(1);
92+
}
7793
}
7894
};
7995

80-
console.log("Starting SSR post-processing");
96+
console.log(workDirExists? "Starting SSR post-processing" : "Starting 'renderAsString' benchmarking");
8197

8298
for (const spa of ssrSpaNames) {
8399
await performSsr(spa);
84100
}
85101

86-
console.log("Finished SSR post-processing")
102+
console.log(workDirExists? "Finished SSR post-processing" : "Finished 'renderAsString' benchmarking");
87103
}
88104

89-
try {
90-
await postProcessCSS();
91-
} catch (e) {
92-
console.error(`Failed to post-process CSS, exception: ${e}`);
93-
process.exit(2);
105+
if (workDirExists) {
106+
try {
107+
await postProcessCSS();
108+
} catch (e) {
109+
console.error(`Failed to post-process CSS, exception: ${e}`);
110+
process.exit(2);
111+
}
112+
} else {
113+
await new Promise(resolve => setTimeout(resolve, 100));
94114
}
95115
}
96116

docs/ProjectHighlights.md

-92
This file was deleted.

docs/Q&A.md

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ Q: I need to add Redux.
137137

138138
A: Have a look at the sibling Crisp BigQuery repository created by cloning and renaming this solution. It uses Redux.
139139

140+
---
140141
Back to the [README](https://github.com/winwiz1/crisp-react#q--a).
141142

142143

docs/Scenarios.md

+1
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,6 @@ Start the debugging configuration `Debug Production Client and Backend (workspa
125125
Wait until an instance of Chrome starts. You should see the overview page. Now you can use VS Code to set breakpoints in both client and backend provided the relevant process is highlighted/selected as explained in the previous scenario. You can also use Chrome DevTools to debug the client application as shown above.<br/>
126126
To finish, stop the running debugging configuration (use the Debugging toolbar or press `Control+F5` once).
127127

128+
---
128129
Back to the [README](https://github.com/winwiz1/crisp-react#scenarios).
129130

0 commit comments

Comments
 (0)