Skip to content

Commit

Permalink
refactor(deploy): aws-lambda serve (#882)
Browse files Browse the repository at this point in the history
Prior art:
- #877 
- #878
  • Loading branch information
dai-shi authored Sep 27, 2024
1 parent 37cd30f commit abc5d17
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 67 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ deployctl deploy --prod dist/serve-deno.js --exclude node_modules
npm run build -- --with-aws-lambda
```

The handler entrypoint is `dist/serve.js`: see [Hono AWS Lambda Deploy Docs](https://hono.dev/getting-started/aws-lambda#_3-deploy).
The handler entrypoint is `dist/serve-asw-lambda.js`: see [Hono AWS Lambda Deploy Docs](https://hono.dev/getting-started/aws-lambda#_3-deploy).

## Community

Expand Down
6 changes: 3 additions & 3 deletions docs/builder/aws-lambda.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Deploy a WAKU application to AWS.
# AWS Lambda Builder

The WAKU builder for AWS Lambda will provide the bundled output in the `dist` folder.
The entry handler for the Lambda is `dist/serve.handler`.
The entry handler for the Lambda is `dist/serve-aws-lambda.handler`.

> Folder which require directly access - eg. `fs.readFile("./private/data.json")` needs to be manual added to the deployment configuration.
Expand Down Expand Up @@ -50,7 +50,7 @@ package:

functions:
ssr:
handler: dist/serve.handler
handler: dist/serve-aws-lambda.handler
events:
- httpApi: '*'

Expand Down Expand Up @@ -211,7 +211,7 @@ export class WakuStack extends cdk.Stack {
},
},
}),
handler: 'serve.handler',
handler: 'serve-aws-lambda.handler',
architecture: lambda.Architecture.ARM_64,
runtime: lambda.Runtime.NODEJS_20_X,
});
Expand Down
26 changes: 0 additions & 26 deletions packages/waku/src/lib/builder/serve-aws-lambda.ts

This file was deleted.

98 changes: 61 additions & 37 deletions packages/waku/src/lib/plugins/vite-plugin-deploy-aws-lambda.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,87 @@
import path from 'node:path';
import { existsSync, writeFileSync } from 'node:fs';
import { normalizePath } from 'vite';
import { writeFileSync } from 'node:fs';
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';
import { SRC_ENTRIES } from '../constants.js';
import { 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;
}
const SERVE_JS = 'serve-aws-lambda.js';

const getServeJsContent = (
distDir: string,
distPublic: string,
srcEntriesFile: string,
) => `
import path from 'node:path';
import { existsSync, readFileSync } from 'node:fs';
import { runner, importHono, importHonoNodeServerServeStatic, importHonoAwsLambda } from 'waku/unstable_hono';
const { Hono } = await importHono();
const { serveStatic } = await importHonoNodeServerServeStatic();
const { handle } = await importHonoAwsLambda();
let contextStorage;
try {
({ contextStorage } = await import('hono/context-storage'));
} catch {}
const distDir = '${distDir}';
const publicDir = '${distPublic}';
const loadEntries = () => import('${srcEntriesFile}');
const app = new Hono();
if (contextStorage) {
app.use(contextStorage());
}
app.use('*', serveStatic({ root: distDir + '/' + publicDir }));
app.use('*', runner({ cmd: 'start', loadEntries, env: process.env }));
app.notFound(async (c) => {
const file = path.join(distDir, publicDir, '404.html');
if (existsSync(file)) {
return c.html(readFileSync(file, 'utf8'), 404);
}
return fname; // returning the default one
};
return c.text('404 Not Found', 404);
});
const srcServeFile = decodeFilePathFromAbsolute(
joinPath(
fileURLToFilePath(import.meta.url),
'../../builder/serve-aws-lambda.js',
),
);
export const handler = handle(app);
`;

export function deployAwsLambdaPlugin(opts: {
srcDir: string;
distDir: string;
}): Plugin {
const platformObject = unstable_getPlatformObject();
let entriesFile: string;
return {
name: 'deploy-aws-lambda-plugin',
config(viteConfig) {
const { deploy, unstable_phase } = platformObject.buildOptions || {};
if (unstable_phase !== 'buildServerBundle' || deploy !== 'aws-lambda') {
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),
),
);
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}`;
}
},
configResolved(config) {
entriesFile = `${config.root}/${opts.srcDir}/${SRC_ENTRIES}`;
const { deploy } = platformObject.buildOptions || {};
if (deploy === 'aws-lambda' && Array.isArray(config.ssr.external)) {
config.ssr.external = config.ssr.external.filter(
(item) => item !== 'hono/context-storage',
);
}
},
resolveId(source) {
if (source === `${opts.srcDir}/${SERVE_JS}`) {
return source;
}
},
load(id) {
if (id === `${opts.srcDir}/${SERVE_JS}`) {
return getServeJsContent(opts.distDir, DIST_PUBLIC, entriesFile);
}
viteConfig.define = {
...viteConfig.define,
'import.meta.env.WAKU_ENTRIES_FILE': JSON.stringify(entriesFile),
'import.meta.env.WAKU_CONFIG_PUBLIC_DIR': JSON.stringify(DIST_PUBLIC),
};
},
closeBundle() {
const { deploy, unstable_phase } = platformObject.buildOptions || {};
Expand Down
1 change: 1 addition & 0 deletions packages/waku/src/unstable_hono.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export const importHono = () => import('hono');
export const importHonoNodeServer: any = () => import('@hono/node-server');
export const importHonoNodeServerServeStatic = () =>
import('@hono/node-server/serve-static');
export const importHonoAwsLambda: any = () => import('hono/aws-lambda');

0 comments on commit abc5d17

Please sign in to comment.