forked from remix-run/examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: updated to latest version of remix & added client-side mocking
- Loading branch information
Showing
12 changed files
with
541 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* 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' | ||
|
||
// if in dev mode, import the worker for msw integration and start the worker | ||
async function prepareApp() { | ||
if (process.env.NODE_ENV === 'development') { | ||
const { worker } = await import('./mocks/browser') | ||
return worker.start() | ||
} | ||
|
||
return Promise.resolve() | ||
} | ||
|
||
prepareApp().then(() => { | ||
startTransition(() => { | ||
hydrateRoot( | ||
document, | ||
<StrictMode> | ||
<RemixBrowser /> | ||
</StrictMode>, | ||
) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/** | ||
* 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 { PassThrough } from 'node:stream' | ||
|
||
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 { renderToPipeableStream } from 'react-dom/server' | ||
|
||
// import server for msw integration | ||
import { server } from './mocks/node' | ||
|
||
const ABORT_DELAY = 5_000 | ||
|
||
// if in dev mode, start the node server | ||
if (process.env.NODE_ENV === 'development') { | ||
server.listen() | ||
} | ||
|
||
export default function handleRequest( | ||
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 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( | ||
<RemixServer | ||
context={remixContext} | ||
url={request.url} | ||
abortDelay={ABORT_DELAY} | ||
/>, | ||
{ | ||
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( | ||
<RemixServer | ||
context={remixContext} | ||
url={request.url} | ||
abortDelay={ABORT_DELAY} | ||
/>, | ||
{ | ||
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) | ||
} | ||
}, | ||
}, | ||
) | ||
|
||
setTimeout(abort, ABORT_DELAY) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { setupWorker } from 'msw/browser' | ||
import { handlers } from './handlers' | ||
|
||
export const worker = setupWorker(...handlers) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { http, HttpResponse } from 'msw' | ||
|
||
export const handlers = [ | ||
// Intercept "GET ${process.env.API_BASE}/user" requests... | ||
http.get(`${process.env.API_BASE}/user`, () => { | ||
// ...and respond to them using this JSON response. | ||
return HttpResponse.json({ | ||
id: 'c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3d', | ||
firstName: 'John', | ||
lastName: 'Maverick', | ||
}) | ||
}), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { setupServer } from 'msw/node' | ||
import { handlers } from './handlers' | ||
|
||
export const server = setupServer(...handlers) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,18 @@ | ||
import { json } from "@remix-run/node"; | ||
import { useLoaderData } from "@remix-run/react"; | ||
import { json } from '@remix-run/node' | ||
import { useLoaderData } from '@remix-run/react' | ||
|
||
export const loader = async () => { | ||
const data = await fetch("https://my-mock-api.com").then((response) => | ||
response.json(), | ||
); | ||
|
||
if (!data || typeof data.message !== "string") { | ||
throw json({ message: "Server error" }, { status: 500 }); | ||
} | ||
|
||
return json(data); | ||
}; | ||
export async function loader() { | ||
const res = await fetch(`${process.env.API_BASE}/user`) | ||
const data = await res.json() | ||
return json(data) | ||
} | ||
|
||
export default function Index() { | ||
const data = useLoaderData<typeof loader>(); | ||
|
||
const data = useLoaderData<typeof loader>() | ||
return ( | ||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}> | ||
<h1>{data.message}</h1> | ||
<h1>Welcome to Remix</h1> | ||
<pre>{JSON.stringify(data)}</pre> | ||
</div> | ||
); | ||
) | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.