From 78d55fc896418e4d889db8b2bb7ae95f2abfa81f Mon Sep 17 00:00:00 2001
From: Kalle <38327916+Sendouc@users.noreply.github.com>
Date: Wed, 23 Nov 2022 21:33:46 +0200
Subject: [PATCH] Switch to renderToPipeableStream API
Closes #1152
Did something weird to remove errors on /plans
---
.eslintrc.js | 1 +
app/entry.server.tsx | 123 +++++++++++++++++++++++++++++++++++++------
app/routes/plans.tsx | 11 ++--
package-lock.json | 14 +++++
package.json | 1 +
5 files changed, 130 insertions(+), 20 deletions(-)
diff --git a/.eslintrc.js b/.eslintrc.js
index 3d360f2cf..6f44cdff2 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -30,6 +30,7 @@ module.exports = {
"@typescript-eslint/no-unsafe-argument": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/no-explicit-any": 0,
+ "@typescript-eslint/unbound-method": 0,
"react/prop-types": 0,
"@typescript-eslint/no-restricted-imports": [
"error",
diff --git a/app/entry.server.tsx b/app/entry.server.tsx
index 3e5ce2426..b782b92c4 100644
--- a/app/entry.server.tsx
+++ b/app/entry.server.tsx
@@ -1,32 +1,125 @@
+import { PassThrough } from "stream";
+
import type { EntryContext } from "@remix-run/node";
+import { Response } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
-import { I18nextProvider } from "react-i18next";
-import { renderToString } from "react-dom/server";
+import isbot from "isbot";
+import { renderToPipeableStream } from "react-dom/server";
import cron from "node-cron";
import { updatePatreonData } from "./modules/patreon";
import { i18Instance } from "./modules/i18n";
+import { I18nextProvider } from "react-i18next";
-export default async function handleRequest(
+const ABORT_DELAY = 5000;
+
+const handleRequest = (
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
-) {
- const i18n = await i18Instance(request, remixContext);
+) =>
+ isbot(request.headers.get("user-agent"))
+ ? handleBotRequest(
+ request,
+ responseStatusCode,
+ responseHeaders,
+ remixContext
+ )
+ : handleBrowserRequest(
+ request,
+ responseStatusCode,
+ responseHeaders,
+ remixContext
+ );
+export default handleRequest;
- const markup = renderToString(
-
-
-
- );
+const handleBotRequest = (
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext
+) =>
+ new Promise((resolve, reject) => {
+ let didError = false;
- responseHeaders.set("Content-Type", "text/html");
+ void i18Instance(request, remixContext).then((i18n) => {
+ const { pipe, abort } = renderToPipeableStream(
+
+
+ ,
+ {
+ onAllReady: () => {
+ const body = new PassThrough();
- return new Response("" + markup, {
- status: responseStatusCode,
- headers: responseHeaders,
+ responseHeaders.set("Content-Type", "text/html");
+
+ resolve(
+ new Response(body, {
+ headers: responseHeaders,
+ status: didError ? 500 : responseStatusCode,
+ })
+ );
+
+ pipe(body);
+ },
+ onShellError: (error: unknown) => {
+ reject(error);
+ },
+ onError: (error: unknown) => {
+ didError = true;
+
+ console.error(error);
+ },
+ }
+ );
+
+ setTimeout(abort, ABORT_DELAY);
+ });
+ });
+
+const handleBrowserRequest = (
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext
+) =>
+ new Promise((resolve, reject) => {
+ let didError = false;
+
+ void i18Instance(request, remixContext).then((i18n) => {
+ const { pipe, abort } = renderToPipeableStream(
+
+
+ ,
+ {
+ onShellReady: () => {
+ const body = new PassThrough();
+
+ responseHeaders.set("Content-Type", "text/html");
+
+ resolve(
+ new Response(body, {
+ headers: responseHeaders,
+ status: didError ? 500 : responseStatusCode,
+ })
+ );
+
+ pipe(body);
+ },
+ onShellError: (error: unknown) => {
+ reject(error);
+ },
+ onError: (error: unknown) => {
+ didError = true;
+
+ console.error(error);
+ },
+ }
+ );
+
+ setTimeout(abort, ABORT_DELAY);
+ });
});
-}
// example from https://github.com/BenMcH/remix-rss/blob/main/app/entry.server.tsx
declare global {
diff --git a/app/routes/plans.tsx b/app/routes/plans.tsx
index c2a999228..3ddf539f3 100644
--- a/app/routes/plans.tsx
+++ b/app/routes/plans.tsx
@@ -2,6 +2,7 @@ import { lazy, Suspense } from "react";
import type { LinksFunction } from "@remix-run/node";
import styles from "~/styles/plans.css";
import type { SendouRouteHandle } from "~/utils/remix";
+import { useIsMounted } from "~/hooks/useIsMounted";
export const handle: SendouRouteHandle = {
i18n: ["weapons"],
@@ -14,9 +15,9 @@ export const links: LinksFunction = () => {
const Planner = lazy(() => import("~/components/Planner"));
export default function MapPlannerPage() {
- return (
- }>
-
-
- );
+ const isMounted = useIsMounted();
+
+ if (!isMounted) return
;
+
+ return ;
}
diff --git a/package-lock.json b/package-lock.json
index 4d0db64f4..6c3dd577b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,6 +23,7 @@
"i18next-browser-languagedetector": "^6.1.5",
"i18next-fs-backend": "^1.1.5",
"i18next-http-backend": "^1.4.4",
+ "isbot": "^3.6.5",
"just-capitalize": "^3.1.1",
"just-clone": "^6.1.1",
"just-random-integer": "^4.1.1",
@@ -10050,6 +10051,14 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
+ "node_modules/isbot": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/isbot/-/isbot-3.6.5.tgz",
+ "integrity": "sha512-BchONELXt6yMad++BwGpa0oQxo/uD0keL7N15cYVf0A1oMIoNQ79OqeYdPMFWDrNhCqCbRuw9Y9F3QBjvAxZ5g==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -24062,6 +24071,11 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
+ "isbot": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/isbot/-/isbot-3.6.5.tgz",
+ "integrity": "sha512-BchONELXt6yMad++BwGpa0oQxo/uD0keL7N15cYVf0A1oMIoNQ79OqeYdPMFWDrNhCqCbRuw9Y9F3QBjvAxZ5g=="
+ },
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
diff --git a/package.json b/package.json
index f9dee72ca..575111954 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
"i18next-browser-languagedetector": "^6.1.5",
"i18next-fs-backend": "^1.1.5",
"i18next-http-backend": "^1.4.4",
+ "isbot": "^3.6.5",
"just-capitalize": "^3.1.1",
"just-clone": "^6.1.1",
"just-random-integer": "^4.1.1",