Skip to content

Commit

Permalink
feat: output cloudflare (dai-shi#267)
Browse files Browse the repository at this point in the history
* add hacky output cloudflare

* wip: readme

* fix for undefined

* fix typo

* oh this is hard..

* fix readme

* update README
  • Loading branch information
dai-shi authored and himself65 committed Dec 17, 2023
1 parent b19a9c0 commit 8bad3c1
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 7 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,27 @@ Alternatively, you could create a project with something like
`npm create waku@latest` and copy files from the example
folder in the repository.

## Deploy

### Vercel

```sh
vercel
```

Then change the setting as follows (needs redeploy for the first time):

![vercel](https://github.com/dai-shi/waku/assets/490574/6bd317a8-2772-42f4-92d4-b508af7d7460)

### Cloudflare

```sh
npm run build -- --with-cloudflare
rm -r node_modules
npm install --omit=dev --omit=peer
npx wrangler dev # or deploy
```

## Tweets

<https://github.com/dai-shi/waku/discussions/150>
Expand Down
26 changes: 21 additions & 5 deletions packages/waku/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ const { values, positionals } = parseArgs({
'with-ssr': {
type: 'boolean',
},
'with-vercel': {
type: 'boolean',
},
'with-cloudflare': {
type: 'boolean',
},
version: {
type: 'boolean',
short: 'v',
Expand All @@ -46,7 +52,11 @@ if (values.version) {
runDev({ ssr: !!values['with-ssr'] });
break;
case 'build':
runBuild({ ssr: !!values['with-ssr'] });
runBuild({
ssr: !!values['with-ssr'],
vercel: values['with-vercel'],
cloudflare: !!values['with-cloudflare'],
});
break;
case 'start':
runStart({ ssr: !!values['with-ssr'] });
Expand All @@ -62,13 +72,17 @@ if (values.version) {

async function runDev(options: { ssr: boolean }) {
const app = new Hono();
app.use('*', honoDevMiddleware({ ssr: options.ssr }));
app.use('*', honoDevMiddleware(options));
const port = parseInt(process.env.PORT || '3000', 10);
startServer(app, port);
}

async function runBuild(options: { ssr: boolean }) {
await build({ ssr: options.ssr });
async function runBuild(options: {
ssr: boolean;
vercel: boolean | undefined;
cloudflare: boolean;
}) {
await build(options);
}

async function runStart(options: { ssr: boolean }) {
Expand All @@ -77,7 +91,7 @@ async function runStart(options: { ssr: boolean }) {
url.pathToFileURL(path.resolve(distDir, entriesJs)).toString()
);
const app = new Hono();
app.use('*', honoPrdMiddleware({ entries, ssr: options.ssr }));
app.use('*', honoPrdMiddleware({ entries, ...options }));
app.use('*', serveStatic({ root: path.join(distDir, publicDir) }));
const port = parseInt(process.env.PORT || '8080', 10);
startServer(app, port);
Expand Down Expand Up @@ -108,6 +122,8 @@ Commands:
Options:
--with-ssr Use opt-in SSR
--with-vercel Output for Vercel on build
--with-cloudflare Output for Cloudflare on build
-v, --version Display the version number
-h, --help Display this help message
`);
Expand Down
8 changes: 7 additions & 1 deletion packages/waku/src/lib/builder/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { nonjsResolvePlugin } from '../plugins/vite-plugin-nonjs-resolve.js';
import { rscTransformPlugin } from '../plugins/vite-plugin-rsc-transform.js';
import { patchReactRefresh } from '../plugins/patch-react-refresh.js';
import { emitVercelOutput } from './output-vercel.js';
import { emitCloudflareOutput } from './output-cloudflare.js';

// TODO this file and functions in it are too long. will fix.

Expand Down Expand Up @@ -481,7 +482,8 @@ const resolveFileName = (fname: string) => {
export async function build(options: {
config?: Config;
ssr?: boolean;
vercel?: boolean;
vercel?: boolean | undefined;
cloudflare?: boolean;
}) {
const config = await resolveConfig(options.config || {});
const rootDir = (
Expand Down Expand Up @@ -536,4 +538,8 @@ export async function build(options: {
!!options?.ssr,
);
}

if (options?.cloudflare) {
await emitCloudflareOutput(rootDir, config, !!options?.ssr);
}
}
54 changes: 54 additions & 0 deletions packages/waku/src/lib/builder/output-cloudflare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import path from 'node:path';
import { existsSync, writeFileSync } from 'node:fs';

import type { ResolvedConfig } from '../config.js';

// XXX this can be very limited. FIXME if anyone has better knowledge.
export const emitCloudflareOutput = async (
rootDir: string,
config: ResolvedConfig,
ssr: boolean,
) => {
const outputDir = path.resolve('.');
const relativeRootDir = path.relative(outputDir, rootDir);
const entriesFile = path.join(
relativeRootDir,
config.distDir,
config.entriesJs,
);
const publicDir = path.join(
relativeRootDir,
config.distDir,
config.publicDir,
);
if (!existsSync(path.join(outputDir, 'serve.js'))) {
writeFileSync(
path.join(outputDir, 'serve.js'),
`
import { honoMiddleware } from 'waku';
import { Hono } from 'hono';
import { serveStatic } from 'hono/cloudflare-workers';
const entries = import('./${entriesFile}');
const app = new Hono();
app.use('*', honoMiddleware({ entries, ssr: ${ssr} }));
app.use('*', serveStatic({ root: './' }));
export default app;
`,
);
}
if (!existsSync(path.join(outputDir, 'wrangler.toml'))) {
writeFileSync(
path.join(outputDir, 'wrangler.toml'),
`
name = "waku-project"
main = "serve.js"
compatibility_date = "2023-12-06"
[site]
bucket = "./${publicDir}"
`,
);
}
};
9 changes: 8 additions & 1 deletion packages/waku/src/lib/rsc/worker-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,14 @@ const getWorker = () => {
return lastWorker;
}
return (lastWorker = new Promise<WorkerOrig>((resolve, reject) => {
Promise.all([import('node:worker_threads'), import('node:module')])
Promise.all([
import('node:worker_threads').catch((e) => {
throw e;
}),
import('node:module').catch((e) => {
throw e;
}),
])
.then(([{ Worker }, { default: module }]) => {
const HAS_MODULE_REGISTER = typeof module.register === 'function';
const worker = new Worker(new URL('worker-impl.js', import.meta.url), {
Expand Down

0 comments on commit 8bad3c1

Please sign in to comment.