Skip to content

Commit

Permalink
refactor: simplify server entry (#408)
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa authored Jun 1, 2023
1 parent ea61db1 commit 7a25fe6
Show file tree
Hide file tree
Showing 20 changed files with 324 additions and 332 deletions.
18 changes: 9 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: pnpm
- run: make lint
- run: pnpm i
Expand All @@ -29,10 +29,10 @@ jobs:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: pnpm
- run: pnpm i
- run: make docker/up db/reset/test db/seed-download
Expand All @@ -48,10 +48,10 @@ jobs:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: pnpm
- run: pnpm i
- uses: actions/cache@v3
Expand Down Expand Up @@ -80,10 +80,10 @@ jobs:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: pnpm
- run: pnpm i
- run: make docker/up db/recreate
Expand All @@ -107,7 +107,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- uses: actions/download-artifact@v3
with:
name: coverage-unit
Expand Down
6 changes: 3 additions & 3 deletions app/db/drizzle-client.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { difference, once, tinyassert } from "@hiogawa/utils";
import { difference, tinyassert } from "@hiogawa/utils";
import { sql } from "drizzle-orm";
import * as E from "drizzle-orm/expressions";
import {
Expand Down Expand Up @@ -356,7 +356,7 @@ declare let globalThis: {

export let db = uninitialized as typeof globalThis.__drizzleClient;

export const initializeDrizzleClient = once(async () => {
export async function initializeDrizzleClient() {
db = globalThis.__drizzleClient ??= await inner();

async function inner() {
Expand All @@ -366,7 +366,7 @@ export const initializeDrizzleClient = once(async () => {
logger: process.env["DEBUG"]?.includes("drizzle"), // enable query logging by DEBUG=drizzle
});
}
});
}

export async function finalizeDrizzleClient() {
__dbExtra().connection.destroy();
Expand Down
3 changes: 0 additions & 3 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { RemixServer } from "@remix-run/react";
import type { HandleDocumentRequestFunction } from "@remix-run/server-runtime";
import { renderToString } from "react-dom/server";
import { injectInitializeServer } from "./misc/initialize-server";

injectInitializeServer();

const handler: HandleDocumentRequestFunction = (
request,
Expand Down
9 changes: 9 additions & 0 deletions app/misc/entry-express.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createMiddleware } from "@hattip/adapter-node";
import { createHattipEntry } from "./entry-hattip";

// we can reuse express middleware both for dev and vercel (by patching @remix-run/dev)
// https://github.com/hattipjs/hattip/blob/03a704fa120dfe2eddd6cf22eff00c90bda2acb5/packages/bundler/bundler-vercel/readme.md

export default createMiddleware(createHattipEntry(), {
trustProxy: true,
});
75 changes: 75 additions & 0 deletions app/misc/entry-hattip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { type RequestHandler, compose } from "@hattip/compose";
import { once } from "@hiogawa/utils";
import * as build from "@remix-run/dev/server-build";
import { createRequestHandler } from "@remix-run/server-runtime";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import type { Context } from "hono";
import { logger } from "hono/logger";
import { TRPC_ENDPOINT } from "../trpc/common";
import { createTrpcAppContext } from "../trpc/context";
import { trpcApp } from "../trpc/server";
import { initializeServer } from "./initialize-server";

// based on https://github.com/hi-ogawa/vite-fullstack-example/blob/92649f99b041820ec86650c99cfcd49a72e79f71/src/server/hattip.ts#L16-L28

export function createHattipEntry() {
return compose(
createLogger(),
bootstrapHandler(),
createTrpchandler(),
createRemixHandler()
);
}

function createRemixHandler(): RequestHandler {
const mode =
process.env.NODE_ENV === "production" ? "production" : "development";
const remixHandler = createRequestHandler(build, mode);
return (ctx) => remixHandler(ctx.request);
}

function createTrpchandler(): RequestHandler {
return async (ctx) => {
if (!ctx.url.pathname.startsWith(TRPC_ENDPOINT)) {
return ctx.next();
}
return fetchRequestHandler({
endpoint: TRPC_ENDPOINT,
req: ctx.request,
router: trpcApp,
createContext: createTrpcAppContext,
onError: (e) => {
console.error(e);
},
});
};
}

function bootstrapHandler(): RequestHandler {
const initializeServerOnce = once(initializeServer);
return async (ctx) => {
await initializeServerOnce();
return ctx.next();
};
}

function createLogger(): RequestHandler {
// borrow hono's logger with minimal compatibility hack
// https://github.com/honojs/hono/blob/0ffd795ec6cfb67d38ab902197bb5461a4740b8f/src/middleware/logger/index.ts
const honoLogger = logger();
return async (ctx) => {
let res!: Response;
await honoLogger(
{
req: { method: ctx.method, raw: ctx.request },
get res() {
return res;
},
} as Context,
async () => {
res = await ctx.next();
}
);
return res;
};
}
12 changes: 2 additions & 10 deletions app/misc/initialize-server.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import { once } from "@hiogawa/utils";
import { installGlobals } from "@remix-run/node";
import {
finalizeDrizzleClient,
initializeDrizzleClient,
} from "../db/drizzle-client.server";
import { initializeConfigServer } from "../utils/config";
import { initializeSessionStore } from "../utils/session.server";

export const initializeServer = once(async () => {
installGlobals();
export async function initializeServer() {
initializeConfigServer();
initializeSessionStore();
await initializeDrizzleClient();
});
}

export async function finalizeServer() {
await finalizeDrizzleClient();
}

// to workaround async initialization on the server (cf. @remix-run/server-runtime patch)
export function injectInitializeServer() {
Object.assign(globalThis, { __onRequestHandler: initializeServer });
}
6 changes: 0 additions & 6 deletions app/misc/vercel.ts

This file was deleted.

22 changes: 0 additions & 22 deletions app/routes/trpc/$trpc.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion app/trpc/client-internal.client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createTRPCProxyClient, httpLink } from "@trpc/client";
import superjson from "superjson";
import { TRPC_ENDPOINT } from "./common";
import type { trpcApp } from "./server";

// remove raw client from server bundle since it's not meant to be used on server.
Expand All @@ -9,7 +10,7 @@ export const trpcClient = createTRPCProxyClient<typeof trpcApp>({
transformer: superjson,
links: [
httpLink({
url: "/trpc",
url: TRPC_ENDPOINT,
}),
],
});
1 change: 1 addition & 0 deletions app/trpc/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const TRPC_ENDPOINT = "/trpc";
5 changes: 2 additions & 3 deletions app/utils/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as process from "process";
import { once } from "@hiogawa/utils";
import { z } from "zod";
import { initializePublicConfigServer } from "./config-public";
import { uninitialized } from "./misc";
Expand Down Expand Up @@ -38,7 +37,7 @@ export type PublicConfig = z.infer<typeof Z_PUBLIC_CONFIG>;

export let serverConfig = uninitialized as z.infer<typeof Z_SERVER_CONFIG>;

export const initializeConfigServer = once(() => {
export function initializeConfigServer() {
serverConfig = Z_SERVER_CONFIG.parse(process.env);
initializePublicConfigServer(Z_PUBLIC_CONFIG.parse(process.env));
});
}
5 changes: 2 additions & 3 deletions app/utils/session.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { once } from "@hiogawa/utils";
import {
Session,
SessionStorage,
Expand All @@ -8,7 +7,7 @@ import { serverConfig } from "./config";

export let sessionStore: SessionStorage;

export const initializeSessionStore = once(() => {
export function initializeSessionStore() {
sessionStore = createCookieSessionStorage({
cookie: {
httpOnly: true,
Expand All @@ -18,7 +17,7 @@ export const initializeSessionStore = once(() => {
secrets: [serverConfig.APP_SESSION_SECRET],
},
});
});
}

//
// utils
Expand Down
2 changes: 1 addition & 1 deletion misc/vercel/.vc-config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"runtime": "nodejs16.x",
"runtime": "nodejs18.x",
"handler": "index.js",
"launcherType": "Nodejs",
"regions": ["hnd1"]
Expand Down
20 changes: 8 additions & 12 deletions misc/vercel/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ set -eu -o pipefail
# project.json
# output/
# config.json
# static/ (= (remix-output)/public)
# static/ = (remix-outdir)/public
# functions/
# index.func/
# .vc-config.json
# index-bootstrap.js (require index.js after process.setSourceMapsEnabled)
# index.js
# index.js = (remix-outdir)/server/index.js
#

# cleanup
Expand All @@ -27,11 +26,8 @@ mkdir -p .vercel/output/functions/index.func
# css
pnpm build:css

# remix's default "node-cjs" build with custom server entry
NODE_ENV=production BUILD_VERCEL=1 npx remix build --sourcemap

# bundle server entry
node -r esbuild-register ./misc/vercel/bundle.ts build/remix/production/server/index.js .vercel/output/functions/index.func/index.js
# remix build with custom server entry
NODE_ENV=production BUILD_VERCEL=1 npx remix build

# config.json
cp misc/vercel/config.json .vercel/output/config.json
Expand All @@ -40,8 +36,8 @@ cp misc/vercel/config.json .vercel/output/config.json
cp -r ./build/remix/production/public .vercel/output/static

# serverless
cp build/remix/production/server/index.js .vercel/output/functions/index.func
cp misc/vercel/.vc-config.json .vercel/output/functions/index.func/.vc-config.json
cat > ".vercel/output/functions/index.func/index-bootstrap.js" <<EOF
process.setSourceMapsEnabled(true);
module.exports = require("./index.js");
EOF

# output server size
ls -lh .vercel/output/functions/index.func
45 changes: 0 additions & 45 deletions misc/vercel/bundle.ts

This file was deleted.

Loading

0 comments on commit 7a25fe6

Please sign in to comment.