Frontend Development 22 min read

Performance Optimization Journey for Wukong H5 Topics

The article details Wukong’s systematic H5 performance overhaul—adding DNS‑prefetch, CDN and HTTP/2, compressing fonts and images, applying lazy‑load and WebP, minimizing reflows with Vue lifecycle hooks, using skeleton screens, and reporting metrics—resulting in load‑time cuts of up to 70 % and scores rising from the 40s‑60s to over 90.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Performance Optimization Journey for Wukong H5 Topics

Background: After a series of articles on the Wukong activity platform, readers are familiar with micro‑components and dynamic layout solutions. This article introduces the performance‑optimization path for Wukong H5 topics.

In the mobile‑Internet era, H5 page load experience is critical. Studies show that each additional second of load time can reduce conversion rates by up to 20 %.

Wukong continuously seeks the best loading solutions through technical innovation. The following sections describe the systematic optimization process.

1. Network‑Layer Optimizations

(1) DNS Prefetch

The browser resolves a domain in the order: browser cache → system cache → router cache → ISP cache → recursive lookup. Mobile networks have very low bandwidth for DNS requests but high latency, so Wukong adds <meta http-equiv="x-dns-prefetch-control" content="on" /> and <link rel="dns-prefetch" href="//topicstatic.vivo.com.cn" /> to the page header. Conditional logic generates region‑specific DNS‑prefetch links, e.g.:

<% if (国内活动) { %>
  <link rel="dns-prefetch" href="//topic.vivo.com.cn">
  <link rel="dns-prefetch" href="//cmsapi.vivo.com.cn">
  <link rel="dns-prefetch" href="//topicstatic.vivo.com.cn">
<% } else if (印度活动) { %>
  <link rel="dns-prefetch" href="//in-goku.vivoglobal.com">
  <link rel="dns-prefetch" href="//topicstatic.vivo.com.cn">
  <link rel="dns-prefetch" href="//in-gokustatic.vivoglobal.com">
<% } else { %>
  <link rel="dns-prefetch" href="//asia-goku.vivoglobal.com">
  <link rel="dns-prefetch" href="//asia-gokustatic.vivoglobal.com">
  <link rel="dns-prefetch" href="//asia-wukongapi.vivoglobal.com">
<% } %>

(2) CDN Distribution

Static resources are uploaded to a CDN, reducing origin‑server pressure and shortening load time. The CDN cache strategy stores JS/CSS but not HTML entry files to ensure timely updates.

(3) HTTP/2

HTTP/2 introduces multiplexing, header compression, and server push. Enabling it in Nginx:

server {
  listen 443 ssl http2;
  server_name yourdomain;
  …
  ssl on;
  …
}

and the listen directive:

listen 443 ssl http2;

(4) Dynamic Font Compression

Using fontmin , Wukong extracts only the glyphs needed for a page, generates TTF/WOFF/EOT/SVG files and corresponding CSS. Example code:

const compressFont = (fontText, fontName) => {
  const srcPath = `dist/${siteId}/font/${fontName}.ttf`;
  const destPath = `dist/${siteId}/compressFont`;
  const fontmin = new Fontmin()
    .src(srcPath)
    .use(Fontmin.glyph({ text: fontText }))
    .use(Fontmin.ttf2eot())
    .use(Fontmin.ttf2woff())
    .use(Fontmin.ttf2svg())
    .use(Fontmin.css({ fontPath: `/compressFont/`, fontFamily: fontName }))
    .dest(destPath);
  fontmin.run((err, files, stream) => {
    if (err) { console.error(err); return; }
    const fontCss = fs.readFileSync(path.join(__dirname, `../dist/${siteId}/compressFont/${fontName}.css`)).toString();
    fontStyleStr += fontCss;
    loadHtml(fontStyleStr);
  });
};

const handleFont = (fontText, familyList) => {
  familyList.forEach(name => compressFont(fontText, name));
};

2. Resource Optimizations

(1) Image Lazy Loading

Wukong adopts vue‑lazyload so that images are loaded only when they enter the viewport. Example component usage:

<template>
  <div>
    <img v‑lazy="imgUrl" />
    <div v‑lazy:background‑image="imgUrl"></div>
    <!-- with error / loading placeholders -->
    <img v‑lazy="imgObj" />
    <div v‑lazy:background‑image="imgObj"></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      imgObj: {
        src: 'http://xx.com/logo.png',
        error: 'http://xx.com/error.png',
        loading: 'http://xx.com/loading‑spin.svg'
      },
      imgUrl: 'http://xx.com/logo.png'
    };
  }
}
</script>

(2) Image Compression (WebP)

WebP provides lossy compression that can shrink a 999 KB image to ~38 KB (≈75 % quality). The conversion command:

await execFileSync(cwebp, ['-q', '75', filePath, '-o', webpPath]);

(3) Cross‑Origin Preflight Reduction

Removing unnecessary custom headers turns a complex request into a simple one, eliminating the OPTIONS preflight and saving ~100 ms.

3. Rendering & Execution Optimizations

(1) Avoid Reflow

Replace direct DOM style changes with class toggles, and batch DOM reads/writes. Example of reading geometry:

offsetTop, offsetLeft, scrollTop, scrollLeft, clientTop, clientLeft, getComputedStyle()

(2) Leverage Vue Lifecycle

Fetch data in beforeCreate (when the render tree is not yet built) and perform DOM‑related work in mounted :

export default {
  beforeCreate() {
    fetch({ url: topicUrl, params: { /* … */ } }).then(res => { /* data handling */ });
  },
  mounted() {
    window.addEventListener('xxx', handler);
    this.$refs.xxx;
    document.querySelector(...);
  }
}

(3) Reduce White‑Screen Time

Use skeleton screens, adjust third‑party script order, split common code with SplitChunksPlugin , and load page‑specific code via dynamic import() . CSS animation delays the visual loading indicator to avoid clash with WebView initialization.

4. Optimization Results

Key metrics before and after optimization (PageSpeed Insights):

Domestic activities – First Paint reduced from 2.8 s to 1.3 s, Speed Index from 4 s to 3.8 s, Total Render time from 12 s to 2.3 s, Overall score from 44 to 90.

Overseas activities – First Paint reduced from 3.5 s to 1.3 s, Speed Index from 5.6 s to 3.3 s, Render time from 3.5 s to 2.8 s, Score from 67 to 92.

5. Performance Data Collection

Metrics such as page load time, first‑paint, DOM‑ready, and custom white‑screen time are collected via the Performance Timing API. Example calculation:

White‑screen time = responseStart - navigationStart

First render duration = loadEventEnd - navigationStart

Data is reported asynchronously using navigator.sendBeacon() to avoid blocking the page.

function stat() {
  navigator.sendBeacon('/path', analyticsData);
}

6. Future Work & Reflections

Further exploration includes SSR, CSR, and “instant‑open” solutions for H5, emphasizing that performance optimization is a mindset rather than a single technique.

References

HTTP/2 Performance Guide

Juejin Article on Performance

frontendPerformanceOptimizationwebcdnVueHTTP2
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.