Frontend Development 13 min read

Performance Optimization Practices for the XRN Platform (Web and React Native)

NetEase’s XRN platform boosts Web and React Native performance by eliminating duplicate bundles, pruning unused code, importing only needed polyfills, using dynamic imports and bundle splitting, pre‑loading assets, lazily loading images and lists, limiting first‑screen rendering, and applying memoization, raising Lighthouse scores from 50.3 to 80.4 and cutting RN load time by 40 %.

NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
Performance Optimization Practices for the XRN Platform (Web and React Native)

The XRN platform, developed by NetEase Cloud Music's front‑end team, is a visual page‑building solution that generates pages runnable on both React Native and Web. To deliver high‑performance experiences, the team applied a series of optimization techniques.

Packaging‑stage Optimizations (Web)

1. Reduce Duplicate Bundling – XRN’s web code is split into xrn-common (shared with RN) and xrn-webview . Using source-map-explorer they identified duplicated libraries and resolved them by aligning versions or configuring resolve.alias in Webpack.

2. Code Pruning – Tree‑shaking removes unused code, but it requires ES6 import/export . For packages like react-native-web , the team used babel-plugin-react-native-web to rewrite import paths, enabling pruning. They also warned that a lingering require('react-native-web') can re‑introduce the whole package.

3. Polyfill Optimization – Instead of bundling the full babel-polyfill , they installed core-js and imported only needed polyfills (e.g., import 'core-js/fn/object/values' ). Using @babel/preset-env with useBuiltIns: 'usage' further reduced bundle size, as shown by Lighthouse metrics.

4. Dynamic Imports – Leveraging the import() syntax, Webpack/Rollup can split code into multiple chunks that are loaded on demand. React.lazy and Suspense enable component‑level lazy loading, while dynamic imports also apply to third‑party libraries.

5. Additional Tools – Chrome DevTools’ Coverage tab and Web Dev recommendations help locate dead code.

Packaging‑stage Optimizations (React Native)

1. Bundle Splitting – The RN build separates a business bundle (XRN‑specific components) from a base bundle (shared dependencies like react, react‑native, react‑navigation). This split reduced the RN jsbundle size by 36% .

2. Pre‑loading – The Cloud Music app pre‑downloads the business bundle and warms up the base bundle before the RN screen appears, cutting first‑load latency.

Rendering‑stage Optimizations

1. Image Lazy Loading – For long pages, images outside the initial viewport are lazily loaded. On the Web, <img loading="lazy" /> , IntersectionObserver, or FlatList (react‑native‑web) are options. XRN implements a custom LazyLoadImage inside a ScrollView that uses measureLayout and onScroll to render placeholders until the image enters view.

// 修改前
import { View } from 'react-native';
// 修改后
import View from 'react-native-web/dist/exports/View';

2. List Lazy Loading – For long lists, XRN first renders a single line to measure its height, then renders remaining items, avoiding full rendering of off‑screen rows.

3. First‑Screen Rendering – The platform limits initial rendering to roughly one and a half screens, using pre‑estimated component heights to decide which components to render immediately.

4. Progressive Rendering – After the first screen, remaining content is loaded in batches using setTimeout , ensuring interactive responsiveness while preventing long white‑screens.

5. Reducing Duplicate Renders – Using React DevTools Profiler, the team identified unnecessary re‑renders. They mitigated them with shouldComponentUpdate , useMemo , useCallback , and React.memo to stabilize props references.

Conclusion

After applying these optimizations, XRN’s Web Lighthouse score rose from 50.3 (198 pages) to 80.4 (618 pages). The RN side saw a 40% improvement in page‑load speed, providing valuable reference points for Web and RN performance tuning.

References

source‑map‑explorer: https://github.com/danvk/source-map-explorer#readme

babel‑plugin‑react‑native‑web: https://www.npmjs.com/package/babel-plugin-react-native-web

Tree‑shaking issue discussion: https://baconbrix.gitbook.io/react-native-web/anti-pitch#tree-shaking-is-too-fragile

Chrome Coverage Tab: https://developers.google.com/web/tools/chrome-devtools/coverage

Web Dev unused JS guide: https://web.dev/unused-javascript/

IntersectionObserver: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

FlatList (react‑native‑web): https://necolas.github.io/react-native-web/docs/?path=/docs/components-flatlist--single-column

React Native re‑render guide: https://callstack.com/blog/the-ultimate-guide-to-react-native-optimization/#Pay_attention_to_UI_re-renders

Apply instant loading with PRPL: https://web.dev/apply-instant-loading-with-prpl/

Fast load times: https://web.dev/fast/

NetEase Cloud Music Front‑end Team: https://github.com/x-orpheus

webWebpacklazy loadingReact NativeTree shakingCode Splitting
NetEase Cloud Music Tech Team
Written by

NetEase Cloud Music Tech Team

Official account of NetEase Cloud Music Tech Team

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.