[vite源碼解析]client篇

從服務(wù)端我們了解到是接住websocket與客戶端進(jìn)行通信酝枢,下面我們來看一下客戶端的代碼:

第1步

初始化websocket實(shí)例,socket協(xié)議以來當(dāng)前的協(xié)議,如果是https那就使用wss,否則使用ws。子協(xié)議名稱使用vite-hmr

// packages/vite/src/client/client.ts

const socketProtocol =
  __HMR_PROTOCOL__ || (location.protocol === 'https:' ? 'wss' : 'ws')
const socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`
const socket = new WebSocket(`${socketProtocol}://${socketHost}`, 'vite-hmr')
const base = __BASE__ || '/'

第2步

添加socket消息監(jiān)聽事件质礼,消息使用JSON.parse解析

// packages/vite/src/client/client.ts

socket.addEventListener('message', async ({ data }) => {
  handleMessage(JSON.parse(data))
})

async function handleMessage(payload: HMRPayload) {
  switch (payload.type) {
    case 'connected':
      console.log(`[vite] connected.`)
      // proxy(nginx, docker) hmr ws maybe caused timeout,
      // so send ping package let ws keep alive.
      setInterval(() => socket.send('ping'), __HMR_TIMEOUT__)
      break
    case 'update':
      notifyListeners('vite:beforeUpdate', payload)
      // if this is the first update and there's already an error overlay, it
      // means the page opened with existing server compile error and the whole
      // module script failed to load (since one of the nested imports is 500).
      // in this case a normal update won't work and a full reload is needed.
      if (isFirstUpdate && hasErrorOverlay()) {
        window.location.reload()
        return
      } else {
        clearErrorOverlay()
        isFirstUpdate = false
      }
      payload.updates.forEach((update) => {
        if (update.type === 'js-update') {
          queueUpdate(fetchUpdate(update))
        } else {
          // css-update
          // this is only sent when a css file referenced with <link> is updated
          let { path, timestamp } = update
          path = path.replace(/\?.*/, '')
          // can't use querySelector with `[href*=]` here since the link may be
          // using relative paths so we need to use link.href to grab the full
          // URL for the include check.
          const el = (
            [].slice.call(
              document.querySelectorAll(`link`)
            ) as HTMLLinkElement[]
          ).find((e) => e.href.includes(path))
          if (el) {
            const newPath = `${path}${
              path.includes('?') ? '&' : '?'
            }t=${timestamp}`
            el.href = new URL(newPath, el.href).href
          }
          console.log(`[vite] css hot updated: ${path}`)
        }
      })
      break
    case 'custom': {
      notifyListeners(payload.event as CustomEventName<any>, payload.data)
      break
    }
    case 'full-reload':
      notifyListeners('vite:beforeFullReload', payload)
      if (payload.path && payload.path.endsWith('.html')) {
        // if html file is edited, only reload the page if the browser is
        // currently on that page.
        const pagePath = location.pathname
        const payloadPath = base + payload.path.slice(1)
        if (
          pagePath === payloadPath ||
          (pagePath.endsWith('/') && pagePath + 'index.html' === payloadPath)
        ) {
          location.reload()
        }
        return
      } else {
        location.reload()
      }
      break
    case 'prune':
      notifyListeners('vite:beforePrune', payload)
      // After an HMR update, some modules are no longer imported on the page
      // but they may have left behind side effects that need to be cleaned up
      // (.e.g style injections)
      // TODO Trigger their dispose callbacks.
      payload.paths.forEach((path) => {
        const fn = pruneMap.get(path)
        if (fn) {
          fn(dataMap.get(path))
        }
      })
      break
    case 'error': {
      notifyListeners('vite:error', payload)
      const err = payload.err
      if (enableOverlay) {
        createErrorOverlay(err)
      } else {
        console.error(
          `[vite] Internal Server Error\n${err.message}\n${err.stack}`
        )
      }
      break
    }
    default: {
      const check: never = payload
      return check
    }
  }
}

針對(duì)收到不同的通信類型來張表格梳理下:

類型 說明
connected 提示連接中,等待一段時(shí)間后發(fā)送ping
update 更新分為js update和cssupdate织阳, 遍歷payload.updates的所有文件
custom
full-reload location reload
prune 裁剪:payload.paths的每個(gè)路徑都拿取剪裁函數(shù)執(zhí)行
error 獲取錯(cuò)誤并借助console.error展示
default 返回payload
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末眶蕉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子唧躲,更是在濱河造成了極大的恐慌造挽,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弄痹,死亡現(xiàn)場(chǎng)離奇詭異饭入,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)肛真,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門谐丢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚓让,你說我怎么就攤上這事乾忱。” “怎么了历极?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵窄瘟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我执解,道長(zhǎng)寞肖,這世上最難降的妖魔是什么纲酗? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任衰腌,我火速辦了婚禮,結(jié)果婚禮上觅赊,老公的妹妹穿的比我還像新娘右蕊。我一直安慰自己,他們只是感情好吮螺,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布饶囚。 她就那樣靜靜地躺著帕翻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪萝风。 梳的紋絲不亂的頭發(fā)上嘀掸,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音规惰,去河邊找鬼睬塌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛歇万,可吹牛的內(nèi)容都是我干的揩晴。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼贪磺,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼硫兰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寒锚,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤劫映,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后刹前,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苏研,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年腮郊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摹蘑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡轧飞,死狀恐怖衅鹿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情过咬,我是刑警寧澤大渤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站掸绞,受9級(jí)特大地震影響泵三,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜衔掸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一烫幕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敞映,春花似錦较曼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弛饭。三九已至,卻和暖如春萍歉,著一層夾襖步出監(jiān)牢的瞬間侣颂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工枪孩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留横蜒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓销凑,卻偏偏與公主長(zhǎng)得像丛晌,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子斗幼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容