Skip to content

Commit

Permalink
create react-18 streaming example
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed Mar 29, 2024
1 parent c76f742 commit 4ef6f43
Show file tree
Hide file tree
Showing 28 changed files with 1,861 additions and 128 deletions.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
registry=https://registry.npmjs.org
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16
18
10 changes: 5 additions & 5 deletions .size-limit.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = [
{
path: ['moveStyles.js'],
ignore: ['tslib'],
limit: '0.5 KB',
},
// {
// path: ['src/moveStyles.ts'],
// ignore: ['tslib'],
// limit: '0.5 KB',
// },
];
10 changes: 3 additions & 7 deletions .size.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[
{
"name": "moveStyles.js",
"passed": true,
"size": 162
}
]
{
"error": "WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.\n - configuration.entry['index'] should be an non-empty array.\n -> A non-empty array of non-empty strings\n at webpack (/Users/akorzunov/dev/github/loaders/used-styles/node_modules/webpack/lib/webpack.js:31:9)\n at /Users/akorzunov/dev/github/loaders/used-styles/node_modules/@size-limit/webpack/run-webpack.js:5:20\n at new Promise (<anonymous>)\n at runWebpack (/Users/akorzunov/dev/github/loaders/used-styles/node_modules/@size-limit/webpack/run-webpack.js:4:10)\n at Object.step40 (/Users/akorzunov/dev/github/loaders/used-styles/node_modules/@size-limit/webpack/index.js:59:38)\n at /Users/akorzunov/dev/github/loaders/used-styles/node_modules/size-limit/calc.js:8:62\n at Array.map (<anonymous>)\n at exec (/Users/akorzunov/dev/github/loaders/used-styles/node_modules/size-limit/calc.js:8:41)\n at calc (/Users/akorzunov/dev/github/loaders/used-styles/node_modules/size-limit/calc.js:14:42)\n at processTicksAndRejections (node:internal/process/task_queues:96:5)"
}
5 changes: 0 additions & 5 deletions doczrc.js

This file was deleted.

22 changes: 0 additions & 22 deletions example/app.tsx

This file was deleted.

Empty file removed example/assets/.gitkeep
Empty file.
11 changes: 0 additions & 11 deletions example/index.html

This file was deleted.

5 changes: 0 additions & 5 deletions example/index.tsx

This file was deleted.

7 changes: 7 additions & 0 deletions example/react-18-streaming/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!doctype html>
<html lang="en">
<body>
<div id="app" style="display: contents"></div>
<script type="module" src="/src/client.tsx" defer></script>
</body>
</html>
22 changes: 22 additions & 0 deletions example/react-18-streaming/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "used-styles-react-18",
"private": true,
"scripts": {
"start:server": "ts-node ./src/server.tsx",
"start:client": "vite . --port 3001"
},
"dependencies": {
"express": "^4.19.2",
"multistream": "^4.1.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/multistream": "^4.1.3",
"@types/react": "^18.2.73",
"@types/react-dom": "^18.2.23",
"ts-node": "^10.9.2",
"vite": "^5.2.6"
}
}
7 changes: 7 additions & 0 deletions example/react-18-streaming/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

export const App = () => (
<div className="app">
your app <div className="test">and your styles</div>
</div>
);
16 changes: 16 additions & 0 deletions example/react-18-streaming/src/client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom/client';

import { moveStyles } from '../../../moveStyles';

import { App } from './App';

// Call before `ReactDOM.hydrateRoot`
moveStyles();

ReactDOM.hydrateRoot(
document.getElementById('root'),
<React.StrictMode>
<App />
</React.StrictMode>
);
66 changes: 66 additions & 0 deletions example/react-18-streaming/src/entry-server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// entry-server.js
import { Readable } from 'node:stream';
import { Transform } from 'stream';

import { Response } from 'express';
import MultiStream from 'multistream';
import React from 'react';
import { renderToPipeableStream } from 'react-dom/server';

import { App } from './App';

// small utility for "readable" streams
const readableString = (string: string) => {
const s = new Readable();
s.push(string);
s.push(null);
s._read = () => true;

return s;
};

const ABORT_DELAY = 10000;

export const renderApp = async (res: Response, styledStream: Transform) => {
let didError = false;

const { pipe, abort } = renderToPipeableStream(
<React.StrictMode>
<App />
</React.StrictMode>,
{
onShellError() {
res.sendStatus(500);
},
// wait for all pieces to be ready
onAllReady() {
res.status(didError ? 500 : 200);
res.set({ 'Content-Type': 'text/html' });

// allow client to start loading js bundle
res.write(`<!DOCTYPE html><html><head><script defer src="client.js"></script></head><body><div id="root">`);

const endStream = readableString('</div></body></html>');

// concatenate all streams together
const streams = [
styledStream, // the main content
endStream, // closing tags
];

new MultiStream(streams).pipe(res);

// start by piping react and styled transform stream
pipe(styledStream);
},
onError(error) {
didError = true;
console.error(error);
},
}
);

setTimeout(() => {
abort();
}, ABORT_DELAY);
};
39 changes: 39 additions & 0 deletions example/react-18-streaming/src/server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import express from 'express';

import {
discoverProjectStyles,
createCriticalStyleStream,
// createStyleStream,
// createLink,
} from '../../../';

import { renderApp } from './entry-server';

const app = express();

// generate lookup table on server start
const stylesLookup = discoverProjectStyles(__dirname);

app.use('*', async (_req, res) => {
await stylesLookup;

try {
// create a style steam
// const styledStream = createStyleStream(stylesLookup, (style) => {
// // _return_ link tag, and it will be appended to the stream output
// return createLink(`${style}`) // <link href="dist/mystyle.css />
// });

// or create critical CSS stream - it will inline all styles
// console.log(stylesLookup)

const styledStream = createCriticalStyleStream(stylesLookup); // <style>.myClass {...

await renderApp(res, styledStream);
} catch (err) {
res.sendStatus(500);
}
});

console.log('listening on port 3000');
app.listen(3000);
7 changes: 7 additions & 0 deletions example/react-18-streaming/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.app {
color: red;
}

.test {
color: blue;
}

0 comments on commit 4ef6f43

Please sign in to comment.