renderToPipeableStream
renderToPipeableStream ஒரு React tree-ஐ pipe செய்யக்கூடிய Node.js Stream ஆக render செய்கிறது.
const { pipe, abort } = renderToPipeableStream(reactNode, options?)- Reference
- Usage
- React tree-ஐ HTML ஆக Node.js Stream-க்கு render செய்தல்
- Content load ஆகும்போது கூடுதல் content-ஐ stream செய்தல்
- Shell-இல் என்ன சேர வேண்டும் என்பதை குறிப்பிடுதல்
- Server-இல் crashes-ஐ log செய்தல்
- Shell-க்குள் errors-இலிருந்து recover செய்தல்
- Shell-க்கு வெளியே errors-இலிருந்து recover செய்தல்
- Status code-ஐ set செய்தல்
- வேறு errors-ஐ வேறு வழிகளில் handle செய்தல்
- Crawlers மற்றும் static generation-க்காக content அனைத்தும் load ஆக காத்திருத்தல்
- Server rendering-ஐ abort செய்தல்
Reference
renderToPipeableStream(reactNode, options?)
உங்கள் React tree-ஐ HTML ஆக Node.js Stream-க்குள் render செய்ய renderToPipeableStream-ஐ call செய்யுங்கள்.
import { renderToPipeableStream } from 'react-dom/server';
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.setHeader('content-type', 'text/html');
pipe(response);
}
});Client-இல், server உருவாக்கிய HTML-ஐ interactive ஆக்க hydrateRoot-ஐ call செய்யுங்கள்.
மேலும் எடுத்துக்காட்டுகளை கீழே பாருங்கள்.
Parameters
-
reactNode: HTML ஆக render செய்ய விரும்பும் React node. உதாரணமாக,<App />போன்ற JSX element. இது முழு document-ஐ represent செய்யும் என்று எதிர்பார்க்கப்படுகிறது, எனவேAppcomponent<html>tag-ஐ render செய்ய வேண்டும். -
optional
options: Streaming options கொண்ட object.- optional
bootstrapScriptContent: குறிப்பிடப்பட்டால், இந்த string inline<script>tag-இல் வைக்கப்படும். - optional
bootstrapScripts: Page-இல் emit செய்ய வேண்டிய<script>tags-க்கான string URLs-ன் array.hydrateRoot-ஐ call செய்யும்<script>-ஐ சேர்க்க இதைப் பயன்படுத்துங்கள். Client-இல் React-ஐ முற்றிலும் run செய்ய வேண்டாம் என்றால் இதை விடுங்கள். - optional
bootstrapModules:bootstrapScriptsபோலவே, ஆனால்<script type="module">-ஐ emit செய்கிறது. - optional
identifierPrefix:useIdஉருவாக்கும் IDs-க்காக React பயன்படுத்தும் string prefix. ஒரே page-இல் பல roots பயன்படுத்தும்போது conflicts தவிர்க்க இது பயனுள்ளது.hydrateRoot-க்கு pass செய்த அதே prefix ஆக இருக்க வேண்டும். - optional
namespaceURI: Stream-க்கான root namespace URI கொண்ட string. Default regular HTML ஆகும். SVG-க்கு'http://www.w3.org/2000/svg'அல்லது MathML-க்கு'http://www.w3.org/1998/Math/MathML'pass செய்யுங்கள். - optional
nonce:script-srcContent-Security-Policy-க்காக scripts-ஐ அனுமதிக்கும்noncestring. - optional
onAllReady: Shell மற்றும் கூடுதல் content அனைத்தும் உட்பட rendering முழுவதும் முடிந்தபோது fire ஆகும் callback. Crawlers மற்றும் static generation-க்காகonShellReady-க்கு பதிலாக இதைப் பயன்படுத்தலாம். இங்கே streaming தொடங்கினால் progressive loading கிடைக்காது. Stream இறுதி HTML-ஐ கொண்டிருக்கும். - optional
onError: Recoverable ஆக இருந்தாலும் இல்லாவிட்டாலும் server error ஏற்படும் ஒவ்வொரு முறையும் fire ஆகும் callback. Default ஆக இதுconsole.error-ஐ மட்டும் call செய்கிறது. Crash reports log செய்ய அதை override செய்தால், இன்னும்console.error-ஐ call செய்கிறீர்கள் என்பதை உறுதி செய்யுங்கள். Shell emit ஆகும் முன் status code-ஐ சரிசெய்ய இதைப் பயன்படுத்தலாம். - optional
onShellReady: Initial shell render ஆன உடனே fire ஆகும் callback. இங்கே status code-ஐ set செய்துpipe-ஐ call செய்து streaming தொடங்கலாம். Shell-க்கு பிறகு React கூடுதல் content-ஐ stream செய்யும்; loading fallbacks-ஐ content-ஆக மாற்றும் inline<script>tags உடனும் அது வரும். - optional
onShellError: Initial shell render செய்யும்போது error இருந்தால் fire ஆகும் callback. இது error-ஐ argument ஆகப் பெறும். Stream-இலிருந்து இன்னும் bytes எதுவும் emit ஆகவில்லை;onShellReadyஅல்லதுonAllReadyஎதுவும் call ஆகாது. எனவே நீங்கள் fallback HTML shell-ஐ output செய்யலாம். - optional
progressiveChunkSize: ஒரு chunk-இல் உள்ள bytes எண்ணிக்கை. Default heuristic பற்றி மேலும் படிக்கவும்.
- optional
Returns
renderToPipeableStream இரண்டு methods கொண்ட object-ஐத் திருப்பித் தருகிறது:
pipeவழங்கப்பட்ட Writable Node.js Stream-க்குள் HTML-ஐ output செய்கிறது. Streaming enable செய்ய விரும்பினால்onShellReady-யில்pipe-ஐ call செய்யுங்கள்; crawlers மற்றும் static generation-க்காகonAllReady-யில் call செய்யுங்கள்.abortserver rendering-ஐ abort செய்து மீதமுள்ளதை client-இல் render செய்ய அனுமதிக்கிறது.
Usage
React tree-ஐ HTML ஆக Node.js Stream-க்கு render செய்தல்
உங்கள் React tree-ஐ HTML ஆக Node.js Stream-க்குள் render செய்ய renderToPipeableStream-ஐ call செய்யுங்கள்:
import { renderToPipeableStream } from 'react-dom/server';
// The route handler syntax depends on your backend framework
app.use('/', (request, response) => {
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.setHeader('content-type', 'text/html');
pipe(response);
}
});
});Root component-உடன், bootstrap <script> paths-ன் list-ஐ வழங்க வேண்டும். உங்கள் root component root <html> tag உட்பட முழு document-ஐ return செய்ய வேண்டும்.
உதாரணமாக, அது இதுபோல் இருக்கலாம்:
export default function App() {
return (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/styles.css"></link>
<title>என் app</title>
</head>
<body>
<Router />
</body>
</html>
);
}Resulting HTML stream-க்குள் React doctype மற்றும் உங்கள் bootstrap <script> tags-ஐ inject செய்யும்:
<!DOCTYPE html>
<html>
<!-- ... உங்கள் components-இலிருந்து வரும் HTML ... -->
</html>
<script src="/main.js" async=""></script>Client-இல், உங்கள் bootstrap script hydrateRoot call மூலம் முழு document-ஐ hydrate செய்ய வேண்டும்:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document, <App />);இது server உருவாக்கிய HTML-க்கு event listeners-ஐ attach செய்து அதை interactive ஆக்கும்.
Deep Dive
இறுதி asset URLs (JavaScript மற்றும் CSS files போன்றவை) build-க்கு பிறகு அடிக்கடி hashed ஆக இருக்கும். உதாரணமாக, styles.css என்பதற்குப் பதிலாக styles.123456.css கிடைக்கலாம். Static asset filenames-ஐ hash செய்வது, அதே asset-ன் ஒவ்வொரு வேறுபட்ட build-க்கும் வேறுபட்ட filename இருப்பதை உறுதி செய்கிறது. இது பயனுள்ளதாகும், ஏனெனில் static assets-க்கு long-term caching-ஐ பாதுகாப்பாக enable செய்ய அனுமதிக்கிறது: ஒரு குறிப்பிட்ட பெயர் கொண்ட file-ன் content ஒருபோதும் மாறாது.
ஆனால் build முடிந்த பிறகே asset URLs தெரிந்தால், அவற்றை source code-இல் வைக்க வழியில்லை. உதாரணமாக, முன்பு போல JSX-இல் "/styles.css"-ஐ hardcode செய்வது வேலை செய்யாது. அவற்றை source code-இலிருந்து வெளியே வைத்திருக்க, prop ஆக pass செய்யப்பட்ட map-இலிருந்து root component உண்மையான filenames-ஐ read செய்யலாம்:
export default function App({ assetMap }) {
return (
<html>
<head>
...
<link rel="stylesheet" href={assetMap['styles.css']}></link>
...
</head>
...
</html>
);
}Server-இல், <App assetMap={assetMap} />-ஐ render செய்து, asset URLs கொண்ட உங்கள் assetMap-ஐ pass செய்யுங்கள்:
// You'd need to get this JSON from your build tooling, e.g. read it from the build output.
const assetMap = {
'styles.css': '/styles.123456.css',
'main.js': '/main.123456.js'
};
app.use('/', (request, response) => {
const { pipe } = renderToPipeableStream(<App assetMap={assetMap} />, {
bootstrapScripts: [assetMap['main.js']],
onShellReady() {
response.setHeader('content-type', 'text/html');
pipe(response);
}
});
});உங்கள் server இப்போது <App assetMap={assetMap} />-ஐ render செய்கிறது என்பதால், hydration errors தவிர்க்க client-இலும் அதே assetMap உடன் render செய்ய வேண்டும். assetMap-ஐ serialize செய்து client-க்கு இதுபோல் pass செய்யலாம்:
// You'd need to get this JSON from your build tooling.
const assetMap = {
'styles.css': '/styles.123456.css',
'main.js': '/main.123456.js'
};
app.use('/', (request, response) => {
const { pipe } = renderToPipeableStream(<App assetMap={assetMap} />, {
// Careful: It's safe to stringify() this because this data isn't user-generated.
bootstrapScriptContent: `window.assetMap = ${JSON.stringify(assetMap)};`,
bootstrapScripts: [assetMap['main.js']],
onShellReady() {
response.setHeader('content-type', 'text/html');
pipe(response);
}
});
});மேலுள்ள எடுத்துக்காட்டில், bootstrapScriptContent option கூடுதல் inline <script> tag ஒன்றைச் சேர்த்து, client-இல் global window.assetMap variable-ஐ set செய்கிறது. இதனால் client code அதே assetMap-ஐ read செய்ய முடியும்:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document, <App assetMap={window.assetMap} />);Client மற்றும் server இரண்டும் ஒரே assetMap prop உடன் App-ஐ render செய்கின்றன, எனவே hydration errors இல்லை.
Content load ஆகும்போது கூடுதல் content-ஐ stream செய்தல்
Server-இல் data அனைத்தும் load ஆகும் முன்பே user content-ஐப் பார்க்கத் தொடங்க streaming அனுமதிக்கிறது. உதாரணமாக, cover, friends மற்றும் photos கொண்ட sidebar, மேலும் posts list காட்டும் profile page ஒன்றைக் கவனியுங்கள்:
function ProfilePage() {
return (
<ProfileLayout>
<ProfileCover />
<Sidebar>
<Friends />
<Photos />
</Sidebar>
<Posts />
</ProfileLayout>
);
}<Posts />-க்கான data load ஆக சில நேரம் எடுக்கிறது என்று கற்பனை செய்யுங்கள். Posts-க்கு காத்திருக்காமல் profile page content-ன் மீதியை user-க்கு காட்ட விரும்புவீர்கள். இதைச் செய்ய, Posts-ஐ <Suspense> boundary-க்குள் wrap செய்யுங்கள்:
function ProfilePage() {
return (
<ProfileLayout>
<ProfileCover />
<Sidebar>
<Friends />
<Photos />
</Sidebar>
<Suspense fallback={<PostsGlimmer />}>
<Posts />
</Suspense>
</ProfileLayout>
);
}Posts அதன் data-வை load செய்யும் முன்பே HTML-ஐ stream செய்ய தொடங்க React-க்கு இது சொல்கிறது. React முதலில் loading fallback (PostsGlimmer)-க்கான HTML-ஐ அனுப்பும்; பின்னர் Posts அதன் data-வை load செய்து முடித்ததும், அந்த loading fallback-ஐ அந்த HTML-ஆல் மாற்றும் inline <script> tag உடன் மீதமுள்ள HTML-ஐ React அனுப்பும். User-ன் பார்வையில், page முதலில் PostsGlimmer உடன் தோன்றி, பின்னர் Posts-ஆல் மாற்றப்படும்.
மேலும் granular loading sequence உருவாக்க <Suspense> boundaries-ஐ nest செய்யலாம்:
function ProfilePage() {
return (
<ProfileLayout>
<ProfileCover />
<Suspense fallback={<BigSpinner />}>
<Sidebar>
<Friends />
<Photos />
</Sidebar>
<Suspense fallback={<PostsGlimmer />}>
<Posts />
</Suspense>
</Suspense>
</ProfileLayout>
);
}இந்த எடுத்துக்காட்டில், React page-ஐ இன்னும் முன்னதாக stream செய்ய தொடங்க முடியும். ProfileLayout மற்றும் ProfileCover மட்டும் முதலில் render முடிக்க வேண்டும், ஏனெனில் அவை எந்த <Suspense> boundary-யிலும் wrap செய்யப்படவில்லை. ஆனால் Sidebar, Friends, அல்லது Photos data load செய்ய வேண்டியிருந்தால், React அதற்கு பதிலாக BigSpinner fallback-க்கான HTML-ஐ அனுப்பும். பின்னர், கூடுதல் data கிடைக்கும்போது, அனைத்தும் visible ஆகும் வரை மேலும் content தொடர்ந்து reveal ஆகும்.
Streaming, browser-இல் React தானாக load ஆக காத்திருக்க வேண்டியதில்லை; உங்கள் app interactive ஆகும் வரை காத்திருக்கவும் வேண்டியதில்லை. Server-இலிருந்து வரும் HTML content எந்த <script> tags load ஆகும் முன்பே progressively reveal ஆகும்.
Streaming HTML எப்படி வேலை செய்கிறது என்பதை மேலும் படிக்கவும்.
Shell-இல் என்ன சேர வேண்டும் என்பதை குறிப்பிடுதல்
எந்த <Suspense> boundaries-க்கும் வெளியே இருக்கும் உங்கள் app-ன் பகுதி shell என அழைக்கப்படுகிறது:
function ProfilePage() {
return (
<ProfileLayout>
<ProfileCover />
<Suspense fallback={<BigSpinner />}>
<Sidebar>
<Friends />
<Photos />
</Sidebar>
<Suspense fallback={<PostsGlimmer />}>
<Posts />
</Suspense>
</Suspense>
</ProfileLayout>
);
}User காணக்கூடிய earliest loading state-ஐ அது தீர்மானிக்கிறது:
<ProfileLayout>
<ProfileCover />
<BigSpinner />
</ProfileLayout>Root-இல் முழு app-ஐ <Suspense> boundary-க்குள் wrap செய்தால், shell அந்த spinner-ஐ மட்டும் கொண்டிருக்கும். ஆனால் அது இனிமையான user experience அல்ல, ஏனெனில் screen-இல் பெரிய spinner ஒன்றைக் காண்பது, இன்னும் சிறிது காத்திருந்து உண்மையான layout-ஐப் பார்ப்பதைவிட மெதுவாகவும் எரிச்சலாகவும் உணரப்படலாம். அதனால்தான் பொதுவாக shell minimal but complete ஆக உணரப்படும் வகையில்—முழு page layout-ன் skeleton போல—<Suspense> boundaries-ஐ அமைக்க விரும்புவீர்கள்.
முழு shell render ஆனபோது onShellReady callback fire ஆகும். வழக்கமாக, அப்போது streaming தொடங்குவீர்கள்:
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.setHeader('content-type', 'text/html');
pipe(response);
}
});onShellReady fire ஆகும் நேரத்தில், nested <Suspense> boundaries-இல் உள்ள components இன்னும் data load செய்து கொண்டிருக்கலாம்.
Server-இல் crashes-ஐ log செய்தல்
Default ஆக, server-இல் உள்ள அனைத்து errors console-க்கு log செய்யப்படும். Crash reports log செய்ய இந்த behavior-ஐ override செய்யலாம்:
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.setHeader('content-type', 'text/html');
pipe(response);
},
onError(error) {
console.error(error);
logServerCrashReport(error);
}
});Custom onError implementation வழங்கினால், மேலே போல errors-ஐ console-க்கும் log செய்ய மறக்காதீர்கள்.
Shell-க்குள் errors-இலிருந்து recover செய்தல்
இந்த எடுத்துக்காட்டில், shell ProfileLayout, ProfileCover, மற்றும் PostsGlimmer-ஐ கொண்டுள்ளது:
function ProfilePage() {
return (
<ProfileLayout>
<ProfileCover />
<Suspense fallback={<PostsGlimmer />}>
<Posts />
</Suspense>
</ProfileLayout>
);
}அந்த components render ஆகும்போது error ஏற்பட்டால், client-க்கு அனுப்ப React-க்கு meaningful HTML எதுவும் இருக்காது. கடைசி முயற்சியாக server rendering-ஐ சாராத fallback HTML அனுப்ப onShellError-ஐ override செய்யுங்கள்:
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.setHeader('content-type', 'text/html');
pipe(response);
},
onShellError(error) {
response.statusCode = 500;
response.setHeader('content-type', 'text/html');
response.send('<h1>ஏதோ தவறு ஏற்பட்டது</h1>');
},
onError(error) {
console.error(error);
logServerCrashReport(error);
}
});Shell உருவாக்கும்போது error இருந்தால், onError மற்றும் onShellError இரண்டும் fire ஆகும். Error reporting-க்கு onError-ஐப் பயன்படுத்துங்கள்; fallback HTML document அனுப்ப onShellError-ஐப் பயன்படுத்துங்கள். உங்கள் fallback HTML அவசியமாக error page ஆக இருக்க வேண்டியதில்லை. அதற்கு பதிலாக, client-இல் மட்டும் உங்கள் app-ஐ render செய்யும் alternative shell-ஐ சேர்க்கலாம்.
Shell-க்கு வெளியே errors-இலிருந்து recover செய்தல்
இந்த எடுத்துக்காட்டில், <Posts /> component <Suspense>-க்குள் wrap செய்யப்பட்டுள்ளது, எனவே அது shell-ன் பகுதி அல்ல:
function ProfilePage() {
return (
<ProfileLayout>
<ProfileCover />
<Suspense fallback={<PostsGlimmer />}>
<Posts />
</Suspense>
</ProfileLayout>
);
}Posts component-இல் அல்லது அதற்குள் எங்காவது error ஏற்பட்டால், React அதிலிருந்து recover செய்ய முயலும்:
- அது அருகிலுள்ள
<Suspense>boundary (PostsGlimmer)-க்கான loading fallback-ஐ HTML-க்குள் emit செய்யும். - Server-இல்
Postscontent-ஐ render செய்ய முயல்வதை அது “give up” செய்யும். - Client-இல் JavaScript code load ஆனபோது, React client-இல்
Posts-ஐ render செய்ய retry செய்யும்.
Client-இல் Posts-ஐ render செய்வதை retry செய்ததும் மீண்டும் தோல்வியடைந்தால், React client-இல் error-ஐ throw செய்யும். Rendering போது throw செய்யப்படும் அனைத்து errors போலவே, அருகிலுள்ள parent error boundary user-க்கு error எப்படிக் காட்டப்பட வேண்டும் என்பதை தீர்மானிக்கும். நடைமுறையில், error recover செய்ய முடியாதது உறுதியாகும் வரை user loading indicator-ஐப் பார்ப்பார் என்பதே இதன் பொருள்.
Client-இல் Posts render செய்வதை retry செய்தது வெற்றியடைந்தால், server-இலிருந்து வந்த loading fallback client rendering output-ஆல் மாற்றப்படும். Server error இருந்தது user-க்கு தெரியாது. ஆனால் server onError callback மற்றும் client onRecoverableError callbacks fire ஆகும்; இதனால் error பற்றி நீங்கள் notified ஆக முடியும்.
Status code-ஐ set செய்தல்
Streaming ஒரு tradeoff-ஐ அறிமுகப்படுத்துகிறது. User content-ஐ விரைவாகப் பார்க்க, page-ஐ மிக விரைவாக stream செய்ய விரும்புகிறீர்கள். ஆனால் streaming தொடங்கிய பிறகு, response status code-ஐ இனி set செய்ய முடியாது.
உங்கள் app-ஐ shell (அனைத்து <Suspense> boundaries-க்கும் மேலே) மற்றும் மீதமுள்ள content ஆக பிரிப்பதன் மூலம், இந்த பிரச்சினையின் ஒரு பகுதியை நீங்கள் ஏற்கனவே தீர்த்துவிட்டீர்கள். Shell error செய்தால், error status code-ஐ set செய்ய அனுமதிக்கும் onShellError callback கிடைக்கும். இல்லையெனில், app client-இல் recover ஆகக்கூடும் என்பதை நீங்கள் அறிந்திருப்பதால், “OK” அனுப்பலாம்.
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.statusCode = 200;
response.setHeader('content-type', 'text/html');
pipe(response);
},
onShellError(error) {
response.statusCode = 500;
response.setHeader('content-type', 'text/html');
response.send('<h1>ஏதோ தவறு ஏற்பட்டது</h1>');
},
onError(error) {
console.error(error);
logServerCrashReport(error);
}
});Shell-க்கு வெளியே உள்ள component (அதாவது <Suspense> boundary-க்குள்) error throw செய்தால், React rendering-ஐ நிறுத்தாது. இதன் பொருள் onError callback fire ஆகும், ஆனால் onShellError-க்கு பதிலாக இன்னும் onShellReady கிடைக்கும். ஏனெனில் React அந்த error-இலிருந்து client-இல் recover செய்ய முயலும், மேலே விவரித்தபடி.
ஆனால், விரும்பினால், ஏதோ ஒன்று errored ஆனது என்ற தகவலைப் பயன்படுத்தி status code-ஐ set செய்யலாம்:
let didError = false;
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.statusCode = didError ? 500 : 200;
response.setHeader('content-type', 'text/html');
pipe(response);
},
onShellError(error) {
response.statusCode = 500;
response.setHeader('content-type', 'text/html');
response.send('<h1>ஏதோ தவறு ஏற்பட்டது</h1>');
},
onError(error) {
didError = true;
console.error(error);
logServerCrashReport(error);
}
});Initial shell content உருவாக்கும்போது ஏற்பட்ட shell-க்கு வெளியேயுள்ள errors-ஐ மட்டுமே இது catch செய்யும், எனவே இது exhaustive அல்ல. ஏதாவது content-க்கு error ஏற்பட்டதா என்பதைத் தெரிந்துகொள்வது critical என்றால், அதை shell-க்குள் மேலே நகர்த்தலாம்.
வேறு errors-ஐ வேறு வழிகளில் handle செய்தல்
நீங்கள் உங்கள் சொந்த Error subclasses-ஐ உருவாக்கலாம் மற்றும் எந்த error throw செய்யப்பட்டது என்பதைச் சரிபார்க்க instanceof operator-ஐப் பயன்படுத்தலாம். உதாரணமாக, custom NotFoundError ஒன்றை define செய்து உங்கள் component-இலிருந்து அதை throw செய்யலாம். அதன் பிறகு உங்கள் onError, onShellReady, மற்றும் onShellError callbacks error type-ஐப் பொறுத்து வேறு செயல்களைச் செய்யலாம்:
let didError = false;
let caughtError = null;
function getStatusCode() {
if (didError) {
if (caughtError instanceof NotFoundError) {
return 404;
} else {
return 500;
}
} else {
return 200;
}
}
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
response.statusCode = getStatusCode();
response.setHeader('content-type', 'text/html');
pipe(response);
},
onShellError(error) {
response.statusCode = getStatusCode();
response.setHeader('content-type', 'text/html');
response.send('<h1>ஏதோ தவறு ஏற்பட்டது</h1>');
},
onError(error) {
didError = true;
caughtError = error;
console.error(error);
logServerCrashReport(error);
}
});Shell-ஐ emit செய்து streaming தொடங்கியதும், status code-ஐ மாற்ற முடியாது என்பதை நினைவில் கொள்ளுங்கள்.
Crawlers மற்றும் static generation-க்காக content அனைத்தும் load ஆக காத்திருத்தல்
Content கிடைக்கும் போதே user அதை காண முடிவதால் streaming சிறந்த user experience-ஐ வழங்குகிறது.
ஆனால் crawler உங்கள் page-ஐ visit செய்யும்போது, அல்லது build time-இல் pages உருவாக்கும் போது, content-ஐ progressively reveal செய்வதற்கு பதிலாக, content அனைத்தும் முதலில் load ஆக அனுமதித்து பின்னர் இறுதி HTML output-ஐ உருவாக்க விரும்பலாம்.
onAllReady callback-ஐப் பயன்படுத்தி content அனைத்தும் load ஆக காத்திருக்கலாம்:
let didError = false;
let isCrawler = // ... உங்கள் bot detection strategy-ஐப் பொறுத்தது ...
const { pipe } = renderToPipeableStream(<App />, {
bootstrapScripts: ['/main.js'],
onShellReady() {
if (!isCrawler) {
response.statusCode = didError ? 500 : 200;
response.setHeader('content-type', 'text/html');
pipe(response);
}
},
onShellError(error) {
response.statusCode = 500;
response.setHeader('content-type', 'text/html');
response.send('<h1>ஏதோ தவறு ஏற்பட்டது</h1>');
},
onAllReady() {
if (isCrawler) {
response.statusCode = didError ? 500 : 200;
response.setHeader('content-type', 'text/html');
pipe(response);
}
},
onError(error) {
didError = true;
console.error(error);
logServerCrashReport(error);
}
});Regular visitor progressively loaded content-ன் stream-ஐ பெறுவார். Crawler, data அனைத்தும் load ஆன பிறகு இறுதி HTML output-ஐப் பெறும். ஆனால் இதனால் crawler அனைத்து data-க்கும் காத்திருக்க வேண்டும்; அவற்றில் சில load ஆக மெதுவாகவோ error ஆகவோ இருக்கலாம். உங்கள் app-ஐப் பொறுத்து, crawlers-க்கும் shell-ஐ அனுப்ப தேர்வு செய்யலாம்.
Server rendering-ஐ abort செய்தல்
Timeout-க்கு பிறகு server rendering-ஐ “give up” செய்ய கட்டாயப்படுத்தலாம்:
const { pipe, abort } = renderToPipeableStream(<App />, {
// ...
});
setTimeout(() => {
abort();
}, 10000);React மீதமுள்ள loading fallbacks-ஐ HTML ஆக flush செய்து, மீதியை client-இல் render செய்ய முயலும்.