@@ -16,102 +16,105 @@ export function optimizeCommand(program: Command) {
1616 . argument ( '[entry]' , 'entry file' )
1717 . option ( '-o, --outfile [outfile]' , 'output file' , 'dist/index.js' )
1818 . option ( '-m, --minify' , 'minify output file' )
19- . action ( async ( entry : string , options : { outfile : string ; minify ?: boolean } ) => {
20- if ( ! entry ) {
21- entry =
22- DEFAULT_ENTRY_CANDIDATES . find ( ( entry ) => existsSync ( entry ) ) ?? DEFAULT_ENTRY_CANDIDATES [ 0 ]
23- }
19+ . option ( '-t, --target [target]' , 'environment target (e.g., node24, deno2, es2024)' , 'node20' )
20+ . action (
21+ async ( entry : string , options : { outfile : string ; minify ?: boolean ; target : string } ) => {
22+ if ( ! entry ) {
23+ entry =
24+ DEFAULT_ENTRY_CANDIDATES . find ( ( entry ) => existsSync ( entry ) ) ??
25+ DEFAULT_ENTRY_CANDIDATES [ 0 ]
26+ }
2427
25- const appPath = resolve ( process . cwd ( ) , entry )
28+ const appPath = resolve ( process . cwd ( ) , entry )
2629
27- if ( ! existsSync ( appPath ) ) {
28- throw new Error ( `Entry file ${ entry } does not exist` )
29- }
30+ if ( ! existsSync ( appPath ) ) {
31+ throw new Error ( `Entry file ${ entry } does not exist` )
32+ }
3033
31- const appFilePath = realpathSync ( appPath )
32- const buildIterator = buildAndImportApp ( appFilePath , {
33- external : [ '@hono/node-server' ] ,
34- } )
35- const app : Hono = ( await buildIterator . next ( ) ) . value
34+ const appFilePath = realpathSync ( appPath )
35+ const buildIterator = buildAndImportApp ( appFilePath , {
36+ external : [ '@hono/node-server' ] ,
37+ } )
38+ const app : Hono = ( await buildIterator . next ( ) ) . value
3639
37- let routerName
38- let importStatement
39- let assignRouterStatement
40- try {
41- const serialized = serializeInitParams (
42- buildInitParams ( {
43- paths : app . routes . map ( ( { path } ) => path ) ,
44- } )
45- )
40+ let routerName
41+ let importStatement
42+ let assignRouterStatement
43+ try {
44+ const serialized = serializeInitParams (
45+ buildInitParams ( {
46+ paths : app . routes . map ( ( { path } ) => path ) ,
47+ } )
48+ )
4649
47- const hasPreparedRegExpRouter = await new Promise < boolean > ( ( resolve ) => {
48- const child = execFile ( process . execPath , [
49- '--input-type=module' ,
50- '-e' ,
51- "try { (await import('hono/router/reg-exp-router')).PreparedRegExpRouter && process.exit(0) } finally { process.exit(1) }" ,
52- ] )
53- child . on ( 'exit' , ( code ) => {
54- resolve ( code === 0 )
50+ const hasPreparedRegExpRouter = await new Promise < boolean > ( ( resolve ) => {
51+ const child = execFile ( process . execPath , [
52+ '--input-type=module' ,
53+ '-e' ,
54+ "try { (await import('hono/router/reg-exp-router')).PreparedRegExpRouter && process.exit(0) } finally { process.exit(1) }" ,
55+ ] )
56+ child . on ( 'exit' , ( code ) => {
57+ resolve ( code === 0 )
58+ } )
5559 } )
56- } )
5760
58- if ( hasPreparedRegExpRouter ) {
59- routerName = 'PreparedRegExpRouter'
60- importStatement = "import { PreparedRegExpRouter } from 'hono/router/reg-exp-router'"
61- assignRouterStatement = `const routerParams = ${ serialized }
61+ if ( hasPreparedRegExpRouter ) {
62+ routerName = 'PreparedRegExpRouter'
63+ importStatement = "import { PreparedRegExpRouter } from 'hono/router/reg-exp-router'"
64+ assignRouterStatement = `const routerParams = ${ serialized }
6265 this.router = new PreparedRegExpRouter(...routerParams)`
63- } else {
64- routerName = 'RegExpRouter'
65- importStatement = "import { RegExpRouter } from 'hono/router/reg-exp-router'"
66- assignRouterStatement = 'this.router = new RegExpRouter()'
66+ } else {
67+ routerName = 'RegExpRouter'
68+ importStatement = "import { RegExpRouter } from 'hono/router/reg-exp-router'"
69+ assignRouterStatement = 'this.router = new RegExpRouter()'
70+ }
71+ } catch {
72+ // fallback to default router
73+ routerName = 'TrieRouter'
74+ importStatement = "import { TrieRouter } from 'hono/router/trie-router'"
75+ assignRouterStatement = 'this.router = new TrieRouter()'
6776 }
68- } catch {
69- // fallback to default router
70- routerName = 'TrieRouter'
71- importStatement = "import { TrieRouter } from 'hono/router/trie-router'"
72- assignRouterStatement = 'this.router = new TrieRouter()'
73- }
7477
75- console . log ( '[Optimized]' )
76- console . log ( ` Router: ${ routerName } ` )
78+ console . log ( '[Optimized]' )
79+ console . log ( ` Router: ${ routerName } ` )
7780
78- const outfile = resolve ( process . cwd ( ) , options . outfile )
79- await esbuild . build ( {
80- entryPoints : [ appFilePath ] ,
81- outfile,
82- bundle : true ,
83- minify : options . minify ,
84- format : 'esm' ,
85- target : 'node20' ,
86- platform : 'node' ,
87- jsx : 'automatic' ,
88- jsxImportSource : 'hono/jsx' ,
89- plugins : [
90- {
91- name : 'hono-optimize' ,
92- setup ( build ) {
93- const honoPseudoImportPath = 'hono-optimized-pseudo-import-path'
81+ const outfile = resolve ( process . cwd ( ) , options . outfile )
82+ await esbuild . build ( {
83+ entryPoints : [ appFilePath ] ,
84+ outfile,
85+ bundle : true ,
86+ minify : options . minify ,
87+ format : 'esm' ,
88+ target : options . target ,
89+ platform : 'node' ,
90+ jsx : 'automatic' ,
91+ jsxImportSource : 'hono/jsx' ,
92+ plugins : [
93+ {
94+ name : 'hono-optimize' ,
95+ setup ( build ) {
96+ const honoPseudoImportPath = 'hono-optimized-pseudo-import-path'
9497
95- build . onResolve ( { filter : / ^ h o n o $ / } , async ( args ) => {
96- if ( ! args . importer ) {
97- // prevent recursive resolution of "hono"
98- return undefined
99- }
98+ build . onResolve ( { filter : / ^ h o n o $ / } , async ( args ) => {
99+ if ( ! args . importer ) {
100+ // prevent recursive resolution of "hono"
101+ return undefined
102+ }
100103
101- // resolve original import path for "hono"
102- const resolved = await build . resolve ( args . path , {
103- kind : 'import-statement' ,
104- resolveDir : args . resolveDir ,
105- } )
104+ // resolve original import path for "hono"
105+ const resolved = await build . resolve ( args . path , {
106+ kind : 'import-statement' ,
107+ resolveDir : args . resolveDir ,
108+ } )
106109
107- // mark "honoOptimize" to the resolved path for filtering
108- return {
109- path : join ( dirname ( resolved . path ) , honoPseudoImportPath ) ,
110- }
111- } )
112- build . onLoad ( { filter : new RegExp ( `/${ honoPseudoImportPath } $` ) } , async ( ) => {
113- return {
114- contents : `
110+ // mark "honoOptimize" to the resolved path for filtering
111+ return {
112+ path : join ( dirname ( resolved . path ) , honoPseudoImportPath ) ,
113+ }
114+ } )
115+ build . onLoad ( { filter : new RegExp ( `/${ honoPseudoImportPath } $` ) } , async ( ) => {
116+ return {
117+ contents : `
115118import { HonoBase } from 'hono/hono-base'
116119${ importStatement }
117120export class Hono extends HonoBase {
@@ -121,14 +124,15 @@ export class Hono extends HonoBase {
121124 }
122125}
123126` ,
124- }
125- } )
127+ }
128+ } )
129+ } ,
126130 } ,
127- } ,
128- ] ,
129- } )
131+ ] ,
132+ } )
130133
131- const outfileStat = statSync ( outfile )
132- console . log ( ` Output: ${ options . outfile } (${ ( outfileStat . size / 1024 ) . toFixed ( 2 ) } KB)` )
133- } )
134+ const outfileStat = statSync ( outfile )
135+ console . log ( ` Output: ${ options . outfile } (${ ( outfileStat . size / 1024 ) . toFixed ( 2 ) } KB)` )
136+ }
137+ )
134138}
0 commit comments