From ae070a65854c80eea4b32cf7b8ca13a549bad598 Mon Sep 17 00:00:00 2001 From: heiso Date: Fri, 19 Jan 2024 14:35:21 +0100 Subject: [PATCH] feat: move from ssr to spa --- .github/workflows/deploy.yml | 48 +++++++++++ web-app/.github/workflows/deploy.yml | 16 ---- web-app/app/entry.client.tsx | 11 --- web-app/app/entry.server.tsx | 117 --------------------------- web-app/app/root.tsx | 78 +++++------------- web-app/app/routes/_layout.tsx | 11 +-- web-app/app/routes/health.tsx | 13 --- web-app/ecosystem.config.cjs | 6 +- web-app/package.json | 3 +- web-app/server/adapter.ts | 89 -------------------- web-app/server/index.ts | 87 -------------------- web-app/server/process.ts | 25 ------ web-app/tsconfig.build.json | 12 --- web-app/vite.config.ts | 1 + 14 files changed, 75 insertions(+), 442 deletions(-) create mode 100644 .github/workflows/deploy.yml delete mode 100644 web-app/.github/workflows/deploy.yml delete mode 100644 web-app/app/entry.server.tsx delete mode 100644 web-app/app/routes/health.tsx delete mode 100644 web-app/server/adapter.ts delete mode 100644 web-app/server/index.ts delete mode 100644 web-app/server/process.ts delete mode 100644 web-app/tsconfig.build.json diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..35ea661 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,48 @@ +name: Deploy + +on: + push: + branches: [main] + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Pages + id: pages + uses: actions/configure-pages@v3 + - uses: actions/setup-node@v4 + with: + node-version: 20.x + - run: npm ci + working-directory: web-app + - run: npx tsx generate-remix-routes.ts + working-directory: web-app + - run: npx tsx generate-svg-icons-sprite.ts + working-directory: web-app + - run: npm run build + working-directory: web-app + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + path: 'web-app/build/client' + + # Deployment job + deploy: + # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages + permissions: + contents: read + pages: write + id-token: write + environment: + name: github-pages + url: https://heiso.github.io/macrolev + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/web-app/.github/workflows/deploy.yml b/web-app/.github/workflows/deploy.yml deleted file mode 100644 index 263b643..0000000 --- a/web-app/.github/workflows/deploy.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Deploy - -on: - push: - branches: [main] - -jobs: - deploy: - name: Deploy app - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: superfly/flyctl-actions/setup-flyctl@master - - run: flyctl deploy --remote-only --config ./fly.toml - env: - FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} diff --git a/web-app/app/entry.client.tsx b/web-app/app/entry.client.tsx index 5b82e78..1ec0bbe 100644 --- a/web-app/app/entry.client.tsx +++ b/web-app/app/entry.client.tsx @@ -1,7 +1,6 @@ import { RemixBrowser } from '@remix-run/react' import { startTransition, StrictMode } from 'react' import { hydrateRoot } from 'react-dom/client' -import { routerPaths } from '../routes.ts' startTransition(() => { hydrateRoot( @@ -11,13 +10,3 @@ startTransition(() => { , ) }) - -window.addEventListener('focus', async () => { - const response = await fetch(routerPaths['/health']) - if (response.status === 200) { - const json = await response.json() - if (json.build !== window.ENV.BUILD_VERSION && json.shouldRefreshIfVersionMismatch) { - window.location.reload() - } - } -}) diff --git a/web-app/app/entry.server.tsx b/web-app/app/entry.server.tsx deleted file mode 100644 index 688d780..0000000 --- a/web-app/app/entry.server.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { PassThrough } from 'node:stream' - -import type { AppLoadContext, DataFunctionArgs, 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' - -const ABORT_DELAY = 5_000 - -export default function handleRequest( - request: Request, - responseStatusCode: number, - responseHeaders: Headers, - remixContext: EntryContext, - 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( - , - { - 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( - , - { - async 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) - }) -} - -export function handleError(error: unknown, { request }: DataFunctionArgs): void { - console.error(error) -} diff --git a/web-app/app/root.tsx b/web-app/app/root.tsx index 746cf5a..a829476 100644 --- a/web-app/app/root.tsx +++ b/web-app/app/root.tsx @@ -1,57 +1,28 @@ -import { json, type LinksFunction, type MetaFunction } from '@remix-run/node' -import { - Links, - LiveReload, - Meta, - Outlet, - Scripts, - ScrollRestoration, - useLoaderData, -} from '@remix-run/react' +// import { type LinksFunction, type MetaFunction } from '@remix-run/node' +import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react' import type { PropsWithChildren } from 'react' import './font.css' import './tailwind.css' -type ENV = { - ENV: string - BUILD_VERSION: string -} - -declare global { - var ENV: ENV - interface Window { - ENV: ENV - } -} - -export function loader() { - return json({ - ENV: { - ENV: process.env.ENV, - BUILD_VERSION: process.env.BUILD_VERSION, - }, - }) -} - -export const meta: MetaFunction = () => { - return [{ title: 'Macrolev' }] -} - -export const links: LinksFunction = () => { - return [ - { - rel: 'alternate icon', - type: 'image/png', - href: '/favicon-32x32.png', - }, - { rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }, - { - rel: 'manifest', - href: '/site.webmanifest', - crossOrigin: 'use-credentials', - } as const, // necessary to make typescript happy - ] -} +// export const meta: MetaFunction = () => { +// return [{ title: 'Macrolev' }] +// } + +// export const links: LinksFunction = () => { +// return [ +// { +// rel: 'alternate icon', +// type: 'image/png', +// href: '/favicon-32x32.png', +// }, +// { rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }, +// { +// rel: 'manifest', +// href: '/site.webmanifest', +// crossOrigin: 'use-credentials', +// } as const, // necessary to make typescript happy +// ] +// } type DocumentProps = PropsWithChildren function Document({ children }: DocumentProps) { @@ -77,16 +48,9 @@ function Document({ children }: DocumentProps) { } export default function App() { - const { ENV } = useLoaderData() - return ( -