Skip to content

Commit 192b80f

Browse files
committed
feat: update plugin to handle vercel specific code
1 parent a4c2622 commit 192b80f

File tree

2 files changed

+80
-17
lines changed

2 files changed

+80
-17
lines changed

src/server/index.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { api } from "@/server/api";
22
import { Hono } from "hono";
3-
import { handle } from "hono/vercel";
43
import { renderToString } from "react-dom/server";
54

5+
// This must be exported for the dev server to work
66
export const app = new Hono();
77

88
app.route("/api", api);
9+
10+
// Serves the main web application. This must come after the API route.
911
app.get("*", (c) => {
12+
// Along with the vite React plugin this enables HMR within react while
13+
// running the dev server.
1014
const { url } = c.req;
1115
const { origin } = new URL(url);
12-
1316
const injectClientScript = `
1417
import RefreshRuntime from "${origin}/@react-refresh";
1518
RefreshRuntime.injectIntoGlobalHook(window);
@@ -21,6 +24,8 @@ app.get("*", (c) => {
2124
<script type="module">{injectClientScript}</script>
2225
) : null;
2326

27+
// Sets the correct path for static assets based on the environment.
28+
// The production paths are hard coded based on the output of the build script.
2429
const cssPath = import.meta.env.PROD
2530
? "/assets/index.css"
2631
: "src/client/index.css";
@@ -57,11 +62,3 @@ app.get("*", (c) => {
5762
].join("\n"),
5863
);
5964
});
60-
61-
const handler = handle(app);
62-
63-
export const GET = handler;
64-
export const POST = handler;
65-
export const PATCH = handler;
66-
export const PUT = handler;
67-
export const OPTIONS = handler;

vite.config.ts

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { defineConfig, mergeConfig } from "vite";
2-
3-
import react from "@vitejs/plugin-react";
4-
import basicSsl from "@vitejs/plugin-basic-ssl";
5-
import path from "node:path";
61
import fs from "node:fs/promises";
2+
import path from "node:path";
73
import devServer from "@hono/vite-dev-server";
4+
import basicSsl from "@vitejs/plugin-basic-ssl";
5+
import react from "@vitejs/plugin-react";
6+
import { defineConfig, mergeConfig, type Plugin } from "vite";
87

98
const OUT_DIR = ".vercel";
109

@@ -37,6 +36,71 @@ const vercelConfigPlugin = () => ({
3736
},
3837
});
3938

39+
/**
40+
* Generate the vercel specific code within the server entry file.
41+
*
42+
* ```ts
43+
* import { handle } from "hono/vercel";
44+
*
45+
* ...
46+
*
47+
* const handler = handle(app);
48+
* export const GET = handler;
49+
* export const POST = handler;
50+
* export const PATCH = handler;
51+
* export const PUT = handler;
52+
* export const OPTIONS = handler;
53+
* ```
54+
*
55+
*/
56+
const vercelEntryPlugin = (): Plugin => {
57+
let entry: string;
58+
let resolvedEntryPath: string;
59+
let projectRoot: string;
60+
61+
return {
62+
name: "vercel-entry",
63+
configResolved(config) {
64+
if (config.build.lib) {
65+
const e = config.build.lib.entry;
66+
if (typeof e === "string") {
67+
entry = e;
68+
} else {
69+
throw new Error("Entry must be a string path");
70+
}
71+
}
72+
73+
projectRoot = config.root;
74+
resolvedEntryPath = path.normalize(path.resolve(projectRoot, entry));
75+
},
76+
async load(id) {
77+
const normalizedId = path.normalize(path.resolve(projectRoot, id));
78+
79+
if (normalizedId === resolvedEntryPath) {
80+
try {
81+
const content = await fs.readFile(resolvedEntryPath, "utf-8");
82+
const transformedContent = [
83+
'import { handle } from "hono/vercel";',
84+
content,
85+
"const handler = handle(app);",
86+
"export const GET = handler;",
87+
"export const POST = handler;",
88+
"export const PATCH = handler;",
89+
"export const PUT = handler;",
90+
"export const OPTIONS = handler;",
91+
].join("\n");
92+
93+
return transformedContent;
94+
} catch (e) {
95+
this.error(`Failed to process entry file ${entry}: ${e}`);
96+
}
97+
}
98+
99+
return null;
100+
},
101+
};
102+
};
103+
40104
/**
41105
* Vite is handling both the building of our final assets and also running the
42106
* dev server which gives us HMR for both SSR'd templates and client React code.
@@ -62,7 +126,7 @@ const vercelConfigPlugin = () => ({
62126
* paths within the code. This is something that could be improved to make
63127
* the build script less brittle.
64128
*
65-
* [1]: <https://vercel.com/docs/build-output-api>
129+
* [1]: <https://vercel.com/docs/build-output-api>
66130
*/
67131
export default defineConfig(({ mode, command }) => {
68132
const baseConfig = {
@@ -101,13 +165,15 @@ export default defineConfig(({ mode, command }) => {
101165
name: "server",
102166
formats: ["umd"],
103167
},
168+
plugins: [vercelConfigPlugin()],
104169
rollupOptions: {
105170
output: {
106171
entryFileNames: "output/functions/index.func/index.js",
107172
},
108-
plugins: [vercelConfigPlugin()],
173+
// plugins: [vercelEntryPlugin("src/server/index.tsx")],
109174
},
110175
},
176+
plugins: [vercelEntryPlugin()],
111177
};
112178

113179
const devConfig = {

0 commit comments

Comments
 (0)