vite 3.0.0-alpha.13 → 3.0.0-alpha.14

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,5 +1,5 @@
1
1
  import type { ErrorPayload, HMRPayload, Update } from 'types/hmrPayload'
2
- import type { ViteHotContext } from 'types/hot'
2
+ import type { ModuleNamespace, ViteHotContext } from 'types/hot'
3
3
  import type { InferCustomEventPayload } from 'types/customEvent'
4
4
  import { ErrorOverlay, overlayId } from './overlay'
5
5
  // eslint-disable-next-line node/no-missing-import
@@ -7,24 +7,70 @@ import '@vite/env'
7
7
 
8
8
  // injected by the hmr plugin when served
9
9
  declare const __BASE__: string
10
- declare const __HMR_PROTOCOL__: string
11
- declare const __HMR_HOSTNAME__: string
12
- declare const __HMR_PORT__: string
10
+ declare const __HMR_PROTOCOL__: string | null
11
+ declare const __HMR_HOSTNAME__: string | null
12
+ declare const __HMR_PORT__: string | null
13
+ declare const __HMR_DIRECT_TARGET__: string
14
+ declare const __HMR_BASE__: string
13
15
  declare const __HMR_TIMEOUT__: number
14
16
  declare const __HMR_ENABLE_OVERLAY__: boolean
15
17
 
16
18
  console.debug('[vite] connecting...')
17
19
 
20
+ const importMetaUrl = new URL(import.meta.url)
21
+
18
22
  // use server configuration, then fallback to inference
19
23
  const socketProtocol =
20
24
  __HMR_PROTOCOL__ || (location.protocol === 'https:' ? 'wss' : 'ws')
21
- const socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`
25
+ const hmrPort = __HMR_PORT__
26
+ const socketHost = `${__HMR_HOSTNAME__ || importMetaUrl.hostname}:${
27
+ hmrPort || importMetaUrl.port
28
+ }${__HMR_BASE__}`
29
+ const directSocketHost = __HMR_DIRECT_TARGET__
22
30
  const base = __BASE__ || '/'
23
31
  const messageBuffer: string[] = []
24
32
 
25
33
  let socket: WebSocket
26
34
  try {
27
- socket = new WebSocket(`${socketProtocol}://${socketHost}`, 'vite-hmr')
35
+ let fallback: (() => void) | undefined
36
+ // only use fallback when port is inferred to prevent confusion
37
+ if (!hmrPort) {
38
+ fallback = () => {
39
+ // fallback to connecting directly to the hmr server
40
+ // for servers which does not support proxying websocket
41
+ socket = setupWebSocket(socketProtocol, directSocketHost)
42
+ socket.addEventListener(
43
+ 'open',
44
+ () => {
45
+ console.info(
46
+ '[vite] Direct websocket connection fallback. Check out https://vitejs.dev/config/server-options.html#server-hmr to remove the previous connection error.'
47
+ )
48
+ },
49
+ { once: true }
50
+ )
51
+ }
52
+ }
53
+
54
+ socket = setupWebSocket(socketProtocol, socketHost, fallback)
55
+ } catch (error) {
56
+ console.error(`[vite] failed to connect to websocket (${error}). `)
57
+ }
58
+
59
+ function setupWebSocket(
60
+ protocol: string,
61
+ hostAndPath: string,
62
+ onCloseWithoutOpen?: () => void
63
+ ) {
64
+ const socket = new WebSocket(`${protocol}://${hostAndPath}`, 'vite-hmr')
65
+ let isOpened = false
66
+
67
+ socket.addEventListener(
68
+ 'open',
69
+ () => {
70
+ isOpened = true
71
+ },
72
+ { once: true }
73
+ )
28
74
 
29
75
  // Listen for messages
30
76
  socket.addEventListener('message', async ({ data }) => {
@@ -34,12 +80,18 @@ try {
34
80
  // ping server
35
81
  socket.addEventListener('close', async ({ wasClean }) => {
36
82
  if (wasClean) return
83
+
84
+ if (!isOpened && onCloseWithoutOpen) {
85
+ onCloseWithoutOpen()
86
+ return
87
+ }
88
+
37
89
  console.log(`[vite] server connection lost. polling for restart...`)
38
- await waitForSuccessfulPing()
90
+ await waitForSuccessfulPing(hostAndPath)
39
91
  location.reload()
40
92
  })
41
- } catch (error) {
42
- console.error(`[vite] failed to connect to websocket (${error}). `)
93
+
94
+ return socket
43
95
  }
44
96
 
45
97
  function warnFailedFetch(err: Error, path: string | string[]) {
@@ -222,13 +274,13 @@ async function queueUpdate(p: Promise<(() => void) | undefined>) {
222
274
  }
223
275
  }
224
276
 
225
- async function waitForSuccessfulPing(ms = 1000) {
277
+ async function waitForSuccessfulPing(hostAndPath: string, ms = 1000) {
226
278
  // eslint-disable-next-line no-constant-condition
227
279
  while (true) {
228
280
  try {
229
281
  // A fetch on a websocket URL will return a successful promise with status 400,
230
282
  // but will reject a networking error.
231
- await fetch(`${location.protocol}//${socketHost}`)
283
+ await fetch(`${location.protocol}//${hostAndPath}`)
232
284
  break
233
285
  } catch (e) {
234
286
  // wait ms before attempting to ping again
@@ -248,7 +300,10 @@ const supportsConstructedSheet = (() => {
248
300
  return false
249
301
  })()
250
302
 
251
- const sheetsMap = new Map()
303
+ const sheetsMap = new Map<
304
+ string,
305
+ HTMLStyleElement | CSSStyleSheet | undefined
306
+ >()
252
307
 
253
308
  export function updateStyle(id: string, content: string): void {
254
309
  let style = sheetsMap.get(id)
@@ -260,10 +315,12 @@ export function updateStyle(id: string, content: string): void {
260
315
 
261
316
  if (!style) {
262
317
  style = new CSSStyleSheet()
318
+ // @ts-expect-error: using experimental API
263
319
  style.replaceSync(content)
264
320
  // @ts-expect-error: using experimental API
265
321
  document.adoptedStyleSheets = [...document.adoptedStyleSheets, style]
266
322
  } else {
323
+ // @ts-expect-error: using experimental API
267
324
  style.replaceSync(content)
268
325
  }
269
326
  } else {
@@ -308,7 +365,7 @@ async function fetchUpdate({ path, acceptedPath, timestamp }: Update) {
308
365
  return
309
366
  }
310
367
 
311
- const moduleMap = new Map()
368
+ const moduleMap = new Map<string, ModuleNamespace>()
312
369
  const isSelfUpdate = path === acceptedPath
313
370
 
314
371
  // make sure we only import each dep once
@@ -338,7 +395,7 @@ async function fetchUpdate({ path, acceptedPath, timestamp }: Update) {
338
395
  if (disposer) await disposer(dataMap.get(dep))
339
396
  const [path, query] = dep.split(`?`)
340
397
  try {
341
- const newMod = await import(
398
+ const newMod: ModuleNamespace = await import(
342
399
  /* @vite-ignore */
343
400
  base +
344
401
  path.slice(1) +
@@ -375,18 +432,17 @@ interface HotModule {
375
432
  interface HotCallback {
376
433
  // the dependencies must be fetchable paths
377
434
  deps: string[]
378
- fn: (modules: object[]) => void
435
+ fn: (modules: Array<ModuleNamespace | undefined>) => void
379
436
  }
380
437
 
438
+ type CustomListenersMap = Map<string, ((data: any) => void)[]>
439
+
381
440
  const hotModulesMap = new Map<string, HotModule>()
382
441
  const disposeMap = new Map<string, (data: any) => void | Promise<void>>()
383
442
  const pruneMap = new Map<string, (data: any) => void | Promise<void>>()
384
443
  const dataMap = new Map<string, any>()
385
- const customListenersMap = new Map<string, ((data: any) => void)[]>()
386
- const ctxToListenersMap = new Map<
387
- string,
388
- Map<string, ((data: any) => void)[]>
389
- >()
444
+ const customListenersMap: CustomListenersMap = new Map()
445
+ const ctxToListenersMap = new Map<string, CustomListenersMap>()
390
446
 
391
447
  export function createHotContext(ownerPath: string): ViteHotContext {
392
448
  if (!dataMap.has(ownerPath)) {
@@ -414,7 +470,7 @@ export function createHotContext(ownerPath: string): ViteHotContext {
414
470
  }
415
471
  }
416
472
 
417
- const newListeners = new Map()
473
+ const newListeners: CustomListenersMap = new Map()
418
474
  ctxToListenersMap.set(ownerPath, newListeners)
419
475
 
420
476
  function acceptDeps(deps: string[], callback: HotCallback['fn'] = () => {}) {
@@ -448,6 +504,12 @@ export function createHotContext(ownerPath: string): ViteHotContext {
448
504
  }
449
505
  },
450
506
 
507
+ // export names (first arg) are irrelevant on the client side, they're
508
+ // extracted in the server for propagation
509
+ acceptExports(_: string | readonly string[], callback?: any) {
510
+ acceptDeps([ownerPath], callback && (([mod]) => callback(mod)))
511
+ },
512
+
451
513
  dispose(cb) {
452
514
  disposeMap.set(ownerPath, cb)
453
515
  },
@@ -28,8 +28,8 @@ THE SOFTWARE.
28
28
  */
29
29
  /// <reference types="node" />
30
30
 
31
- import type * as fs from 'fs'
32
- import { EventEmitter } from 'events'
31
+ import type * as fs from 'node:fs'
32
+ import { EventEmitter } from 'node:events'
33
33
  import type { Matcher } from './anymatch'
34
34
 
35
35
  export class FSWatcher extends EventEmitter implements fs.FSWatcher {
@@ -8,7 +8,7 @@
8
8
  // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
9
9
 
10
10
  /// <reference types="node" />
11
- import * as http from 'http'
11
+ import * as http from 'node:http'
12
12
 
13
13
  export namespace Connect {
14
14
  export type ServerHandle = HandleFunction | http.Server
package/types/hot.d.ts CHANGED
@@ -1,12 +1,26 @@
1
1
  import type { InferCustomEventPayload } from './customEvent'
2
2
 
3
+ export type ModuleNamespace = Record<string, any> & {
4
+ [Symbol.toStringTag]: 'Module'
5
+ }
6
+
3
7
  export interface ViteHotContext {
4
8
  readonly data: any
5
9
 
6
10
  accept(): void
7
- accept(cb: (mod: any) => void): void
8
- accept(dep: string, cb: (mod: any) => void): void
9
- accept(deps: readonly string[], cb: (mods: any[]) => void): void
11
+ accept(cb: (mod: ModuleNamespace | undefined) => void): void
12
+ accept(dep: string, cb: (mod: ModuleNamespace | undefined) => void): void
13
+ accept(
14
+ deps: readonly string[],
15
+ cb: (mods: Array<ModuleNamespace | undefined>) => void
16
+ ): void
17
+
18
+ acceptExports(exportNames: string | readonly string[]): void
19
+ acceptExports(
20
+ exportNames: string | readonly string[],
21
+ cb: (mod: ModuleNamespace | undefined) => void
22
+ ): void
23
+
10
24
  dispose(cb: (data: any) => void): void
11
25
  decline(): void
12
26
  invalidate(): void
@@ -13,11 +13,11 @@
13
13
 
14
14
  /// <reference types="node" />
15
15
 
16
- import type * as net from 'net'
17
- import type * as http from 'http'
18
- import * as events from 'events'
19
- import type * as url from 'url'
20
- import type * as stream from 'stream'
16
+ import type * as net from 'node:net'
17
+ import type * as http from 'node:http'
18
+ import * as events from 'node:events'
19
+ import type * as url from 'node:url'
20
+ import type * as stream from 'node:stream'
21
21
 
22
22
  export namespace HttpProxy {
23
23
  export type ProxyTarget = ProxyTargetUrl | ProxyTargetDetailed
package/types/ws.d.ts CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  /// <reference types="node" />
17
17
 
18
- import { EventEmitter } from 'events'
18
+ import { EventEmitter } from 'node:events'
19
19
  import type {
20
20
  Agent,
21
21
  ClientRequest,
@@ -23,12 +23,12 @@ import type {
23
23
  Server as HTTPServer,
24
24
  IncomingMessage,
25
25
  OutgoingHttpHeaders
26
- } from 'http'
27
- import type { Server as HTTPSServer } from 'https'
28
- import type { Duplex, DuplexOptions } from 'stream'
26
+ } from 'node:http'
27
+ import type { Server as HTTPSServer } from 'node:https'
28
+ import type { Duplex, DuplexOptions } from 'node:stream'
29
29
  import type { SecureContextOptions } from 'tls'
30
- import type { URL } from 'url'
31
- import type { ZlibOptions } from 'zlib'
30
+ import type { URL } from 'node:url'
31
+ import type { ZlibOptions } from 'node:zlib'
32
32
 
33
33
  // WebSocket socket.
34
34
  declare class WebSocket extends EventEmitter {