Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(deploy): cloudflare serve #879

Merged
merged 12 commits into from
Sep 19, 2024
41 changes: 0 additions & 41 deletions packages/waku/src/lib/builder/serve-cloudflare.ts

This file was deleted.

90 changes: 49 additions & 41 deletions packages/waku/src/lib/plugins/vite-plugin-deploy-cloudflare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,46 @@ import {
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_PUBLIC } from '../builder/constants.js';

const SERVE_JS = 'serve-cloudflare.js';

const getServeJsContent = (srcEntriesFile: string) => `
import { runner, importHono } from 'waku/unstable_hono';

const { Hono } = await importHono();

const loadEntries = () => import('${srcEntriesFile}');
let serveWaku;

const app = new Hono();
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 +75,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 +106,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 +140,7 @@ export function deployCloudflarePlugin(opts: {
writeFileSync(
workerEntrypoint,
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if index.js and serve-cloudflare.js can be combined.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be. We could remove this and update SERVE_JS to const SERVE_JS = 'index.js';

`
import server from './${DIST_SERVE_JS}'
import server from './${SERVE_JS}'

export default {
...server
Expand Down
Loading