vite 3.2.1 → 3.2.3
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/LICENSE.md +2 -85
- package/dist/client/client.mjs +35 -30
- package/dist/client/client.mjs.map +1 -1
- package/dist/node/chunks/{dep-d29b4e33.js → dep-51c4f80a.js} +2593 -3774
- package/dist/node/chunks/{dep-9055f77d.js → dep-7591464a.js} +1 -1
- package/dist/node/cli.js +5 -5
- package/dist/node/constants.js +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node-cjs/publicUtils.cjs +1 -1
- package/package.json +9 -6
- package/types/customEvent.d.ts +1 -0
- package/src/client/client.ts +0 -593
- package/src/client/env.ts +0 -29
- package/src/client/overlay.ts +0 -208
- package/src/client/tsconfig.json +0 -10
package/src/client/client.ts
DELETED
|
@@ -1,593 +0,0 @@
|
|
|
1
|
-
import type { ErrorPayload, HMRPayload, Update } from 'types/hmrPayload'
|
|
2
|
-
import type { ModuleNamespace, ViteHotContext } from 'types/hot'
|
|
3
|
-
import type { InferCustomEventPayload } from 'types/customEvent'
|
|
4
|
-
import { ErrorOverlay, overlayId } from './overlay'
|
|
5
|
-
// eslint-disable-next-line node/no-missing-import
|
|
6
|
-
import '@vite/env'
|
|
7
|
-
|
|
8
|
-
// injected by the hmr plugin when served
|
|
9
|
-
declare const __BASE__: string
|
|
10
|
-
declare const __SERVER_HOST__: string
|
|
11
|
-
declare const __HMR_PROTOCOL__: string | null
|
|
12
|
-
declare const __HMR_HOSTNAME__: string | null
|
|
13
|
-
declare const __HMR_PORT__: number | null
|
|
14
|
-
declare const __HMR_DIRECT_TARGET__: string
|
|
15
|
-
declare const __HMR_BASE__: string
|
|
16
|
-
declare const __HMR_TIMEOUT__: number
|
|
17
|
-
declare const __HMR_ENABLE_OVERLAY__: boolean
|
|
18
|
-
|
|
19
|
-
console.debug('[vite] connecting...')
|
|
20
|
-
|
|
21
|
-
const importMetaUrl = new URL(import.meta.url)
|
|
22
|
-
|
|
23
|
-
// use server configuration, then fallback to inference
|
|
24
|
-
const serverHost = __SERVER_HOST__
|
|
25
|
-
const socketProtocol =
|
|
26
|
-
__HMR_PROTOCOL__ || (location.protocol === 'https:' ? 'wss' : 'ws')
|
|
27
|
-
const hmrPort = __HMR_PORT__
|
|
28
|
-
const socketHost = `${__HMR_HOSTNAME__ || importMetaUrl.hostname}:${
|
|
29
|
-
hmrPort || importMetaUrl.port
|
|
30
|
-
}${__HMR_BASE__}`
|
|
31
|
-
const directSocketHost = __HMR_DIRECT_TARGET__
|
|
32
|
-
const base = __BASE__ || '/'
|
|
33
|
-
const messageBuffer: string[] = []
|
|
34
|
-
|
|
35
|
-
let socket: WebSocket
|
|
36
|
-
try {
|
|
37
|
-
let fallback: (() => void) | undefined
|
|
38
|
-
// only use fallback when port is inferred to prevent confusion
|
|
39
|
-
if (!hmrPort) {
|
|
40
|
-
fallback = () => {
|
|
41
|
-
// fallback to connecting directly to the hmr server
|
|
42
|
-
// for servers which does not support proxying websocket
|
|
43
|
-
socket = setupWebSocket(socketProtocol, directSocketHost, () => {
|
|
44
|
-
const currentScriptHostURL = new URL(import.meta.url)
|
|
45
|
-
const currentScriptHost =
|
|
46
|
-
currentScriptHostURL.host +
|
|
47
|
-
currentScriptHostURL.pathname.replace(/@vite\/client$/, '')
|
|
48
|
-
console.error(
|
|
49
|
-
'[vite] failed to connect to websocket.\n' +
|
|
50
|
-
'your current setup:\n' +
|
|
51
|
-
` (browser) ${currentScriptHost} <--[HTTP]--> ${serverHost} (server)\n` +
|
|
52
|
-
` (browser) ${socketHost} <--[WebSocket (failing)]--> ${directSocketHost} (server)\n` +
|
|
53
|
-
'Check out your Vite / network configuration and https://vitejs.dev/config/server-options.html#server-hmr .'
|
|
54
|
-
)
|
|
55
|
-
})
|
|
56
|
-
socket.addEventListener(
|
|
57
|
-
'open',
|
|
58
|
-
() => {
|
|
59
|
-
console.info(
|
|
60
|
-
'[vite] Direct websocket connection fallback. Check out https://vitejs.dev/config/server-options.html#server-hmr to remove the previous connection error.'
|
|
61
|
-
)
|
|
62
|
-
},
|
|
63
|
-
{ once: true }
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
socket = setupWebSocket(socketProtocol, socketHost, fallback)
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error(`[vite] failed to connect to websocket (${error}). `)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function setupWebSocket(
|
|
74
|
-
protocol: string,
|
|
75
|
-
hostAndPath: string,
|
|
76
|
-
onCloseWithoutOpen?: () => void
|
|
77
|
-
) {
|
|
78
|
-
const socket = new WebSocket(`${protocol}://${hostAndPath}`, 'vite-hmr')
|
|
79
|
-
let isOpened = false
|
|
80
|
-
|
|
81
|
-
socket.addEventListener(
|
|
82
|
-
'open',
|
|
83
|
-
() => {
|
|
84
|
-
isOpened = true
|
|
85
|
-
},
|
|
86
|
-
{ once: true }
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
// Listen for messages
|
|
90
|
-
socket.addEventListener('message', async ({ data }) => {
|
|
91
|
-
handleMessage(JSON.parse(data))
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
// ping server
|
|
95
|
-
socket.addEventListener('close', async ({ wasClean }) => {
|
|
96
|
-
if (wasClean) return
|
|
97
|
-
|
|
98
|
-
if (!isOpened && onCloseWithoutOpen) {
|
|
99
|
-
onCloseWithoutOpen()
|
|
100
|
-
return
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
console.log(`[vite] server connection lost. polling for restart...`)
|
|
104
|
-
await waitForSuccessfulPing(protocol, hostAndPath)
|
|
105
|
-
location.reload()
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
return socket
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function warnFailedFetch(err: Error, path: string | string[]) {
|
|
112
|
-
if (!err.message.match('fetch')) {
|
|
113
|
-
console.error(err)
|
|
114
|
-
}
|
|
115
|
-
console.error(
|
|
116
|
-
`[hmr] Failed to reload ${path}. ` +
|
|
117
|
-
`This could be due to syntax errors or importing non-existent ` +
|
|
118
|
-
`modules. (see errors above)`
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function cleanUrl(pathname: string): string {
|
|
123
|
-
const url = new URL(pathname, location.toString())
|
|
124
|
-
url.searchParams.delete('direct')
|
|
125
|
-
return url.pathname + url.search
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let isFirstUpdate = true
|
|
129
|
-
const outdatedLinkTags = new WeakSet<HTMLLinkElement>()
|
|
130
|
-
|
|
131
|
-
async function handleMessage(payload: HMRPayload) {
|
|
132
|
-
switch (payload.type) {
|
|
133
|
-
case 'connected':
|
|
134
|
-
console.debug(`[vite] connected.`)
|
|
135
|
-
sendMessageBuffer()
|
|
136
|
-
// proxy(nginx, docker) hmr ws maybe caused timeout,
|
|
137
|
-
// so send ping package let ws keep alive.
|
|
138
|
-
setInterval(() => {
|
|
139
|
-
if (socket.readyState === socket.OPEN) {
|
|
140
|
-
socket.send('{"type":"ping"}')
|
|
141
|
-
}
|
|
142
|
-
}, __HMR_TIMEOUT__)
|
|
143
|
-
break
|
|
144
|
-
case 'update':
|
|
145
|
-
notifyListeners('vite:beforeUpdate', payload)
|
|
146
|
-
// if this is the first update and there's already an error overlay, it
|
|
147
|
-
// means the page opened with existing server compile error and the whole
|
|
148
|
-
// module script failed to load (since one of the nested imports is 500).
|
|
149
|
-
// in this case a normal update won't work and a full reload is needed.
|
|
150
|
-
if (isFirstUpdate && hasErrorOverlay()) {
|
|
151
|
-
window.location.reload()
|
|
152
|
-
return
|
|
153
|
-
} else {
|
|
154
|
-
clearErrorOverlay()
|
|
155
|
-
isFirstUpdate = false
|
|
156
|
-
}
|
|
157
|
-
payload.updates.forEach((update) => {
|
|
158
|
-
if (update.type === 'js-update') {
|
|
159
|
-
queueUpdate(fetchUpdate(update))
|
|
160
|
-
} else {
|
|
161
|
-
// css-update
|
|
162
|
-
// this is only sent when a css file referenced with <link> is updated
|
|
163
|
-
const { path, timestamp } = update
|
|
164
|
-
const searchUrl = cleanUrl(path)
|
|
165
|
-
// can't use querySelector with `[href*=]` here since the link may be
|
|
166
|
-
// using relative paths so we need to use link.href to grab the full
|
|
167
|
-
// URL for the include check.
|
|
168
|
-
const el = Array.from(
|
|
169
|
-
document.querySelectorAll<HTMLLinkElement>('link')
|
|
170
|
-
).find(
|
|
171
|
-
(e) =>
|
|
172
|
-
!outdatedLinkTags.has(e) && cleanUrl(e.href).includes(searchUrl)
|
|
173
|
-
)
|
|
174
|
-
if (el) {
|
|
175
|
-
const newPath = `${base}${searchUrl.slice(1)}${
|
|
176
|
-
searchUrl.includes('?') ? '&' : '?'
|
|
177
|
-
}t=${timestamp}`
|
|
178
|
-
|
|
179
|
-
// rather than swapping the href on the existing tag, we will
|
|
180
|
-
// create a new link tag. Once the new stylesheet has loaded we
|
|
181
|
-
// will remove the existing link tag. This removes a Flash Of
|
|
182
|
-
// Unstyled Content that can occur when swapping out the tag href
|
|
183
|
-
// directly, as the new stylesheet has not yet been loaded.
|
|
184
|
-
const newLinkTag = el.cloneNode() as HTMLLinkElement
|
|
185
|
-
newLinkTag.href = new URL(newPath, el.href).href
|
|
186
|
-
const removeOldEl = () => el.remove()
|
|
187
|
-
newLinkTag.addEventListener('load', removeOldEl)
|
|
188
|
-
newLinkTag.addEventListener('error', removeOldEl)
|
|
189
|
-
outdatedLinkTags.add(el)
|
|
190
|
-
el.after(newLinkTag)
|
|
191
|
-
}
|
|
192
|
-
console.debug(`[vite] css hot updated: ${searchUrl}`)
|
|
193
|
-
}
|
|
194
|
-
})
|
|
195
|
-
break
|
|
196
|
-
case 'custom': {
|
|
197
|
-
notifyListeners(payload.event, payload.data)
|
|
198
|
-
break
|
|
199
|
-
}
|
|
200
|
-
case 'full-reload':
|
|
201
|
-
notifyListeners('vite:beforeFullReload', payload)
|
|
202
|
-
if (payload.path && payload.path.endsWith('.html')) {
|
|
203
|
-
// if html file is edited, only reload the page if the browser is
|
|
204
|
-
// currently on that page.
|
|
205
|
-
const pagePath = decodeURI(location.pathname)
|
|
206
|
-
const payloadPath = base + payload.path.slice(1)
|
|
207
|
-
if (
|
|
208
|
-
pagePath === payloadPath ||
|
|
209
|
-
payload.path === '/index.html' ||
|
|
210
|
-
(pagePath.endsWith('/') && pagePath + 'index.html' === payloadPath)
|
|
211
|
-
) {
|
|
212
|
-
location.reload()
|
|
213
|
-
}
|
|
214
|
-
return
|
|
215
|
-
} else {
|
|
216
|
-
location.reload()
|
|
217
|
-
}
|
|
218
|
-
break
|
|
219
|
-
case 'prune':
|
|
220
|
-
notifyListeners('vite:beforePrune', payload)
|
|
221
|
-
// After an HMR update, some modules are no longer imported on the page
|
|
222
|
-
// but they may have left behind side effects that need to be cleaned up
|
|
223
|
-
// (.e.g style injections)
|
|
224
|
-
// TODO Trigger their dispose callbacks.
|
|
225
|
-
payload.paths.forEach((path) => {
|
|
226
|
-
const fn = pruneMap.get(path)
|
|
227
|
-
if (fn) {
|
|
228
|
-
fn(dataMap.get(path))
|
|
229
|
-
}
|
|
230
|
-
})
|
|
231
|
-
break
|
|
232
|
-
case 'error': {
|
|
233
|
-
notifyListeners('vite:error', payload)
|
|
234
|
-
const err = payload.err
|
|
235
|
-
if (enableOverlay) {
|
|
236
|
-
createErrorOverlay(err)
|
|
237
|
-
} else {
|
|
238
|
-
console.error(
|
|
239
|
-
`[vite] Internal Server Error\n${err.message}\n${err.stack}`
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
break
|
|
243
|
-
}
|
|
244
|
-
default: {
|
|
245
|
-
const check: never = payload
|
|
246
|
-
return check
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function notifyListeners<T extends string>(
|
|
252
|
-
event: T,
|
|
253
|
-
data: InferCustomEventPayload<T>
|
|
254
|
-
): void
|
|
255
|
-
function notifyListeners(event: string, data: any): void {
|
|
256
|
-
const cbs = customListenersMap.get(event)
|
|
257
|
-
if (cbs) {
|
|
258
|
-
cbs.forEach((cb) => cb(data))
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const enableOverlay = __HMR_ENABLE_OVERLAY__
|
|
263
|
-
|
|
264
|
-
function createErrorOverlay(err: ErrorPayload['err']) {
|
|
265
|
-
if (!enableOverlay) return
|
|
266
|
-
clearErrorOverlay()
|
|
267
|
-
document.body.appendChild(new ErrorOverlay(err))
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function clearErrorOverlay() {
|
|
271
|
-
document
|
|
272
|
-
.querySelectorAll(overlayId)
|
|
273
|
-
.forEach((n) => (n as ErrorOverlay).close())
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function hasErrorOverlay() {
|
|
277
|
-
return document.querySelectorAll(overlayId).length
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
let pending = false
|
|
281
|
-
let queued: Promise<(() => void) | undefined>[] = []
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* buffer multiple hot updates triggered by the same src change
|
|
285
|
-
* so that they are invoked in the same order they were sent.
|
|
286
|
-
* (otherwise the order may be inconsistent because of the http request round trip)
|
|
287
|
-
*/
|
|
288
|
-
async function queueUpdate(p: Promise<(() => void) | undefined>) {
|
|
289
|
-
queued.push(p)
|
|
290
|
-
if (!pending) {
|
|
291
|
-
pending = true
|
|
292
|
-
await Promise.resolve()
|
|
293
|
-
pending = false
|
|
294
|
-
const loading = [...queued]
|
|
295
|
-
queued = []
|
|
296
|
-
;(await Promise.all(loading)).forEach((fn) => fn && fn())
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
async function waitForSuccessfulPing(
|
|
301
|
-
socketProtocol: string,
|
|
302
|
-
hostAndPath: string,
|
|
303
|
-
ms = 1000
|
|
304
|
-
) {
|
|
305
|
-
const pingHostProtocol = socketProtocol === 'wss' ? 'https' : 'http'
|
|
306
|
-
|
|
307
|
-
// eslint-disable-next-line no-constant-condition
|
|
308
|
-
while (true) {
|
|
309
|
-
try {
|
|
310
|
-
// A fetch on a websocket URL will return a successful promise with status 400,
|
|
311
|
-
// but will reject a networking error.
|
|
312
|
-
// When running on middleware mode, it returns status 426, and an cors error happens if mode is not no-cors
|
|
313
|
-
await fetch(`${pingHostProtocol}://${hostAndPath}`, {
|
|
314
|
-
mode: 'no-cors'
|
|
315
|
-
})
|
|
316
|
-
break
|
|
317
|
-
} catch (e) {
|
|
318
|
-
// wait ms before attempting to ping again
|
|
319
|
-
await new Promise((resolve) => setTimeout(resolve, ms))
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// https://wicg.github.io/construct-stylesheets
|
|
325
|
-
const supportsConstructedSheet = (() => {
|
|
326
|
-
// TODO: re-enable this try block once Chrome fixes the performance of
|
|
327
|
-
// rule insertion in really big stylesheets
|
|
328
|
-
// try {
|
|
329
|
-
// new CSSStyleSheet()
|
|
330
|
-
// return true
|
|
331
|
-
// } catch (e) {}
|
|
332
|
-
return false
|
|
333
|
-
})()
|
|
334
|
-
|
|
335
|
-
const sheetsMap = new Map<
|
|
336
|
-
string,
|
|
337
|
-
HTMLStyleElement | CSSStyleSheet | undefined
|
|
338
|
-
>()
|
|
339
|
-
|
|
340
|
-
export function updateStyle(id: string, content: string): void {
|
|
341
|
-
let style = sheetsMap.get(id)
|
|
342
|
-
if (supportsConstructedSheet && !content.includes('@import')) {
|
|
343
|
-
if (style && !(style instanceof CSSStyleSheet)) {
|
|
344
|
-
removeStyle(id)
|
|
345
|
-
style = undefined
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
if (!style) {
|
|
349
|
-
style = new CSSStyleSheet()
|
|
350
|
-
// @ts-expect-error: using experimental API
|
|
351
|
-
style.replaceSync(content)
|
|
352
|
-
// @ts-expect-error: using experimental API
|
|
353
|
-
document.adoptedStyleSheets = [...document.adoptedStyleSheets, style]
|
|
354
|
-
} else {
|
|
355
|
-
// @ts-expect-error: using experimental API
|
|
356
|
-
style.replaceSync(content)
|
|
357
|
-
}
|
|
358
|
-
} else {
|
|
359
|
-
if (style && !(style instanceof HTMLStyleElement)) {
|
|
360
|
-
removeStyle(id)
|
|
361
|
-
style = undefined
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (!style) {
|
|
365
|
-
style = document.createElement('style')
|
|
366
|
-
style.setAttribute('type', 'text/css')
|
|
367
|
-
style.setAttribute('data-vite-dev-id', id)
|
|
368
|
-
style.innerHTML = content
|
|
369
|
-
document.head.appendChild(style)
|
|
370
|
-
} else {
|
|
371
|
-
style.innerHTML = content
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
sheetsMap.set(id, style)
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
export function removeStyle(id: string): void {
|
|
378
|
-
const style = sheetsMap.get(id)
|
|
379
|
-
if (style) {
|
|
380
|
-
if (style instanceof CSSStyleSheet) {
|
|
381
|
-
// @ts-expect-error: using experimental API
|
|
382
|
-
document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
|
|
383
|
-
(s: CSSStyleSheet) => s !== style
|
|
384
|
-
)
|
|
385
|
-
} else {
|
|
386
|
-
document.head.removeChild(style)
|
|
387
|
-
}
|
|
388
|
-
sheetsMap.delete(id)
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
async function fetchUpdate({
|
|
393
|
-
path,
|
|
394
|
-
acceptedPath,
|
|
395
|
-
timestamp,
|
|
396
|
-
explicitImportRequired
|
|
397
|
-
}: Update) {
|
|
398
|
-
const mod = hotModulesMap.get(path)
|
|
399
|
-
if (!mod) {
|
|
400
|
-
// In a code-splitting project,
|
|
401
|
-
// it is common that the hot-updating module is not loaded yet.
|
|
402
|
-
// https://github.com/vitejs/vite/issues/721
|
|
403
|
-
return
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const moduleMap = new Map<string, ModuleNamespace>()
|
|
407
|
-
const isSelfUpdate = path === acceptedPath
|
|
408
|
-
|
|
409
|
-
// determine the qualified callbacks before we re-import the modules
|
|
410
|
-
const qualifiedCallbacks = mod.callbacks.filter(({ deps }) =>
|
|
411
|
-
deps.includes(acceptedPath)
|
|
412
|
-
)
|
|
413
|
-
|
|
414
|
-
if (isSelfUpdate || qualifiedCallbacks.length > 0) {
|
|
415
|
-
const dep = acceptedPath
|
|
416
|
-
const disposer = disposeMap.get(dep)
|
|
417
|
-
if (disposer) await disposer(dataMap.get(dep))
|
|
418
|
-
const [path, query] = dep.split(`?`)
|
|
419
|
-
try {
|
|
420
|
-
const newMod: ModuleNamespace = await import(
|
|
421
|
-
/* @vite-ignore */
|
|
422
|
-
base +
|
|
423
|
-
path.slice(1) +
|
|
424
|
-
`?${explicitImportRequired ? 'import&' : ''}t=${timestamp}${
|
|
425
|
-
query ? `&${query}` : ''
|
|
426
|
-
}`
|
|
427
|
-
)
|
|
428
|
-
moduleMap.set(dep, newMod)
|
|
429
|
-
} catch (e) {
|
|
430
|
-
warnFailedFetch(e, dep)
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
return () => {
|
|
435
|
-
for (const { deps, fn } of qualifiedCallbacks) {
|
|
436
|
-
fn(deps.map((dep) => moduleMap.get(dep)))
|
|
437
|
-
}
|
|
438
|
-
const loggedPath = isSelfUpdate ? path : `${acceptedPath} via ${path}`
|
|
439
|
-
console.debug(`[vite] hot updated: ${loggedPath}`)
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
function sendMessageBuffer() {
|
|
444
|
-
if (socket.readyState === 1) {
|
|
445
|
-
messageBuffer.forEach((msg) => socket.send(msg))
|
|
446
|
-
messageBuffer.length = 0
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
interface HotModule {
|
|
451
|
-
id: string
|
|
452
|
-
callbacks: HotCallback[]
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
interface HotCallback {
|
|
456
|
-
// the dependencies must be fetchable paths
|
|
457
|
-
deps: string[]
|
|
458
|
-
fn: (modules: Array<ModuleNamespace | undefined>) => void
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
type CustomListenersMap = Map<string, ((data: any) => void)[]>
|
|
462
|
-
|
|
463
|
-
const hotModulesMap = new Map<string, HotModule>()
|
|
464
|
-
const disposeMap = new Map<string, (data: any) => void | Promise<void>>()
|
|
465
|
-
const pruneMap = new Map<string, (data: any) => void | Promise<void>>()
|
|
466
|
-
const dataMap = new Map<string, any>()
|
|
467
|
-
const customListenersMap: CustomListenersMap = new Map()
|
|
468
|
-
const ctxToListenersMap = new Map<string, CustomListenersMap>()
|
|
469
|
-
|
|
470
|
-
export function createHotContext(ownerPath: string): ViteHotContext {
|
|
471
|
-
if (!dataMap.has(ownerPath)) {
|
|
472
|
-
dataMap.set(ownerPath, {})
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// when a file is hot updated, a new context is created
|
|
476
|
-
// clear its stale callbacks
|
|
477
|
-
const mod = hotModulesMap.get(ownerPath)
|
|
478
|
-
if (mod) {
|
|
479
|
-
mod.callbacks = []
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// clear stale custom event listeners
|
|
483
|
-
const staleListeners = ctxToListenersMap.get(ownerPath)
|
|
484
|
-
if (staleListeners) {
|
|
485
|
-
for (const [event, staleFns] of staleListeners) {
|
|
486
|
-
const listeners = customListenersMap.get(event)
|
|
487
|
-
if (listeners) {
|
|
488
|
-
customListenersMap.set(
|
|
489
|
-
event,
|
|
490
|
-
listeners.filter((l) => !staleFns.includes(l))
|
|
491
|
-
)
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
const newListeners: CustomListenersMap = new Map()
|
|
497
|
-
ctxToListenersMap.set(ownerPath, newListeners)
|
|
498
|
-
|
|
499
|
-
function acceptDeps(deps: string[], callback: HotCallback['fn'] = () => {}) {
|
|
500
|
-
const mod: HotModule = hotModulesMap.get(ownerPath) || {
|
|
501
|
-
id: ownerPath,
|
|
502
|
-
callbacks: []
|
|
503
|
-
}
|
|
504
|
-
mod.callbacks.push({
|
|
505
|
-
deps,
|
|
506
|
-
fn: callback
|
|
507
|
-
})
|
|
508
|
-
hotModulesMap.set(ownerPath, mod)
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
const hot: ViteHotContext = {
|
|
512
|
-
get data() {
|
|
513
|
-
return dataMap.get(ownerPath)
|
|
514
|
-
},
|
|
515
|
-
|
|
516
|
-
accept(deps?: any, callback?: any) {
|
|
517
|
-
if (typeof deps === 'function' || !deps) {
|
|
518
|
-
// self-accept: hot.accept(() => {})
|
|
519
|
-
acceptDeps([ownerPath], ([mod]) => deps && deps(mod))
|
|
520
|
-
} else if (typeof deps === 'string') {
|
|
521
|
-
// explicit deps
|
|
522
|
-
acceptDeps([deps], ([mod]) => callback && callback(mod))
|
|
523
|
-
} else if (Array.isArray(deps)) {
|
|
524
|
-
acceptDeps(deps, callback)
|
|
525
|
-
} else {
|
|
526
|
-
throw new Error(`invalid hot.accept() usage.`)
|
|
527
|
-
}
|
|
528
|
-
},
|
|
529
|
-
|
|
530
|
-
// export names (first arg) are irrelevant on the client side, they're
|
|
531
|
-
// extracted in the server for propagation
|
|
532
|
-
acceptExports(_: string | readonly string[], callback?: any) {
|
|
533
|
-
acceptDeps([ownerPath], callback && (([mod]) => callback(mod)))
|
|
534
|
-
},
|
|
535
|
-
|
|
536
|
-
dispose(cb) {
|
|
537
|
-
disposeMap.set(ownerPath, cb)
|
|
538
|
-
},
|
|
539
|
-
|
|
540
|
-
// @ts-expect-error untyped
|
|
541
|
-
prune(cb: (data: any) => void) {
|
|
542
|
-
pruneMap.set(ownerPath, cb)
|
|
543
|
-
},
|
|
544
|
-
|
|
545
|
-
// TODO
|
|
546
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
547
|
-
decline() {},
|
|
548
|
-
|
|
549
|
-
// tell the server to re-perform hmr propagation from this module as root
|
|
550
|
-
invalidate() {
|
|
551
|
-
notifyListeners('vite:invalidate', { path: ownerPath })
|
|
552
|
-
this.send('vite:invalidate', { path: ownerPath })
|
|
553
|
-
},
|
|
554
|
-
|
|
555
|
-
// custom events
|
|
556
|
-
on(event, cb) {
|
|
557
|
-
const addToMap = (map: Map<string, any[]>) => {
|
|
558
|
-
const existing = map.get(event) || []
|
|
559
|
-
existing.push(cb)
|
|
560
|
-
map.set(event, existing)
|
|
561
|
-
}
|
|
562
|
-
addToMap(customListenersMap)
|
|
563
|
-
addToMap(newListeners)
|
|
564
|
-
},
|
|
565
|
-
|
|
566
|
-
send(event, data) {
|
|
567
|
-
messageBuffer.push(JSON.stringify({ type: 'custom', event, data }))
|
|
568
|
-
sendMessageBuffer()
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
return hot
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* urls here are dynamic import() urls that couldn't be statically analyzed
|
|
577
|
-
*/
|
|
578
|
-
export function injectQuery(url: string, queryToInject: string): string {
|
|
579
|
-
// skip urls that won't be handled by vite
|
|
580
|
-
if (!url.startsWith('.') && !url.startsWith('/')) {
|
|
581
|
-
return url
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
// can't use pathname from URL since it may be relative like ../
|
|
585
|
-
const pathname = url.replace(/#.*$/, '').replace(/\?.*$/, '')
|
|
586
|
-
const { search, hash } = new URL(url, 'http://vitejs.dev')
|
|
587
|
-
|
|
588
|
-
return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${
|
|
589
|
-
hash || ''
|
|
590
|
-
}`
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
export { ErrorOverlay }
|
package/src/client/env.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
declare const __MODE__: string
|
|
2
|
-
declare const __DEFINES__: Record<string, any>
|
|
3
|
-
|
|
4
|
-
const context = (() => {
|
|
5
|
-
if (typeof globalThis !== 'undefined') {
|
|
6
|
-
return globalThis
|
|
7
|
-
} else if (typeof self !== 'undefined') {
|
|
8
|
-
return self
|
|
9
|
-
} else if (typeof window !== 'undefined') {
|
|
10
|
-
return window
|
|
11
|
-
} else {
|
|
12
|
-
return Function('return this')()
|
|
13
|
-
}
|
|
14
|
-
})()
|
|
15
|
-
|
|
16
|
-
// assign defines
|
|
17
|
-
const defines = __DEFINES__
|
|
18
|
-
Object.keys(defines).forEach((key) => {
|
|
19
|
-
const segments = key.split('.')
|
|
20
|
-
let target = context
|
|
21
|
-
for (let i = 0; i < segments.length; i++) {
|
|
22
|
-
const segment = segments[i]
|
|
23
|
-
if (i === segments.length - 1) {
|
|
24
|
-
target[segment] = defines[key]
|
|
25
|
-
} else {
|
|
26
|
-
target = target[segment] || (target[segment] = {})
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
})
|