Boosting Taobao Home Page Speed: Front‑End Strategies for Personalization
Taobao’s redesigned home page faces heavy personalization demands, multiple data sources, and numerous modules, prompting a series of front‑end performance techniques—including prioritized loading, lazy execution, image compression, caching, and request consolidation—to improve FPS, DOMContentLoaded, and overall user experience.
Many have noticed the new Taobao home page, which differs from previous versions and is saturated with personalization. The unique personalization requirements bring several front‑end technical challenges:
Multiple data sources
Serial requests to render a single module
Matching and managing operational data with personalized data
Data fallback and disaster recovery
The redesign no longer supports IE6/IE7, but many factors still affect performance:
Too many system dependencies : static resources (js/css/images/iconfonts), CDN‑delivered static data (operational content, front‑end configuration), and backend APIs. Roughly eight requests are issued on initial load and more than twenty when scrolling to the bottom.
Inability to output first‑screen data directly : many first‑screen pieces are fetched asynchronously, which inevitably adds latency.
Excessive modules : to isolate operational permissions, modules are split into fine‑grained pieces, many of which may never be displayed; an algorithm decides which modules to show.
Too many images : images come from operational input or personalization APIs, often without fixed dimensions.
Web Performance Metrics
There are many web performance indicators; focusing on a few key ones can raise overall performance.
FPS
The most direct indicator is FPS (frames per second). Screens refresh at 60 fps; below 24 fps feels sluggish, below 12 fps feels broken. One frame lasts about 16 ms; after accounting for system overhead, only ~10 ms remain for JavaScript. Tasks exceeding 80 ms should be split, and repeated loss of five or six frames must be avoided.
During the first second of page load, many initializations and DOM operations occur, which can lower the frame rate; this can be ignored on desktop but is more critical on mobile where the script and DOM size are smaller.
DOMContentLoaded and Load
DOMContentLoaded fires after the DOM is parsed. Large HTML (e.g., 2 000 extra nodes with deep nesting) can add 50–200 ms, which is unnecessary for first‑screen rendering; later content should be rendered via JavaScript hooks.
Load time reflects the total amount of data the client receives for the first screen. Large images or many connection attempts increase this metric.
Smoothness
Smoothness is the visual perception of FPS. To keep the page feeling responsive, content is often loaded lazily, as shown in the Google Plus example.
Taobao Home Page Performance Optimizations
Because the platform requires data from seven different back‑ends for the first screen, requests cannot be merged, and personalized or ad content cannot be cached.
Prioritizing Key Modules
Regardless of the first‑screen size, key modules must load first . The core initialization code is:
$('.J_Module').each(function(mod) { var $mod = $(mod); var name = $mod.attr('tms'); var data = $mod.attr('tms-data'); if($mod.hasClass('tb-pass')) { Reporter.send({msg: "Skipping module " + name}); return; } // Ensure first‑screen modules load first if (/promo|tmall|tanx|notice|member/.test(name)) { window.requestNextAnimationFrame(function(){ // Force render, no lazy‑load new Loader($mod, data, /tanx/.test(name)); }); } else { // Remaining modules enter lazy‑load queue lazyQueue.push({$mod:$mod, data:data, force:/fixedtool|decorations|bubble/.test(name)}); } });TMS outputs a .J_Module hook and pre‑loads the associated JS and CSS. Modules without JavaScript are marked with tb-pass and skipped during initialization. Non‑critical modules are placed in a lazyQueue for later loading.
Non‑critical modules are not added to the lazy queue immediately for two reasons:
Adding every module to the scroll‑handling logic would itself become a performance bottleneck.
If a non‑critical module renders before a key module finishes, it can block the key module.
Non‑critical modules start loading when user interaction occurs or after a timeout:
var __lazyLoaded = false;function runLazyQueue(){ if(__lazyLoaded){return;} __lazyLoaded = true; $(window).detach("mousemove scroll mousedown touchstart touchmove keydown resize onload", runLazyQueue); var module; while(module = lazyQueue.shift()){ (function(m){ // Process JS during browser idle time window.requestNextAnimationFrame(function(){ new Loader(m.$mod, m.data, m.force); }); })(module); } }$(window).on("mousemove scroll mousedown touchstart touchmove keydown resize onload", runLazyQueue); // Fallback: execute after 5 s if onload never fires window.requestNextAnimationFrame(function(){runLazyQueue();},5000);Two triggers start the lazy queue:
When any of the listed interaction events fire, indicating the user is engaging with the page.
If the page has already fired onload, the queue runs immediately; otherwise a 5‑second timeout forces execution.
Lazy Execution – Execute Only on Interaction
Some modules contain interactive features (e.g., headline tabs, floating layers). Because many users never use these, the full initialization is deferred until the user hovers over the module.
Even Lazier Execution – After Page Refresh
Two secondary requests (hot tags in the market module and the personal‑center background) are fetched during idle time or ten seconds after window.onload, then cached locally so that the next visit shows the result immediately. This “refresh‑only” execution is acceptable to product and technically feasible.
Image Size Control and Lazy Loading
Images from both operational input and personalization APIs often lack fixed dimensions, and retina screens increase the visual load. Alibaba CDN can resize images; for example, a 200 × 200 image can be requested with a size suffix. Adding _.webp further reduces size by about one‑third (where supported).
src = src.replace(/\s/g, '');var arr;if(/(_\d{2,}x\d{2,}\w*?\.(?:jpg|png)){2,}/.test(src) && src.indexOf('_!!') == -1){ arr = src.split('_'); if(arr[arr.length-1] == '.webp'){ src = [arr[0], arr[arr.length-2], arr[arr.length-1]].join('_'); } else { src = [arr[0], arr[arr.length-1]].join('_'); } }if(src.indexOf('_!!') > -1){ src = src.replace(/((_\d{2,}x\d{2,}[\w\d]*?|_co0)\.(jpg|png))+/,'$1');}WebP.isSupport(function(isSupportWebp){ if(/^http:/.test(src)){ src = src.slice(5); } if(isSupportWebp && /(taobaocdn|alicdn)\.com/.test(src) && (src.indexOf('.jpg') || src.indexOf('.png')) && !/webp/.test(src) && !ignoreWebP && !/\/s\.gif$/.test(src)){ src += '_.webp'; } $img.attr('src', src);});All homepage images undergo this compression and size‑suffix handling; however, images already compressed by operations may not benefit from additional processing.
Removing Module Hooks – Configuration‑Based Rendering
TMS modules embed the data ID in a hook, e.g., tms-datakey. For asynchronous modules, the front‑end can fetch data using this key. To avoid redundant data, modules with identical data structures are extracted into separate data pages, reducing source size and DOM parsing.
<div class="J_Module" tms-datakey="2483"></div> <textarea class="tb-hide">[{"backup":"false","baseid":"1","mid":"222726","name":"iFashion","per":"false","tid":"3","uid":"1000"}, ... ]</textarea>This approach cuts down on source code and DOM parsing overhead.
Low‑Frequency Module Caching
Modules that rarely change (e.g., fallback data, Alibaba APP modules) can be cached by adjusting request parameters:
io({url:URL, dataType:'jsonp', cache:true, jsonpCallback:'jsonp' + Math.floor(new Date/(1000*60)), success:function(){/*...*/}});The expression Math.floor(new Date/(1000*60)) yields a value that stays constant for a minute, effectively caching the request for that period. For daily caching: Math.floor(new Date/(1000*60*60*24)) Local storage can also be used:
offline.setItem('cache-moduleName', JSON.stringify(data), 1000*60*60*24);Taobao’s homepage primarily uses local storage for a one‑day cache.
Using Easing to Reduce Perceived Waiting
Instead of abrupt .show() calls, CSS3 transitions provide smoother visual feedback with lower performance cost.
Optimization Thinking Angles
Key performance principles for high‑traffic pages include:
First‑screen must be fast
Scrolling must be smooth
Avoid loading anything that can be deferred
Avoid executing code that can be deferred
Progressive and graceful rendering
Chrome Timeline analysis reveals a painting block around 1 s, FPS drops between 1.5 s‑2 s, and several jank points that can be traced to specific code stacks.
Macro‑level Optimization – requestAnimationFrame Polyfill
(function(){ var lastTime = 0; var vendors = ['ms','moz','webkit','o']; for(var x=0;x<vendors.length && !window.requestAnimationFrame; ++x){ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if(!window.requestAnimationFrame){ window.requestAnimationFrame = function(callback, element){ var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function(){ callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; } if(!window.cancelAnimationFrame){ window.cancelAnimationFrame = function(id){ clearTimeout(id); }; }})();This polyfill ensures each module’s initialization runs during browser idle periods, reducing frame loss.
Conclusion
Performance optimization is a fine‑grained effort; refactoring a large, unoptimized page may be necessary. Starting from Taobao’s personalized homepage, the article walks through micro‑ and macro‑level front‑end practices—prioritizing key modules, lazy loading, image compression, caching, and request consolidation—to provide actionable guidelines for high‑traffic web applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITFLY8 Architecture Home
ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
