Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 16 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ hono --help
# Send request to Hono app
hono request

# Build your Hono app
hono build
# Build an optimized Hono app
hono optimize

# Show routes of your Hono app
hono routes
Expand All @@ -43,7 +43,7 @@ hono agent-context
## Commands

- `request [file]` - Send request to Hono app using `app.request()`
- `build [entry]` - Build your Hono app
- `optimize [entry]` - Build an optimized Hono app
- `routes [file]` - Show routes of your Hono app
- `ssg [file]` - Generate static files from your Hono app
- `agent-context` - Show how to use Hono CLI, for coding agents
Expand Down Expand Up @@ -118,15 +118,15 @@ The result is JSON with the shared envelope. A JSON response body is embedded as

A binary response body becomes `"body": null` with `"binary": true` — save it with `-o`. Use `--plain` to print the raw body like curl.

### `build`
### `optimize`

Build your Hono app into a single bundled file.
Build your Hono app into a single optimized bundle. For a plain bundle, use your normal build tool — this command exists for the Hono-specific optimizations:

```bash
hono build [entry] [options]
hono optimize [entry] [options]
```

With the `--optimize` option, it also applies Hono-specific optimizations to reduce bundle size:
It applies the following optimizations to reduce bundle size:

- **Router optimization**: Replaces the router with a prebuilt router for your routes
- **Request body API removal**: Removes request body APIs (`c.req.json()`, `c.req.formData()`, etc.) when every route method is strictly GET, HEAD, or OPTIONS. A route or middleware registered with `all()` or `use()` keeps the APIs, because it may read the request body
Expand All @@ -142,7 +142,6 @@ With the `--optimize` option, it also applies Hono-specific optimizations to red
- `-o, --outfile <outfile>` - Output file
- `-m, --minify` - minify output file
- `-t, --target [target]` - environment target
- `--optimize` - apply Hono-specific optimizations
- `--request-body-api-removal <mode>` - Request body API removal mode: `auto` (default), `force`, or `disable`
- `--no-context-response-api-removal` - Disable response utility API removal from Context object
- `--no-hono-api-removal` - Disable Hono API removal optimization
Expand All @@ -151,17 +150,17 @@ With the `--optimize` option, it also applies Hono-specific optimizations to red
**Examples:**

```bash
# Build src/index.ts to dist/index.js
hono build

# Build with optimizations
hono build --optimize
# Build an optimized bundle to dist/index.js
hono optimize

# Specify entry file and output file
hono build -o dist/app.js src/app.ts
hono optimize -o dist/app.js src/app.ts

# With minification
hono optimize -m

# Build with minification
hono build -m --optimize
# Control request body API removal
hono optimize --request-body-api-removal force
```

**Output:**
Expand All @@ -172,7 +171,6 @@ The result is JSON. All Hono CLI commands use the same envelope: `ok` and `data`
{
"ok": true,
"data": {
"optimized": true,
"router": "PreparedRegExpRouter",
"removed": {
"requestBodyApis": true,
Expand All @@ -192,7 +190,7 @@ The result is JSON. All Hono CLI commands use the same envelope: `ok` and `data`
"code": "ENTRY_NOT_FOUND",
"message": "Entry file missing.ts does not exist",
"suggestions": [
"Pass the entry file: hono build src/app.ts",
"Pass the entry file: hono optimize src/app.ts",
"Default candidates are src/index.ts, src/index.tsx, src/index.js, and src/index.jsx"
]
}
Expand Down
4 changes: 2 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { agentContextCommand } from './commands/agent-context/index.js'
import { buildCommand } from './commands/build/index.js'
import { optimizeCommand } from './commands/optimize/index.js'
import { requestCommand } from './commands/request/index.js'
import { routesCommand } from './commands/routes/index.js'
import { ssgCommand } from './commands/ssg/index.js'
Expand All @@ -23,7 +23,7 @@ program
.addHelpText('after', "\nFor coding agents: run 'hono agent-context' and follow it.")

// Register commands
buildCommand(program)
optimizeCommand(program)
requestCommand(program)
routesCommand(program)
ssgCommand(program)
Expand Down
6 changes: 3 additions & 3 deletions src/commands/agent-context/document.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { Command } from 'commander'
import type { CommandAgentContext } from '../../utils/agent-context.js'
import { bullets, codeBlock, section, steps } from '../../utils/markdown.js'
import { agentContext as buildContext } from '../build/index.js'
import { agentContext as optimizeContext } from '../optimize/index.js'
import { agentContext as requestContext } from '../request/index.js'
import { agentContext as routesContext } from '../routes/index.js'
import { agentContext as ssgContext } from '../ssg/index.js'

const contexts: Record<string, CommandAgentContext> = {
routes: routesContext,
request: requestContext,
build: buildContext,
optimize: optimizeContext,
ssg: ssgContext,
}

Expand Down Expand Up @@ -70,7 +70,7 @@ export const renderAgentContext = (program: Command): string =>
'`hono routes` — get all routes of the app without reading the source',
'`hono request -P <path>` — send a request to the app without a server',
'After you change the app, run them again to verify',
'`hono build` — bundle the app (`--optimize` to reduce size)',
'`hono optimize` — build an optimized bundle of the app',
])
),
section(
Expand Down
10 changes: 5 additions & 5 deletions src/commands/agent-context/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Command } from 'commander'
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { buildCommand } from '../build/index.js'
import { optimizeCommand } from '../optimize/index.js'
import { requestCommand } from '../request/index.js'
import { routesCommand } from '../routes/index.js'
import { agentContextCommand } from './index.js'
Expand All @@ -12,7 +12,7 @@ describe('agentContextCommand', () => {

beforeEach(() => {
program = new Command()
buildCommand(program)
optimizeCommand(program)
requestCommand(program)
routesCommand(program)
agentContextCommand(program)
Expand Down Expand Up @@ -45,15 +45,15 @@ describe('agentContextCommand', () => {

it('should document every command except itself', async () => {
const output = await getOutput()
expect(output).toContain('### hono build [entry]')
expect(output).toContain('### hono optimize [entry]')
expect(output).toContain('### hono request [file]')
expect(output).toContain('### hono routes [file]')
expect(output).not.toContain('### hono agent-context')
})

it('should include options from the command definitions', async () => {
const output = await getOutput()
expect(output).toContain('`--optimize`')
expect(output).toContain('`--request-body-api-removal <mode>`')
expect(output).toContain('`-P, --path <path>`')
expect(output).toContain('`--verbose`')
})
Expand All @@ -63,6 +63,6 @@ describe('agentContextCommand', () => {
expect(output).toContain('`ENTRY_NOT_FOUND`')
expect(output).toContain('`INVALID_APP`')
expect(output).toContain('"router": "SmartRouter + RegExpRouter"')
expect(output).toContain('hono build --optimize')
expect(output).toContain('hono optimize -m')
})
})
Loading
Loading