Skip to content

FEATURE: 能否用 PerformanceObserver API 实现资源加载进度百分比 #7767

@elkon028

Description

@elkon028

Version

Vben Admin V5

Description

不知道是否可行

这里有个演示,用 PerformanceObserver API 实现的资源加载进度百分比效果

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>真实字节加载进度</title>

  <style>
    #app-loading {
      position: fixed;inset: 0;background:#fff;z-index:999999;
      display:flex;align-items:center;justify-content:center;
      transition:all 0.5s;
    }
    #app-loading.fade-out {
      opacity:0;visibility:hidden;
    }
    .wrap { width:380px;display:flex;flex-direction:column;gap:20px }
    .item { display:flex;flex-direction:column;gap:6px }
    .txt { display:flex;justify-content:space-between;font-size:14px;color:#333 }
    .bar { height:6px;background:#f2f2f2;border-radius:6px;overflow:hidden }
    .fill { height:100%;width:0%;transition:width 0.15s linear }
    .css .fill { background:#42b983 }
    .js  .fill { background:#1677ff }
  </style>
</head>
<body>

<div id="app-loading">
  <div class="wrap">
    <div class="item css">
      <div class="txt"><span>CSS 加载</span><span id="cssPct">0%</span></div>
      <div class="bar"><div id="cssBar" class="fill"></div></div>
    </div>
    <div class="item js">
      <div class="txt"><span>JS 加载</span><span id="jsPct">0%</span></div>
      <div class="bar"><div id="jsBar" class="fill"></div></div>
    </div>
  </div>
</div>

<div id="app"></div>

<script>
  const cssBar = document.getElementById('cssBar')
  const jsBar = document.getElementById('jsBar')
  const cssPct = document.getElementById('cssPct')
  const jsPct = document.getElementById('jsPct')
  const loading = document.getElementById('app-loading')

  let cssTotal = 0, cssLoaded = 0
  let jsTotal = 0, jsLoaded = 0

  console.log('🚀 初始化加载监听')

  // ==============================================
  // 🔥 核心:使用 initiatorType 判断资源类型
  // ==============================================
  function handleEntry(entry) {
    console.log('==================== 资源 Entry ====================')
    console.log(entry)

    const isResource = entry.entryType === 'resource'
    const isCSS = entry.initiatorType === 'link'
    const isJS = entry.initiatorType === 'script'
    const size = entry.encodedBodySize || 0

    console.log('✅ 处理资源:',
      isCSS ? 'CSS' : isJS ? 'JS' : '其他',
      ' | initiatorType:', entry.initiatorType,
      ' | 大小:', size,
      ' | URL:', entry.name
    )

    if (!isResource) return

    if (isCSS) {
      cssTotal += size
      cssLoaded += size
      updateCSS()
    }

    if (isJS) {
      jsTotal += size
      jsLoaded += size
      updateJS()
    }
  }

  // ==============================================
  // PerformanceObserver 监听
  // ==============================================
  const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      handleEntry(entry)
    }
  })
  observer.observe({ entryTypes: ['resource'] })

  // ==============================================
  // 进度更新
  // ==============================================
  function updateCSS() {
    const p = cssTotal ? Math.min(100, (cssLoaded / cssTotal * 100) | 0) : 0
    cssBar.style.width = p + '%'
    cssPct.innerText = p + '%'
  }
  function updateJS() {
    const p = jsTotal ? Math.min(100, (jsLoaded / jsTotal * 100) | 0) : 0
    jsBar.style.width = p + '%'
    jsPct.innerText = p + '%'
  }

  // ==============================================
  // 页面完全加载后,强制完成
  // ==============================================
  window.addEventListener('load', () => {
    console.log('🌍 页面完全加载')
    setTimeout(() => {
      cssBar.style.width = '100%'
      cssPct.innerText = '100%'
      jsBar.style.width = '100%'
      jsPct.innerText = '100%'
      setTimeout(() => loading.classList.add('fade-out'), 300)
    }, 400)
  })
</script>
</body>
</html>

注意

这个API有安全策略,好象只能监听同源资源

The Content Security Policy directive 'upgrade-insecure-requests' is ignored when delivered in a report-only policy.

Proposed Solution

Alternatives Considered

No response

Additional Context

No response

Validations

  • Read the docs
  • Ensure the code is up to date. (Some issues have been fixed in the latest version)
  • I have searched the existing issues and checked that my issue does not duplicate any existing issues.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions