Skip to content

Commit

Permalink
refactor(deploy): cloudflare serve (#879)
Browse files Browse the repository at this point in the history
Prior art:
- #877 
- #878

---------

Co-authored-by: Rob Marscher <rob@robmarscher.com>
  • Loading branch information
dai-shi and rmarscher authored Sep 19, 2024
1 parent 58f7ded commit 543da2a
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 87 deletions.
10 changes: 6 additions & 4 deletions packages/waku/src/lib/builder/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -777,8 +777,10 @@ export async function build(options: {
await buildDeploy(rootDir, config);
delete platformObject.buildOptions.unstable_phase;

await appendFile(
distEntriesFile,
`export const buildData = ${JSON.stringify(platformObject.buildData)};`,
);
if (existsSync(distEntriesFile)) {
await appendFile(
distEntriesFile,
`export const buildData = ${JSON.stringify(platformObject.buildData)};`,
);
}
}
41 changes: 0 additions & 41 deletions packages/waku/src/lib/builder/serve-cloudflare.ts

This file was deleted.

100 changes: 58 additions & 42 deletions packages/waku/src/lib/plugins/vite-plugin-deploy-cloudflare.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,55 @@
import path from 'node:path';
import {
appendFileSync,
existsSync,
mkdirSync,
readdirSync,
renameSync,
rmSync,
writeFileSync,
} from 'node:fs';
import { normalizePath } from 'vite';
import type { Plugin } from 'vite';

import { unstable_getPlatformObject } from '../../server.js';
import { EXTENSIONS, SRC_ENTRIES } from '../constants.js';
import {
decodeFilePathFromAbsolute,
extname,
fileURLToFilePath,
joinPath,
} from '../utils/path.js';
import { DIST_SERVE_JS, DIST_PUBLIC } from '../builder/constants.js';

const resolveFileName = (fname: string) => {
for (const ext of EXTENSIONS) {
const resolvedName = fname.slice(0, -extname(fname).length) + ext;
if (existsSync(resolvedName)) {
return resolvedName;
}
import { SRC_ENTRIES } from '../constants.js';
import { DIST_ENTRIES_JS, DIST_PUBLIC } from '../builder/constants.js';

const SERVE_JS = 'serve-cloudflare.js';

const getServeJsContent = (srcEntriesFile: string) => `
import { runner, importHono, importHonoContextStorage } from 'waku/unstable_hono';
const { Hono } = await importHono();
const { contextStorage } = await importHonoContextStorage();
const loadEntries = () => import('${srcEntriesFile}');
let serveWaku;
const app = new Hono();
app.use(contextStorage());
app.use('*', (c, next) => serveWaku(c, next));
app.notFound(async (c) => {
const assetsFetcher = c.env.ASSETS;
const url = new URL(c.req.raw.url);
const errorHtmlUrl = url.origin + '/404.html';
const notFoundStaticAssetResponse = await assetsFetcher.fetch(
new URL(errorHtmlUrl),
);
if (notFoundStaticAssetResponse && notFoundStaticAssetResponse.status < 400) {
return c.body(notFoundStaticAssetResponse.body, 404);
}
return fname; // returning the default one
};
return c.text('404 Not Found', 404);
});
const srcServeFile = decodeFilePathFromAbsolute(
joinPath(
fileURLToFilePath(import.meta.url),
'../../builder/serve-cloudflare.js',
),
);
export default {
async fetch(request, env, ctx) {
if (!serveWaku) {
serveWaku = runner({ cmd: 'start', loadEntries, env });
}
return app.fetch(request, env, ctx);
},
};
`;

const getFiles = (dir: string, files: string[] = []): string[] => {
const entries = readdirSync(dir, { withFileTypes: true });
Expand Down Expand Up @@ -64,35 +78,22 @@ export function deployCloudflarePlugin(opts: {
}): Plugin {
const platformObject = unstable_getPlatformObject();
let rootDir: string;
let entriesFile: string;
return {
name: 'deploy-cloudflare-plugin',
config(viteConfig) {
const { deploy, unstable_phase } = platformObject.buildOptions || {};
if (unstable_phase !== 'buildServerBundle' || deploy !== 'cloudflare') {
return;
}

// FIXME This seems too hacky (The use of viteConfig.root, '.', path.resolve and resolveFileName)
const entriesFile = normalizePath(
resolveFileName(
path.resolve(
viteConfig.root || '.',
opts.srcDir,
SRC_ENTRIES + '.jsx',
),
),
);
const { input } = viteConfig.build?.rollupOptions ?? {};
if (input && !(typeof input === 'string') && !(input instanceof Array)) {
input[DIST_SERVE_JS.replace(/\.js$/, '')] = srcServeFile;
input[SERVE_JS.replace(/\.js$/, '')] = `${opts.srcDir}/${SERVE_JS}`;
}
viteConfig.define = {
...viteConfig.define,
'import.meta.env.WAKU_ENTRIES_FILE': JSON.stringify(entriesFile),
};
},
configResolved(config) {
rootDir = config.root;
entriesFile = `${rootDir}/${opts.srcDir}/${SRC_ENTRIES}`;
const { deploy, unstable_phase } = platformObject.buildOptions || {};
if (
(unstable_phase !== 'buildServerBundle' &&
Expand All @@ -108,6 +109,16 @@ export function deployCloudflarePlugin(opts: {
config.ssr.resolve.externalConditions ||= [];
config.ssr.resolve.externalConditions.push('worker');
},
resolveId(source) {
if (source === `${opts.srcDir}/${SERVE_JS}`) {
return source;
}
},
load(id) {
if (id === `${opts.srcDir}/${SERVE_JS}`) {
return getServeJsContent(entriesFile);
}
},
closeBundle() {
const { deploy, unstable_phase } = platformObject.buildOptions || {};
if (unstable_phase !== 'buildDeploy' || deploy !== 'cloudflare') {
Expand All @@ -132,7 +143,7 @@ export function deployCloudflarePlugin(opts: {
writeFileSync(
workerEntrypoint,
`
import server from './${DIST_SERVE_JS}'
import server from './${SERVE_JS}'
export default {
...server
Expand Down Expand Up @@ -200,14 +211,19 @@ export default {
force: true,
});

appendFileSync(
path.join(outDir, WORKER_JS_NAME, DIST_ENTRIES_JS),
`export const buildData = ${JSON.stringify(platformObject.buildData)};`,
);

const wranglerTomlFile = path.join(rootDir, 'wrangler.toml');
if (!existsSync(wranglerTomlFile)) {
writeFileSync(
wranglerTomlFile,
`
# See https://developers.cloudflare.com/pages/functions/wrangler-configuration/
name = "waku-project"
compatibility_date = "2024-04-03"
compatibility_date = "2024-09-02"
compatibility_flags = [ "nodejs_als" ]
pages_build_output_dir = "./dist"
`,
Expand Down

0 comments on commit 543da2a

Please sign in to comment.