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.
@@ -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
- })