Skip to content

Commit

Permalink
Merge branch 'main' into refactor/deploy/aws-lambda
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Sep 19, 2024
2 parents d091fc3 + 543da2a commit 2364d6c
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 91 deletions.
1 change: 1 addition & 0 deletions examples/08_cookies/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"dependencies": {
"cookie": "0.6.0",
"hono": "4.6.1",
"react": "19.0.0-rc-d6cb4e77-20240911",
"react-dom": "19.0.0-rc-d6cb4e77-20240911",
"react-server-dom-webpack": "19.0.0-rc-d6cb4e77-20240911",
Expand Down
4 changes: 3 additions & 1 deletion examples/08_cookies/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Suspense, cache } from 'react';
import { unstable_getCustomContext as getCustomContext } from 'waku/server';
import { getContext } from 'hono/context-storage';

import { Counter } from './Counter';

Expand All @@ -13,7 +14,8 @@ const InternalAsyncComponent = async () => {
throw new Error('Cache not working');
}
// console.log(getCustomContext()); // fails when it's sent to the browser
console.log(Object.keys(getCustomContext()));
console.log('waku context', Object.keys(getCustomContext()));
console.log('hono context', Object.keys(getContext()));
return null;
};

Expand Down
9 changes: 6 additions & 3 deletions packages/waku/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ if (values.version) {

async function runDev() {
const config = await loadConfig();
const honoEnhancer = config.unstable_honoEnhancer || ((app) => app);
const app = new Hono();
app.use(contextStorage());
app.use('*', runner({ cmd: 'dev', config, env: process.env as any }));
Expand All @@ -107,7 +108,7 @@ async function runDev() {
return c.text('404 Not Found', 404);
});
const port = parseInt(values.port || '3000', 10);
await startServer(app, port);
await startServer(honoEnhancer(app), port);
}

async function runBuild() {
Expand Down Expand Up @@ -136,7 +137,9 @@ async function runBuild() {
}

async function runStart() {
const { distDir = 'dist' } = await loadConfig();
const config = await loadConfig();
const { distDir = 'dist' } = config;
const honoEnhancer = config.unstable_honoEnhancer || ((app) => app);
const loadEntries = () =>
import(pathToFileURL(path.resolve(distDir, DIST_ENTRIES_JS)).toString());
const app = new Hono();
Expand All @@ -152,7 +155,7 @@ async function runStart() {
return c.text('404 Not Found', 404);
});
const port = parseInt(values.port || '8080', 10);
await startServer(app, port);
await startServer(honoEnhancer(app), port);
}

function startServer(app: Hono, port: number) {
Expand Down
5 changes: 5 additions & 0 deletions packages/waku/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ export interface Config {
* ]
*/
middleware?: () => Promise<{ default: Middleware }>[];
/**
* Enhander for Hono
* Defaults to `undefined`
*/
unstable_honoEnhancer?: (<Hono>(app: Hono) => Hono) | undefined;
}

export function defineConfig(config: Config) {
Expand Down
11 changes: 7 additions & 4 deletions packages/waku/src/lib/builder/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ const buildServerBundle = async (
conditions: ['react-server'],
externalConditions: ['react-server'],
},
external: ['hono/context-storage'],
noExternal: /^(?!node:)/,
},
esbuild: {
Expand Down Expand Up @@ -776,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.

1 change: 1 addition & 0 deletions packages/waku/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export async function resolveConfig(config: Config) {
privateDir: 'private',
rscPath: 'RSC',
middleware: DEFAULT_MIDDLEWARE,
unstable_honoEnhancer: undefined,
...config,
};
return resolvedConfig;
Expand Down
1 change: 1 addition & 0 deletions packages/waku/src/lib/middleware/dev-server-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ const createRscViteServer = (
conditions: ['react-server'],
externalConditions: ['react-server'],
},
external: ['hono/context-storage'],
noExternal: /^(?!node:)/,
optimizeDeps: {
include: [
Expand Down
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
3 changes: 3 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 2364d6c

Please sign in to comment.