Skip to content

Commit

Permalink
feat: server support
Browse files Browse the repository at this point in the history
  • Loading branch information
magne4000 committed Jun 26, 2024
1 parent 842cd1d commit 6abe690
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 3,543 deletions.
3,531 changes: 0 additions & 3,531 deletions examples/bati-app/pnpm-lock.yaml

This file was deleted.

7 changes: 6 additions & 1 deletion examples/bati-app/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export default defineConfig({
}),
vike({}),
vikeSolid(),
pages(),
pages({
server: {
kind: "hono",
entry: "hono-entry.ts",
},
}),
],
});
9 changes: 9 additions & 0 deletions packages/vike-cloudflare/assets/hono.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Hono } from "hono";
import app from "virtual:vike-cloudflare-entry";

const worker = new Hono();

worker.route("/", app);
worker.notFound(app.notFoundHandler);

export default worker;
File renamed without changes.
3 changes: 3 additions & 0 deletions packages/vike-cloudflare/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module "virtual:*" {
export default any;
}
6 changes: 5 additions & 1 deletion packages/vike-cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@
"keywords": [],
"author": "",
"devDependencies": {
"esbuild-plugin-raw": "^0.1.8",
"hono": "^4.4.7",
"tsup": "^8.1.0",
"typescript": "^5.5.2"
},
"dependencies": {
"vike": "^0.4.177",
"vite": "^5.3.1"
},
"files": ["dist"],
"files": [
"dist"
],
"exports": {
".": {
"import": "./dist/index.js",
Expand Down
78 changes: 69 additions & 9 deletions packages/vike-cloudflare/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { copyFile, mkdir, rm, symlink, writeFile } from "node:fs/promises";
import { mkdir, rm, symlink, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { normalizePath, Plugin, ResolvedConfig } from "vite";
import honoAsset from "../assets/hono.js?raw";
import vikeAsset from "../assets/vike.js?raw";

const __dirname = dirname(fileURLToPath(import.meta.url));

const NAME = "vike-cloudflare";
const WORKER_JS_NAME = "_worker.js";
const WORKER_NAME = "cloudflare-worker";
const ROUTES_JSON_NAME = "_routes.json";

export interface VikeCloudflarePagesOptions {}
export interface VikeCloudflarePagesOptions {
server?: {
kind: "hono";
entry: string;
};
}

function getOutDir(config: ResolvedConfig, force?: "client" | "server" | "cloudflare"): string {
const p = join(config.root, normalizePath(config.build.outDir));
Expand All @@ -17,18 +23,56 @@ function getOutDir(config: ResolvedConfig, force?: "client" | "server" | "cloudf
}

export const pages = (options?: VikeCloudflarePagesOptions): Plugin => {
const virtualEntryId = "virtual:vike-cloudflare-entry";
const virtualServerId = "virtual:vike-cloudflare-server";
const resolvedVirtualServerId = "\0" + virtualServerId;
let resolvedConfig: ResolvedConfig;

return {
name: "vike-cloudflare",
name: NAME,
enforce: "post",
resolveId(id) {
if (id === virtualEntryId) {
assert(options?.server, `[${NAME}] server.entry is required when using a server`);
return options.server.entry;
}
if (id === virtualServerId) {
return resolvedVirtualServerId;
}
},
load(id) {
if (id === resolvedVirtualServerId) {
switch (options?.server?.kind) {
case "hono": {
return honoAsset;
}
default:
return vikeAsset;
}
}
},
configResolved: async (config) => {
resolvedConfig = config;
},
options(inputOptions) {
if (!resolvedConfig.build?.ssr) {
return;
}
assert(
typeof inputOptions.input === "object" && !Array.isArray(inputOptions.input),
`[${NAME}] input should be an object. Aborting`,
);

inputOptions.input[WORKER_NAME] = virtualServerId;

if (options?.server?.entry) {
inputOptions.input["cloudflare-server-entry"] = virtualEntryId;
}
},
writeBundle: {
order: "post",
sequential: true,
async handler() {
async handler(_, bundle) {
if (!resolvedConfig.build?.ssr) {
return;
}
Expand All @@ -51,7 +95,6 @@ export const pages = (options?: VikeCloudflarePagesOptions): Plugin => {
{
version: 1,
include: ["/*"],
// TODO: when using servers, can be extended
exclude: ["/assets/*"],
},
undefined,
Expand All @@ -61,8 +104,25 @@ export const pages = (options?: VikeCloudflarePagesOptions): Plugin => {
);

// 5. Create _worker.js
await copyFile(join(__dirname, WORKER_JS_NAME), join(outCloudflare, WORKER_JS_NAME));
const [chunkPath] = Object.entries(bundle).find(([_, value]) => {
return value.type === "chunk" && value.isEntry && value.name === WORKER_NAME;
})!;

await writeFile(
join(outCloudflare, WORKER_JS_NAME),
`import handler from "./server/${chunkPath}";
export default handler;
`,
"utf-8",
);
},
},
};
};

function assert(condition: unknown, message: string): asserts condition {
if (condition) {
return;
}
throw new Error(message);
}
3 changes: 2 additions & 1 deletion packages/vike-cloudflare/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import RawPlugin from "esbuild-plugin-raw";
import { defineConfig } from "tsup";

export default defineConfig({
Expand All @@ -6,5 +7,5 @@ export default defineConfig({
dts: true,
entry: ["src/index.ts"],
clean: true,
publicDir: "assets",
esbuildPlugins: [RawPlugin()],
});
15 changes: 15 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6abe690

Please sign in to comment.