From d215d606b226f4850adb8335e05623e06dd30e30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20Emir=20=C5=9Een?= Date: Thu, 4 Jan 2024 14:31:11 +0300 Subject: [PATCH] chore(refine-remix): update to `remix@2` and `@refinedev/remix-router@3` (#382) * chore(refine-remix): update to v2 * chore: update custom server configurations * fix: node version for CI --------- Co-authored-by: Batuhan Wilhelm --- .github/workflows/test-local.yaml | 2 +- .../plugins/antd/app/contexts/index.tsx | 25 +-- refine-remix/plugins/antd/package.json | 1 - .../plugins/chakra/app/createEmotionCache.ts | 8 +- .../plugins/chakra/app/entry.client.tsx | 49 ++--- refine-remix/plugins/chakra/app/root.tsx | 12 +- .../plugins/mantine/app/entry.client.tsx | 21 +++ refine-remix/plugins/mantine/app/root.tsx | 12 +- .../mui/app/contexts/ColorModeContext.tsx | 28 +-- refine-remix/plugins/mui/app/entry.client.tsx | 28 +-- refine-remix/plugins/mui/app/root.tsx | 8 +- refine-remix/plugins/mui/package.json | 1 - refine-remix/template/_package.json | 25 +-- refine-remix/template/app/entry.client.tsx | 16 +- refine-remix/template/app/entry.server.tsx | 169 ++++++++++++++---- refine-remix/template/app/root.tsx | 12 +- refine-remix/template/remix.config.js | 14 +- 17 files changed, 265 insertions(+), 166 deletions(-) create mode 100644 refine-remix/plugins/mantine/app/entry.client.tsx diff --git a/.github/workflows/test-local.yaml b/.github/workflows/test-local.yaml index b34425080..286f5db3d 100644 --- a/.github/workflows/test-local.yaml +++ b/.github/workflows/test-local.yaml @@ -176,7 +176,7 @@ jobs: uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: Install run: npm install - name: Build Examples diff --git a/refine-remix/plugins/antd/app/contexts/index.tsx b/refine-remix/plugins/antd/app/contexts/index.tsx index e59fdff99..42a3979d9 100644 --- a/refine-remix/plugins/antd/app/contexts/index.tsx +++ b/refine-remix/plugins/antd/app/contexts/index.tsx @@ -1,37 +1,20 @@ -import React, { - PropsWithChildren, - createContext, - useEffect, - useState, -} from "react"; +import React from "react"; import { RefineThemes } from "@refinedev/antd"; import { ConfigProvider, theme } from "antd"; -import { parseCookies, setCookie } from "nookies"; type ColorModeContextType = { mode: string; setMode: (mode: string) => void; }; -export const ColorModeContext = createContext( +export const ColorModeContext = React.createContext( {} as ColorModeContextType, ); -export const ColorModeContextProvider: React.FC = ({ +export const ColorModeContextProvider: React.FC = ({ children, }) => { - const [isMounted, setIsMounted] = useState(false); - const [mode, setMode] = useState("light"); - - useEffect(() => { - setIsMounted(true); - }, []); - - useEffect(() => { - if (isMounted) { - setMode(parseCookies()["theme"]); - } - }, [isMounted]); + const [mode, setMode] = React.useState("light"); const setColorMode = () => { if (mode === "light") { diff --git a/refine-remix/plugins/antd/package.json b/refine-remix/plugins/antd/package.json index ee1949037..a490611f5 100644 --- a/refine-remix/plugins/antd/package.json +++ b/refine-remix/plugins/antd/package.json @@ -1,7 +1,6 @@ { "dependencies": { "@refinedev/antd": "^5.37.1", - "nookies": "^2.5.2", "antd": "^5.0.5", "@ant-design/icons": "^5.0.1" } diff --git a/refine-remix/plugins/chakra/app/createEmotionCache.ts b/refine-remix/plugins/chakra/app/createEmotionCache.ts index 7390c50cf..2d205675c 100644 --- a/refine-remix/plugins/chakra/app/createEmotionCache.ts +++ b/refine-remix/plugins/chakra/app/createEmotionCache.ts @@ -1,5 +1,7 @@ -import createCache from '@emotion/cache' +import createCache from "@emotion/cache"; export default function createEmotionCache() { - return createCache({ key: 'css' }) -} \ No newline at end of file + return createCache({ key: "cha" }); +} + +export const defaultCache = createEmotionCache(); diff --git a/refine-remix/plugins/chakra/app/entry.client.tsx b/refine-remix/plugins/chakra/app/entry.client.tsx index 1147e3a38..2af90d058 100644 --- a/refine-remix/plugins/chakra/app/entry.client.tsx +++ b/refine-remix/plugins/chakra/app/entry.client.tsx @@ -1,32 +1,35 @@ -import React, { useState } from 'react' -import { hydrateRoot } from 'react-dom/client' -import { CacheProvider } from '@emotion/react' -import { RemixBrowser } from '@remix-run/react' - -import { ClientStyleContext } from './context' -import createEmotionCache from './createEmotionCache' +import { CacheProvider } from "@emotion/react"; +import { RemixBrowser } from "@remix-run/react"; +import React, { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; +import { ClientStyleContext } from "./context"; +import createEmotionCache, { defaultCache } from "./createEmotionCache"; interface ClientCacheProviderProps { - children: React.ReactNode; + children: React.ReactNode; } function ClientCacheProvider({ children }: ClientCacheProviderProps) { - const [cache, setCache] = useState(createEmotionCache()) + const [cache, setCache] = React.useState(defaultCache); - function reset() { - setCache(createEmotionCache()) - } + function reset() { + setCache(createEmotionCache()); + } - return ( - - {children} - - ) + return ( + + {children} + + ); } -hydrateRoot( - document, - - - -) +startTransition(() => { + hydrateRoot( + document, + + + + + , + ); +}); diff --git a/refine-remix/plugins/chakra/app/root.tsx b/refine-remix/plugins/chakra/app/root.tsx index 519fbe094..ccf8ee82d 100644 --- a/refine-remix/plugins/chakra/app/root.tsx +++ b/refine-remix/plugins/chakra/app/root.tsx @@ -29,11 +29,11 @@ import { ServerStyleContext, ClientStyleContext } from './context' <%- (_app.afterImport || []).join("\n") _%> -export const meta: MetaFunction = () => ({ - charset: 'utf-8', - title: 'New Remix App', - viewport: 'width=device-width,initial-scale=1', -}); +export const meta: MetaFunction = () => ([ + { + title: 'New Remix App', + } +]); <% var top = _app.wrapper.map(wrapper => wrapper[0] || ""); @@ -77,6 +77,8 @@ const Document = withEmotionCache( return ( + + {serverStyleData?.map(({ key, ids, css }) => ( diff --git a/refine-remix/plugins/mantine/app/entry.client.tsx b/refine-remix/plugins/mantine/app/entry.client.tsx new file mode 100644 index 000000000..18557f739 --- /dev/null +++ b/refine-remix/plugins/mantine/app/entry.client.tsx @@ -0,0 +1,21 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + +import { ClientProvider } from "@mantine/remix"; +import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; + +startTransition(() => { + hydrateRoot( + document, + + + + + , + ); +}); diff --git a/refine-remix/plugins/mantine/app/root.tsx b/refine-remix/plugins/mantine/app/root.tsx index cba6f7cf0..bd46f1a62 100644 --- a/refine-remix/plugins/mantine/app/root.tsx +++ b/refine-remix/plugins/mantine/app/root.tsx @@ -33,11 +33,11 @@ import routerProvider, { UnsavedChangesNotifier } from "@refinedev/remix-router" var bottom = _app.wrapper.map(wrapper => wrapper[1] || "").reverse(); %> -export const meta: MetaFunction = () => ({ - charset: "utf-8", - title: "New Remix + Refine App", - viewport: "width=device-width,initial-scale=1", -}); +export const meta: MetaFunction = () => ([ + { + title: "New Remix + Refine App", + } +]); createEmotionCache({ key: 'mantine' }); @@ -53,6 +53,8 @@ export default function App() { + + diff --git a/refine-remix/plugins/mui/app/contexts/ColorModeContext.tsx b/refine-remix/plugins/mui/app/contexts/ColorModeContext.tsx index 332c93449..0c9181129 100644 --- a/refine-remix/plugins/mui/app/contexts/ColorModeContext.tsx +++ b/refine-remix/plugins/mui/app/contexts/ColorModeContext.tsx @@ -1,48 +1,28 @@ import useMediaQuery from "@mui/material/useMediaQuery"; import { ThemeProvider } from "@mui/material/styles"; import { RefineThemes } from "@refinedev/mui"; -import { parseCookies, setCookie } from "nookies"; -import React, { - PropsWithChildren, - createContext, - useEffect, - useState, -} from "react"; +import React from "react"; type ColorModeContextType = { mode: string; setMode: () => void; }; -export const ColorModeContext = createContext( +export const ColorModeContext = React.createContext( {} as ColorModeContextType, ); -export const ColorModeContextProvider: React.FC = ({ +export const ColorModeContextProvider: React.FC = ({ children, }) => { - const [isMounted, setIsMounted] = useState(false); - const [mode, setMode] = useState("light"); - - useEffect(() => { - setIsMounted(true); - }, []); + const [mode, setMode] = React.useState("light"); const systemTheme = useMediaQuery(`(prefers-color-scheme: dark)`); - useEffect(() => { - if (isMounted) { - setMode( - parseCookies()["theme"] || (systemTheme ? "dark" : "light"), - ); - } - }, [isMounted, systemTheme]); - const toggleTheme = () => { const nextTheme = mode === "light" ? "dark" : "light"; setMode(nextTheme); - setCookie(null, "theme", nextTheme); }; return ( diff --git a/refine-remix/plugins/mui/app/entry.client.tsx b/refine-remix/plugins/mui/app/entry.client.tsx index 9d931dff0..bbc6cf1d8 100644 --- a/refine-remix/plugins/mui/app/entry.client.tsx +++ b/refine-remix/plugins/mui/app/entry.client.tsx @@ -1,23 +1,25 @@ import CssBaseline from "@mui/material/CssBaseline"; import GlobalStyles from "@mui/material/GlobalStyles"; import { RemixBrowser } from "@remix-run/react"; -import * as React from "react"; -import * as ReactDOM from "react-dom/client"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; import { ClientStyleCacheProvider, ColorModeContextProvider } from "~/contexts"; const hydrate = () => { - React.startTransition(() => { - ReactDOM.hydrateRoot( + startTransition(() => { + hydrateRoot( document, - - - - - - - , + + + + + + + + + , ); }); }; diff --git a/refine-remix/plugins/mui/app/root.tsx b/refine-remix/plugins/mui/app/root.tsx index a4b5c65e4..434cb2a90 100644 --- a/refine-remix/plugins/mui/app/root.tsx +++ b/refine-remix/plugins/mui/app/root.tsx @@ -33,11 +33,11 @@ import routerProvider, { UnsavedChangesNotifier } from "@refinedev/remix-router" var bottom = _app.wrapper.map(wrapper => wrapper[1] || "").reverse(); %> -export const meta: MetaFunction = () => ({ - charset: "utf-8", +export const meta: MetaFunction = () => ([ + { title: "New Remix + Refine App", - viewport: "width=device-width,initial-scale=1", -}); + } +]); interface DocumentProps { diff --git a/refine-remix/plugins/mui/package.json b/refine-remix/plugins/mui/package.json index d3049de9c..11762faef 100644 --- a/refine-remix/plugins/mui/package.json +++ b/refine-remix/plugins/mui/package.json @@ -3,7 +3,6 @@ "@refinedev/mui": "^5.14.1", "@refinedev/react-hook-form": "^4.8.13", "@mui/icons-material": "^5.8.3", - "nookies": "^2.5.2", "@emotion/react": "^11.8.2", "@emotion/styled": "^11.8.1", "@mui/lab": "^5.0.0-alpha.85", diff --git a/refine-remix/template/_package.json b/refine-remix/template/_package.json index ebf819970..be0f7a0d5 100644 --- a/refine-remix/template/_package.json +++ b/refine-remix/template/_package.json @@ -5,26 +5,27 @@ "sideEffects": false, "scripts": { "dev": "refine dev", - "build": "remix build", - "start": "remix-serve build", + "build": "refine build", + "start": "refine start ./build/index.js", "refine": "refine" }, "dependencies": { - "@refinedev/cli": "^2.16.21", - "@refinedev/core": "^4.46.1", - "@refinedev/devtools": "^1.1.29", - "@refinedev/remix-router": "^2.3.1", - "@refinedev/inferencer": "^4.5.16", + "@refinedev/cli": "^2.16.22", + "@refinedev/core": "^4.46.2", + "@refinedev/devtools": "^1.1.30", + "@refinedev/remix-router": "^3.0.0", + "@refinedev/inferencer": "^4.5.17", "@refinedev/kbar": "^1.3.5", - "@remix-run/node": "^1.6.7", - "@remix-run/react": "^1.6.7", - "@remix-run/serve": "^1.6.7", + "@remix-run/node": "^2.4.1", + "@remix-run/react": "^2.4.1", + "@remix-run/serve": "^2.4.1", + "isbot": "^3.6.8", "react": "^18.0.0", "react-dom": "^18.0.0" }, "devDependencies": { - "@remix-run/dev": "^1.6.8", - "@remix-run/eslint-config": "^1.6.8", + "@remix-run/dev": "^2.4.1", + "@remix-run/eslint-config": "^2.4.1", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "eslint": "^8.24.0", diff --git a/refine-remix/template/app/entry.client.tsx b/refine-remix/template/app/entry.client.tsx index ffef95f66..64ea0b340 100644 --- a/refine-remix/template/app/entry.client.tsx +++ b/refine-remix/template/app/entry.client.tsx @@ -1,4 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; import { hydrateRoot } from "react-dom/client"; -hydrateRoot(document, ); +startTransition(() => { + hydrateRoot( + document, + + + , + ); +}); diff --git a/refine-remix/template/app/entry.server.tsx b/refine-remix/template/app/entry.server.tsx index 92ac9fc51..ae78caa4c 100644 --- a/refine-remix/template/app/entry.server.tsx +++ b/refine-remix/template/app/entry.server.tsx @@ -1,48 +1,139 @@ -import { PassThrough } from "stream"; -import type { EntryContext } from "@remix-run/node"; -import { Response } from "@remix-run/node"; +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.server + */ + +import type { AppLoadContext, EntryContext } from "@remix-run/node"; +import { createReadableStreamFromReadable } from "@remix-run/node"; import { RemixServer } from "@remix-run/react"; +import isbot from "isbot"; +import { PassThrough } from "node:stream"; import { renderToPipeableStream } from "react-dom/server"; -const ABORT_DELAY = 5000; +const ABORT_DELAY = 5_000; export default function handleRequest( - request: Request, - responseStatusCode: number, - responseHeaders: Headers, - remixContext: EntryContext + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadContext: AppLoadContext, ) { - return new Promise((resolve, reject) => { - let didError = false; - - let { pipe, abort } = renderToPipeableStream( - , - { - onShellReady: () => { - let body = new PassThrough(); - - responseHeaders.set("Content-Type", "text/html"); - - resolve( - new Response(body, { - headers: responseHeaders, - status: didError ? 500 : responseStatusCode, - }) + return isbot(request.headers.get("user-agent")) + ? handleBotRequest( + request, + responseStatusCode, + responseHeaders, + remixContext, + ) + : handleBrowserRequest( + request, + responseStatusCode, + responseHeaders, + remixContext, ); +} + +function handleBotRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onAllReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error); + } + }, + }, + ); + + setTimeout(abort, ABORT_DELAY); + }); +} + +function handleBrowserRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onShellReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error); + } + }, + }, + ); - pipe(body); - }, - onShellError: (err) => { - reject(err); - }, - onError: (error) => { - didError = true; - - console.error(error); - }, - } - ); - - setTimeout(abort, ABORT_DELAY); - }); + setTimeout(abort, ABORT_DELAY); + }); } diff --git a/refine-remix/template/app/root.tsx b/refine-remix/template/app/root.tsx index 00484d1da..cd62402d0 100644 --- a/refine-remix/template/app/root.tsx +++ b/refine-remix/template/app/root.tsx @@ -39,11 +39,11 @@ import routerProvider, { UnsavedChangesNotifier } from "@refinedev/remix-router" var bottom = _app.wrapper.map(wrapper => wrapper[1] || "").reverse(); %> -export const meta: MetaFunction = () => ({ - charset: "utf-8", - title: "New Remix + Refine App", - viewport: "width=device-width,initial-scale=1", -}); +export const meta: MetaFunction = () => ([ + { + title: "New Remix + Refine App", + } +]); export default function App() { @@ -53,6 +53,8 @@ export default function App() { return ( + + diff --git a/refine-remix/template/remix.config.js b/refine-remix/template/remix.config.js index 21f14efcd..6e1142162 100644 --- a/refine-remix/template/remix.config.js +++ b/refine-remix/template/remix.config.js @@ -1,11 +1,9 @@ /** @type {import('@remix-run/dev').AppConfig} */ module.exports = { - ignoredRouteFiles: ["**/.*"], - future: { - v2_routeConvention: true, - }, - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", + ignoredRouteFiles: ["**/.*"], + serverModuleFormat: "cjs", + // appDirectory: "app", + // assetsBuildDirectory: "public/build", + // serverBuildPath: "build/index.js", + // publicPath: "/build/", };