/
cli.ts
240 lines (229 loc) · 6.65 KB
/
cli.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
import { cac } from 'cac'
import chalk from 'chalk'
import { BuildOptions } from './build'
import { ServerOptions } from './server'
import { createLogger, LogLevel } from './logger'
import { resolveConfig } from '.'
import { preview } from './preview'
const cli = cac('vite')
// global options
interface GlobalCLIOptions {
'--'?: string[]
debug?: boolean | string
d?: boolean | string
filter?: string
f?: string
config?: string
c?: boolean | string
root?: string
base?: string
r?: string
mode?: string
m?: string
logLevel?: LogLevel
l?: LogLevel
clearScreen?: boolean
}
/**
* removing global flags before passing as command specific sub-configs
*/
function cleanOptions(options: GlobalCLIOptions) {
const ret = { ...options }
delete ret['--']
delete ret.debug
delete ret.d
delete ret.filter
delete ret.f
delete ret.config
delete ret.c
delete ret.root
delete ret.base
delete ret.r
delete ret.mode
delete ret.m
delete ret.logLevel
delete ret.l
delete ret.clearScreen
return ret
}
cli
.option('-c, --config <file>', `[string] use specified config file`)
.option('-r, --root <path>', `[string] use specified root directory`)
.option('--base <path>', `[string] public base path (default: /)`)
.option('-l, --logLevel <level>', `[string] info | warn | error | silent`)
.option('--clearScreen', `[boolean] allow/disable clear screen when logging`)
.option('-d, --debug [feat]', `[string | boolean] show debug logs`)
.option('-f, --filter <filter>', `[string] filter debug logs`)
// dev
cli
.command('[root]') // default command
.alias('serve')
.option('--host [host]', `[string] specify hostname`)
.option('--port <port>', `[number] specify port`)
.option('--https', `[boolean] use TLS + HTTP/2`)
.option('--open [path]', `[boolean | string] open browser on startup`)
.option('--cors', `[boolean] enable CORS`)
.option('--strictPort', `[boolean] exit if specified port is already in use`)
.option('-m, --mode <mode>', `[string] set env mode`)
.option(
'--force',
`[boolean] force the optimizer to ignore the cache and re-bundle`
)
.action(async (root: string, options: ServerOptions & GlobalCLIOptions) => {
// output structure is preserved even after bundling so require()
// is ok here
const { createServer } = await import('./server')
try {
const server = await createServer({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
logLevel: options.logLevel,
clearScreen: options.clearScreen,
server: cleanOptions(options) as ServerOptions
})
await server.listen()
} catch (e) {
createLogger(options.logLevel).error(
chalk.red(`error when starting dev server:\n${e.stack}`)
)
process.exit(1)
}
})
// build
cli
.command('build [root]')
.option('--target <target>', `[string] transpile target (default: 'modules')`)
.option('--outDir <dir>', `[string] output directory (default: dist)`)
.option(
'--assetsDir <dir>',
`[string] directory under outDir to place assets in (default: _assets)`
)
.option(
'--assetsInlineLimit <number>',
`[number] static asset base64 inline threshold in bytes (default: 4096)`
)
.option(
'--ssr [entry]',
`[string] build specified entry for server-side rendering`
)
.option(
'--sourcemap',
`[boolean] output source maps for build (default: false)`
)
.option(
'--minify [minifier]',
`[boolean | "terser" | "esbuild"] enable/disable minification, ` +
`or specify minifier to use (default: terser)`
)
.option('--manifest', `[boolean] emit build manifest json`)
.option('--ssrManifest', `[boolean] emit ssr manifest json`)
.option(
'--emptyOutDir',
`[boolean] force empty outDir when it's outside of root`
)
.option('-m, --mode <mode>', `[string] set env mode`)
.option('-w, --watch', `[boolean] rebuilds when modules have changed on disk`)
.action(async (root: string, options: BuildOptions & GlobalCLIOptions) => {
const { build } = await import('./build')
const buildOptions = cleanOptions(options) as BuildOptions
try {
await build({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
logLevel: options.logLevel,
clearScreen: options.clearScreen,
build: buildOptions
})
} catch (e) {
createLogger(options.logLevel).error(
chalk.red(`error during build:\n${e.stack}`)
)
process.exit(1)
}
})
// optimize
cli
.command('optimize [root]')
.option(
'--force',
`[boolean] force the optimizer to ignore the cache and re-bundle`
)
.action(
async (root: string, options: { force?: boolean } & GlobalCLIOptions) => {
const { optimizeDeps } = await import('./optimizer')
try {
const config = await resolveConfig(
{
root,
base: options.base,
configFile: options.config,
logLevel: options.logLevel
},
'build',
'development'
)
await optimizeDeps(config, options.force, true)
} catch (e) {
createLogger(options.logLevel).error(
chalk.red(`error when optimizing deps:\n${e.stack}`)
)
process.exit(1)
}
}
)
cli
.command('preview [root]')
.option('--host [host]', `[string] specify hostname`)
.option('--port <port>', `[number] specify port`)
.option('--https', `[boolean] use TLS + HTTP/2`)
.option('--open [path]', `[boolean | string] open browser on startup`)
.option('--strictPort', `[boolean] exit if specified port is already in use`)
.action(
async (
root: string,
options: {
host?: string
port?: number
https?: boolean
open?: boolean | string
strictPort?: boolean
} & GlobalCLIOptions
) => {
try {
const config = await resolveConfig(
{
root,
base: options.base,
configFile: options.config,
logLevel: options.logLevel,
server: {
open: options.open,
strictPort: options.strictPort,
https: options.https
}
},
'serve',
'development'
)
await preview(
config,
cleanOptions(options) as {
host?: string
port?: number
}
)
} catch (e) {
createLogger(options.logLevel).error(
chalk.red(`error when starting preview server:\n${e.stack}`)
)
process.exit(1)
}
}
)
cli.help()
cli.version(require('../../package.json').version)
cli.parse()