react 页面如何自动监控版本更新

一般我们打包的js bundle,都自带了hash,所以,刷新页面就会加载最新的内容。
但如果用户一直不去刷新页面,停留在当前页面呢?

  1. 可以前端写个轮询,去检测,2. 后端推送

对于第一种方案实现简单,但会有一点性能损耗,第二种需要后端实现,SSE,或websocket?

下面代码展示第一种轮询方案:

usePoller.js

import { useEffect, useState } from 'react'
export const UsePoller = ({ deploymentUrl }: any) => {
  const [isNewVersionAvailable, setIsNewVersionAvailable] = useState(false)
  useEffect(() => {
    const compareVersions = async () => {
      // request the index.html file from the deployment

      const fetchedPage = await fetch(deploymentUrl, { method: 'get', mode: 'cors' })

      // get the text from the response

      const loadedText = await fetchedPage.text()
      // get the index.js file to get hash
      const SCRIPT_REJEX_MAIN = /^.*<script.*\/(index.*\.js).*$/gim
      const matchResponses = SCRIPT_REJEX_MAIN.exec(loadedText)

      const remoteMainScript =
        matchResponses && matchResponses?.length > 0 ? matchResponses[1] : undefined

      if (remoteMainScript === undefined) {
        console.log('Could not find index script in index.html')
        setIsNewVersionAvailable(false)
        return
      }

      // get the current version hash from current deployment

      let currentMainScript = undefined

      // get text representation of document

      const scriptTags = document.head.getElementsByTagName('script')
      for (let i = 0; i < scriptTags.length; i++) {
        const scriptTag: any = scriptTags[i]
        const reg = /^.*\/(index.*\.js).*$/gim
        if (scriptTag.src) {
          const obj = reg.exec(scriptTag.src)
          if (obj !== null) {
            currentMainScript = obj[1]
          } else {
            currentMainScript = undefined
          }
        }
      }

      // if the current index script, or the remote index script is undefined, we can't compare
      // but if they are there, compare them

      setIsNewVersionAvailable(
        !!currentMainScript &&
          !!remoteMainScript &&
          currentMainScript !== remoteMainScript
      )

      console.log('Current index script: ', currentMainScript)
      console.log('Remote index script: ', remoteMainScript)
    }

    // compare versions every 5 minutes

    const createdInterval = setInterval(compareVersions, 5 * 60 * 1000)

    return () => {
      // clear the interval when the component unmounts

      clearInterval(createdInterval)
    }
  }, [deploymentUrl])

  // return the state

  return { isNewVersionAvailable }
}

app.tsx

import { UsePoller } from './usePoller'
export default function App() {
  const { isNewVersionAvailable } = UsePoller({
    deploymentUrl: INDEX_HTML_DEPLOYMENT_URL,
  })

  useEffect(() => {
    if (isNewVersionAvailable) {
      console.log('New version available, reloading...')
      alert('New version available, click ok to reload')
      window.location.reload()
    } else {
      console.log('No new version available...')
    }
  }, [isNewVersionAvailable])
rerturn ...
}
posted @ 2023-10-09 16:29  小猪ab  阅读(160)  评论(0编辑  收藏  举报