Skip to content

Commit 17b519c

Browse files
committed
feat: watch mode
1 parent 979e246 commit 17b519c

File tree

2 files changed

+75
-14
lines changed

2 files changed

+75
-14
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,21 @@ Vite as Node runtime.
1313
npx vite-node index.ts
1414
```
1515

16+
Options:
17+
18+
```bash
19+
npx vite-node -h
20+
```
21+
1622
## Features
1723

1824
- Out-of-box ESM & TypeScript support (possible for more with plugins)
1925
- Top-level await
20-
- Shims for `__dirname` and `__filename`
26+
- Vite plugins, resolve, aliasing
2127
- Respect `vite.config.ts`
22-
- Access to node modules like `fs`, `path` etc.
28+
- Shims for `__dirname` and `__filename` in ESM
29+
- Access to native node modules like `fs`, `path`, etc.
30+
- Watch mode (like `nodemon`)
2331

2432
## When NOT to Use
2533

index.mjs

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1+
/* eslint-disable no-console */
12
import { builtinModules, createRequire } from 'module'
23
import { pathToFileURL } from 'url'
34
import { dirname, resolve, relative } from 'path'
45
import { createServer } from 'vite'
56
import createDebug from 'debug'
67
import minimist from 'minimist'
7-
import { red, dim, yellow } from 'kolorist'
8+
import { red, dim, yellow, green, inverse, cyan } from 'kolorist'
89

910
const argv = minimist(process.argv.slice(2), {
1011
alias: {
1112
r: 'root',
1213
c: 'config',
1314
h: 'help',
15+
w: 'watch',
16+
s: 'silent',
1417
},
1518
string: ['root', 'config'],
16-
boolean: ['help', 'vue'],
19+
boolean: ['help', 'vue', 'watch', 'silent'],
1720
unknown(name) {
1821
if (name[0] === '-') {
1922
console.error(red(`Unknown argument: ${name}`))
@@ -43,6 +46,8 @@ const root = argv.root || process.cwd()
4346
process.chdir(root)
4447

4548
const server = await createServer({
49+
logLevel: 'error',
50+
clearScreen: false,
4651
configFile: argv.config,
4752
root,
4853
resolve: argv.vue
@@ -60,8 +65,50 @@ const server = await createServer({
6065
: {},
6166
})
6267
await server.pluginContainer.buildStart({})
63-
await execute(files, server, argv)
64-
await server.close()
68+
let executing = false
69+
70+
async function run() {
71+
process.exitCode = 0
72+
executing = true
73+
let err
74+
try {
75+
await execute(files, server, argv)
76+
}
77+
catch (e) {
78+
console.error(e)
79+
err = e
80+
if (!argv.watch)
81+
process.exit(1)
82+
}
83+
finally {
84+
executing = false
85+
}
86+
87+
if (argv.watch) {
88+
setTimeout(() => {
89+
if (err || process.exitCode)
90+
log(inverse(red(' vite node ')), red('program exited with error, waiting for file changes...'))
91+
else
92+
log(inverse(green(' vite node ')), green('program exited, waiting for file changes...'))
93+
}, 10)
94+
}
95+
else {
96+
await server.close()
97+
}
98+
}
99+
100+
if (argv.watch) {
101+
log(inverse(cyan(' vite node ')), cyan('watch mode enabled\n'))
102+
103+
server.watcher.on('change', (file) => {
104+
if (!executing) {
105+
log(inverse(yellow(' vite node ')), yellow(`${file} changed, restarting...\n`))
106+
run()
107+
}
108+
})
109+
}
110+
111+
await run(files, server, argv)
65112

66113
// --- CLI END ---
67114

@@ -85,6 +132,11 @@ function toFilePath(id) {
85132
async function execute(files, server) {
86133
const __pendingModules__ = new Map()
87134

135+
const result = []
136+
for (const file of files)
137+
result.push(await cachedRequest(`/@fs/${slash(resolve(file))}`, []))
138+
return result
139+
88140
async function directRequest(rawId, callstack) {
89141
if (builtinModules.includes(rawId))
90142
return import(rawId)
@@ -139,9 +191,8 @@ async function execute(files, server) {
139191
)
140192

141193
// prefetch deps
142-
result.deps.forEach(dep => request(dep))
143-
144194
await fn(...Object.values(context))
195+
145196
return exports
146197
}
147198

@@ -166,26 +217,28 @@ async function execute(files, server) {
166217
}
167218
}
168219
}
169-
170-
const result = []
171-
for (const file of files)
172-
result.push(await cachedRequest(`/@fs/${slash(resolve(file))}`, []))
173-
return result
174220
}
175221

176222
function slash(path) {
177223
return path.replace(/\\/g, '/')
178224
}
179225

180226
function help() {
181-
// eslint-disable-next-line no-console
182227
console.log(`
183228
Usage:
184229
$ vite-node [options] [files]
185230
186231
Options:
187232
-r, --root <path> ${dim('[string]')} use specified root directory
188233
-c, --config <file> ${dim('[string]')} use specified config file
234+
-w, --watch ${dim('[boolean]')} restart on file changes, similar to "nodemon"
235+
-s, --silent ${dim('[boolean]')} do not emit errors and logs
189236
--vue ${dim('[boolean]')} support for importing Vue component
190237
`)
191238
}
239+
240+
function log(...args) {
241+
if (argv.silent)
242+
return
243+
console.log(...args)
244+
}

0 commit comments

Comments
 (0)