vite-node 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -7
- package/index.mjs +128 -40
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -6,9 +6,6 @@ Vite as Node runtime.
|
|
|
6
6
|
|
|
7
7
|
> **EXPERIMENTAL**
|
|
8
8
|
|
|
9
|
-
## Why?
|
|
10
|
-
|
|
11
|
-
It runs Vite's id resolving, module transforming, and most importantly, the powerful plugins system!
|
|
12
9
|
|
|
13
10
|
## Usage
|
|
14
11
|
|
|
@@ -16,19 +13,31 @@ It runs Vite's id resolving, module transforming, and most importantly, the powe
|
|
|
16
13
|
npx vite-node index.ts
|
|
17
14
|
```
|
|
18
15
|
|
|
16
|
+
Options:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx vite-node -h
|
|
20
|
+
```
|
|
21
|
+
|
|
19
22
|
## Features
|
|
20
23
|
|
|
21
24
|
- Out-of-box ESM & TypeScript support (possible for more with plugins)
|
|
22
25
|
- Top-level await
|
|
23
|
-
-
|
|
26
|
+
- Vite plugins, resolve, aliasing
|
|
24
27
|
- Respect `vite.config.ts`
|
|
25
|
-
-
|
|
28
|
+
- Shims for `__dirname` and `__filename` in ESM
|
|
29
|
+
- Access to native node modules like `fs`, `path`, etc.
|
|
30
|
+
- Watch mode (like `nodemon`)
|
|
26
31
|
|
|
27
32
|
## When NOT to Use
|
|
28
33
|
|
|
29
34
|
- Production, yet - in very early stage, check it later
|
|
30
|
-
- Most of the time when other tools can do that job
|
|
31
|
-
- We
|
|
35
|
+
- Most of the time, when other tools can do that job
|
|
36
|
+
- We need to start a Vite server upon each execution, which inevitably introduces some overhead. Only use it when you want the same behavior as Vite or the powerful plugins system (for example, testing components with a Vite-specific setup).
|
|
37
|
+
|
|
38
|
+
## Why?
|
|
39
|
+
|
|
40
|
+
It runs Vite's id resolving, module transforming, and most importantly, the powerful plugins system!
|
|
32
41
|
|
|
33
42
|
## How?
|
|
34
43
|
|
package/index.mjs
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import { builtinModules, createRequire } from 'module'
|
|
2
3
|
import { pathToFileURL } from 'url'
|
|
3
|
-
import {
|
|
4
|
+
import { dirname, resolve, relative } from 'path'
|
|
5
|
+
import vm from 'vm'
|
|
4
6
|
import { createServer } from 'vite'
|
|
5
7
|
import createDebug from 'debug'
|
|
6
8
|
import minimist from 'minimist'
|
|
7
|
-
import { red, dim } from 'kolorist'
|
|
9
|
+
import { red, dim, yellow, green, inverse, cyan } from 'kolorist'
|
|
8
10
|
|
|
9
11
|
const argv = minimist(process.argv.slice(2), {
|
|
10
12
|
alias: {
|
|
11
13
|
r: 'root',
|
|
12
14
|
c: 'config',
|
|
13
15
|
h: 'help',
|
|
16
|
+
w: 'watch',
|
|
17
|
+
s: 'silent',
|
|
14
18
|
},
|
|
15
19
|
string: ['root', 'config'],
|
|
16
|
-
boolean: ['help', 'vue'],
|
|
20
|
+
boolean: ['help', 'vue', 'watch', 'silent'],
|
|
17
21
|
unknown(name) {
|
|
18
22
|
if (name[0] === '-') {
|
|
19
23
|
console.error(red(`Unknown argument: ${name}`))
|
|
@@ -37,12 +41,13 @@ if (!argv._.length) {
|
|
|
37
41
|
|
|
38
42
|
const debugRequest = createDebug('vite-node:request')
|
|
39
43
|
const debugTransform = createDebug('vite-node:transform')
|
|
40
|
-
const AsyncFunction = Object.getPrototypeOf(async() => {}).constructor
|
|
41
44
|
|
|
42
45
|
const root = argv.root || process.cwd()
|
|
43
46
|
process.chdir(root)
|
|
44
47
|
|
|
45
48
|
const server = await createServer({
|
|
49
|
+
logLevel: 'error',
|
|
50
|
+
clearScreen: false,
|
|
46
51
|
configFile: argv.config,
|
|
47
52
|
root,
|
|
48
53
|
resolve: argv.vue
|
|
@@ -60,27 +65,95 @@ const server = await createServer({
|
|
|
60
65
|
: {},
|
|
61
66
|
})
|
|
62
67
|
await server.pluginContainer.buildStart({})
|
|
63
|
-
|
|
64
|
-
|
|
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)
|
|
65
112
|
|
|
66
113
|
// --- CLI END ---
|
|
67
114
|
|
|
115
|
+
function normalizeId(id) {
|
|
116
|
+
// Virtual modules start with `\0`
|
|
117
|
+
if (id && id.startsWith('/@id/__x00__'))
|
|
118
|
+
id = `\0${id.slice('/@id/__x00__'.length)}`
|
|
119
|
+
if (id && id.startsWith('/@id/'))
|
|
120
|
+
id = id.slice('/@id/'.length)
|
|
121
|
+
return id
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function toFilePath(id) {
|
|
125
|
+
const absolute = id.startsWith('/@fs/')
|
|
126
|
+
? id.slice(4)
|
|
127
|
+
: slash(resolve(server.config.root, id.slice(1)))
|
|
128
|
+
|
|
129
|
+
return absolute
|
|
130
|
+
}
|
|
131
|
+
|
|
68
132
|
async function execute(files, server) {
|
|
69
|
-
const
|
|
133
|
+
const __pendingModules__ = new Map()
|
|
70
134
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (id && id.startsWith('/@id/'))
|
|
76
|
-
id = id.slice('/@id/'.length)
|
|
135
|
+
const result = []
|
|
136
|
+
for (const file of files)
|
|
137
|
+
result.push(await cachedRequest(`/@fs/${slash(resolve(file))}`, []))
|
|
138
|
+
return result
|
|
77
139
|
|
|
78
|
-
|
|
79
|
-
|
|
140
|
+
async function directRequest(rawId, callstack) {
|
|
141
|
+
if (builtinModules.includes(rawId))
|
|
142
|
+
return import(rawId)
|
|
143
|
+
|
|
144
|
+
callstack = [...callstack, rawId]
|
|
145
|
+
const request = async(dep) => {
|
|
146
|
+
if (callstack.includes(dep)) {
|
|
147
|
+
throw new Error(`${red('Circular dependency detected')}\nStack:\n${[...callstack, dep].reverse().map((i) => {
|
|
148
|
+
const path = relative(server.config.root, toFilePath(normalizeId(i)))
|
|
149
|
+
return dim(' -> ') + (i === dep ? yellow(path) : path)
|
|
150
|
+
}).join('\n')}\n`)
|
|
151
|
+
}
|
|
152
|
+
return cachedRequest(dep, callstack)
|
|
153
|
+
}
|
|
80
154
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
: slash(join(server.config.root, id.slice(1)))
|
|
155
|
+
const id = normalizeId(rawId)
|
|
156
|
+
const absolute = toFilePath(id)
|
|
84
157
|
|
|
85
158
|
debugRequest(absolute)
|
|
86
159
|
|
|
@@ -89,7 +162,7 @@ async function execute(files, server) {
|
|
|
89
162
|
? `/${absolute}`
|
|
90
163
|
: absolute
|
|
91
164
|
|
|
92
|
-
if (
|
|
165
|
+
if (absolute.includes('/node_modules/'))
|
|
93
166
|
return import(unifiedPath)
|
|
94
167
|
|
|
95
168
|
const result = await server.transformRequest(id, { ssr: true })
|
|
@@ -99,42 +172,50 @@ async function execute(files, server) {
|
|
|
99
172
|
debugTransform(id, result.code)
|
|
100
173
|
|
|
101
174
|
const url = pathToFileURL(unifiedPath)
|
|
102
|
-
|
|
103
175
|
const exports = {}
|
|
104
176
|
|
|
105
177
|
const context = {
|
|
106
178
|
require: createRequire(url),
|
|
107
179
|
__filename: absolute,
|
|
108
180
|
__dirname: dirname(absolute),
|
|
109
|
-
__vite_ssr_import__:
|
|
110
|
-
__vite_ssr_dynamic_import__:
|
|
181
|
+
__vite_ssr_import__: request,
|
|
182
|
+
__vite_ssr_dynamic_import__: request,
|
|
111
183
|
__vite_ssr_exports__: exports,
|
|
112
|
-
__vite_ssr_exportAll__: obj =>
|
|
184
|
+
__vite_ssr_exportAll__: obj => exportAll(exports, obj),
|
|
113
185
|
__vite_ssr_import_meta__: { url },
|
|
114
186
|
}
|
|
115
187
|
|
|
116
|
-
const fn =
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
// prefetch deps
|
|
122
|
-
result.deps.forEach(dep => cachedRequest(dep))
|
|
123
|
-
|
|
188
|
+
const fn = vm.runInThisContext(`async (${Object.keys(context).join(',')}) => { ${result.code} }`, {
|
|
189
|
+
filename: absolute,
|
|
190
|
+
lineOffset: 0,
|
|
191
|
+
})
|
|
124
192
|
await fn(...Object.values(context))
|
|
193
|
+
|
|
125
194
|
return exports
|
|
126
195
|
}
|
|
127
196
|
|
|
128
|
-
function cachedRequest(
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
197
|
+
async function cachedRequest(id, callstack) {
|
|
198
|
+
if (__pendingModules__[id])
|
|
199
|
+
return __pendingModules__[id]
|
|
200
|
+
__pendingModules__[id] = directRequest(id, callstack)
|
|
201
|
+
return await __pendingModules__[id]
|
|
132
202
|
}
|
|
133
203
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
204
|
+
function exportAll(exports, sourceModule) {
|
|
205
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
206
|
+
for (const key in sourceModule) {
|
|
207
|
+
if (key !== 'default') {
|
|
208
|
+
try {
|
|
209
|
+
Object.defineProperty(exports, key, {
|
|
210
|
+
enumerable: true,
|
|
211
|
+
configurable: true,
|
|
212
|
+
get() { return sourceModule[key] },
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
catch (_err) { }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
138
219
|
}
|
|
139
220
|
|
|
140
221
|
function slash(path) {
|
|
@@ -142,7 +223,6 @@ function slash(path) {
|
|
|
142
223
|
}
|
|
143
224
|
|
|
144
225
|
function help() {
|
|
145
|
-
// eslint-disable-next-line no-console
|
|
146
226
|
console.log(`
|
|
147
227
|
Usage:
|
|
148
228
|
$ vite-node [options] [files]
|
|
@@ -150,6 +230,14 @@ Usage:
|
|
|
150
230
|
Options:
|
|
151
231
|
-r, --root <path> ${dim('[string]')} use specified root directory
|
|
152
232
|
-c, --config <file> ${dim('[string]')} use specified config file
|
|
233
|
+
-w, --watch ${dim('[boolean]')} restart on file changes, similar to "nodemon"
|
|
234
|
+
-s, --silent ${dim('[boolean]')} do not emit errors and logs
|
|
153
235
|
--vue ${dim('[boolean]')} support for importing Vue component
|
|
154
236
|
`)
|
|
155
237
|
}
|
|
238
|
+
|
|
239
|
+
function log(...args) {
|
|
240
|
+
if (argv.silent)
|
|
241
|
+
return
|
|
242
|
+
console.log(...args)
|
|
243
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Vite as Node runtime",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite"
|
|
@@ -33,23 +33,23 @@
|
|
|
33
33
|
"bin"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"debug": "^4.3.
|
|
36
|
+
"debug": "^4.3.3",
|
|
37
37
|
"kolorist": "^1.5.0",
|
|
38
38
|
"minimist": "^1.2.5",
|
|
39
39
|
"vite": "^2.6.5"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@antfu/eslint-config": "^0.
|
|
43
|
-
"@antfu/ni": "^0.
|
|
42
|
+
"@antfu/eslint-config": "^0.11.1",
|
|
43
|
+
"@antfu/ni": "^0.11.0",
|
|
44
44
|
"@types/debug": "^4.1.7",
|
|
45
|
-
"@types/node": "^16.
|
|
46
|
-
"@vitejs/plugin-vue": "^1.
|
|
45
|
+
"@types/node": "^16.11.11",
|
|
46
|
+
"@vitejs/plugin-vue": "^1.10.1",
|
|
47
47
|
"bumpp": "^7.1.1",
|
|
48
|
-
"eslint": "^
|
|
49
|
-
"esno": "^0.
|
|
50
|
-
"typescript": "^4.
|
|
48
|
+
"eslint": "^8.3.0",
|
|
49
|
+
"esno": "^0.12.1",
|
|
50
|
+
"typescript": "^4.5.2",
|
|
51
51
|
"uvu": "^0.5.2",
|
|
52
|
-
"vue": "^3.2.
|
|
52
|
+
"vue": "^3.2.23"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": ">=14.0.0"
|