Skip to content

Commit

Permalink
Merge pull request #5 from PaystackHQ/build/migrate-to-vite
Browse files Browse the repository at this point in the history
Switch to vite
  • Loading branch information
alex-paystack authored Jul 26, 2024
2 parents f9b5810 + 9459b78 commit fefdbc3
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 50 deletions.
152 changes: 152 additions & 0 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/**
* 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 } from './mocks/node';

const ABORT_DELAY = 5_000;

if (
process.env.NODE_ENV === 'development' &&
process.env.ENABLE_MOCKS === 'true'
) {
server.listen({ onUnhandledRequest: 'bypass' });
console.info('🔶 Mock server running');

process.once('SIGINT', () => server.close());
process.once('SIGTERM', () => server.close());
}

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);
});
}
15 changes: 15 additions & 0 deletions app/mocks/node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw'

// put one-off handlers that don't really need an entire file to themselves here
const miscHandlers = [
http.get('https://example.com/user', () => {
return HttpResponse.json({
id: 'c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3d',
firstName: 'John',
lastName: 'Maverick',
});
}),
];

export const server = setupServer(...miscHandlers);
2 changes: 0 additions & 2 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { LinksFunction, LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
Expand Down Expand Up @@ -35,7 +34,6 @@ const Document = ({ children }: { children: ReactNode }) => {
{children}
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
Expand Down
7 changes: 0 additions & 7 deletions mocks/README.md

This file was deleted.

21 changes: 0 additions & 21 deletions mocks/index.js

This file was deleted.

12 changes: 5 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
"name": "paystack-remix-template",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"build": "remix build",
"dev": "remix dev --manual -c \"npm run dev:serve\"",
"dev:serve": "binode --require ./mocks -- @remix-run/serve:remix-serve ./build/index.js",
"dev": "remix vite:dev",
"build": "remix vite:build",
"start": "remix-serve ./build/server/index.js",
"dev:mocks": "cross-env ENABLE_MOCKS=true remix vite:dev",
"format": "prettier --write .",
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
"start": "remix-serve ./build/index.js",
"start:mocks": "binode --require ./mocks -- @remix-run/serve:remix-serve ./build/index.js",
"test": "vitest",
"test:e2e:dev": "start-server-and-test dev http://localhost:3000 \"npx cypress open\"",
"pretest:e2e:run": "npm run build",
Expand Down Expand Up @@ -43,7 +43,6 @@
"@vitejs/plugin-react": "^4.0.1",
"@vitest/coverage-v8": "^0.32.2",
"autoprefixer": "^10.4.19",
"binode": "^1.0.5",
"cookie": "^0.5.0",
"cross-env": "^7.0.3",
"cypress": "^13.13.1",
Expand All @@ -60,7 +59,6 @@
"start-server-and-test": "^2.0.0",
"tailwindcss": "^3.4.6",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3",
"vite": "^5.3.5",
"vite-tsconfig-paths": "^3.6.0",
Expand Down
2 changes: 1 addition & 1 deletion postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
plugins: {
autoprefixer: {},
tailwindcss: {}
Expand Down
6 changes: 0 additions & 6 deletions remix.config.js

This file was deleted.

2 changes: 0 additions & 2 deletions remix.env.d.ts

This file was deleted.

8 changes: 4 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"exclude": ["./cypress", "./cypress.config.ts"],
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
"include": ["**/*.ts", "**/*.tsx"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2020"],
"types": ["vitest/globals"],
"types": ["vitest/globals", "@remix-run/node", "vite/client"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"module": "CommonJS",
"moduleResolution": "node",
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"target": "ES2020",
"strict": true,
Expand Down
16 changes: 16 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { vitePlugin as remix } from '@remix-run/dev';
import { installGlobals } from '@remix-run/node';
import { defineConfig } from 'vite';

installGlobals();

export default defineConfig({
plugins: [
remix({
ignoredRouteFiles: ['**/.*', '**/*.test.{ts,tsx}'],
}),
],
server: {
port: 4000,
},
});

0 comments on commit fefdbc3

Please sign in to comment.