Module Loading Performance Optimization
Reducing Network Requests
HTTP/2 Optimization Strategies:
- Multiplexing: Leverages HTTP/2’s multiplexing to eliminate HTTP/1.1 request number limitations.
- Header Compression: Uses the HPACK algorithm to compress request headers, reducing transmission overhead.
- Server Push: Proactively pushes critical resources to the client’s cache.
Implementation Example:
// Webpack configuration for HTTP/2 optimization
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
publicPath: 'https://cdn.example.com/assets/' // Use CDN for acceleration
},
performance: {
hints: 'warning',
maxAssetSize: 244 * 1024, // 244KB
maxEntrypointSize: 244 * 1024 // 244KB
}Resource Merging Strategies:
- Critical CSS Inlining: Inline critical CSS for the first screen directly into HTML.
- JS/CSS Merging: Combine small files into larger chunks.
- On-Demand Merging: Avoid excessive merging to prevent cache invalidation.
// Webpack configuration for merging small files
optimization: {
concatenateModules: true, // Scope hoisting
splitChunks: {
minSize: 30000, // Split chunks larger than 30KB
maxSize: 244000 // Attempt to split chunks larger than 244KB into smaller ones
}
}Module Preloading and Prefetching
Preloading Technology Comparison:
| Technology | Purpose | Priority | Use Case |
|---|---|---|---|
| preload | Resources essential for the current page | High | Critical rendering path resources |
| prefetch | Resources likely needed in the future | Low | Predictive loading |
| preconnect | Establish connections in advance | Medium | Third-party resource domains |
| dns-prefetch | Pre-resolve DNS | Low | Cross-domain resources |
Implementation Example:
<!-- Preload critical resources -->
<link rel="preload" href="critical.js" as="script">
<link rel="preload" href="main.css" as="style">
<!-- Predictive prefetching -->
<link rel="prefetch" href="next-page.js" as="script">
<link rel="prefetch" href="user-profile.jpg" as="image">
<!-- Pre-establish connections -->
<link rel="preconnect" href="https://api.example.com">
<link rel="dns-prefetch" href="https://cdn.example.com">Dynamic Preloading:
// Predictive preloading based on user behavior
document.addEventListener('mousemove', throttle(e => {
if (e.clientX > window.innerWidth - 100) {
// User may scroll, preload next page module
import(/* webpackPrefetch: true */ './next-page-module');
}
}, 200));
// Route-based preloading
const routes = [
{
path: '/dashboard',
component: () => import(/* webpackPrefetch: true */ './Dashboard')
}
];Module Caching Strategies
Cache Control Best Practices:
- Strong Caching Configuration:
Cache-Control: public, max-age=31536000, immutable- Negotiated Caching Configuration:
ETag: "xyz123"
Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT- Service Worker Caching:
// sw.js
const CACHE_NAME = 'v2';
const PRECACHE_URLS = [
'/index.html',
'/styles/main.[contenthash].css',
'/scripts/main.[contenthash].js'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(PRECACHE_URLS))
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetchAndCache(event.request))
);
});Caching Strategy Matrix:
| Resource Type | Caching Strategy | Example |
|---|---|---|
| Core JS/CSS | Strong caching + content hash | main.[contenthash].js |
| Images/Fonts | Strong caching + CDN | /images/logo.[hash].png |
| API Responses | Negotiated caching | ETag/Last-Modified |
| Third-Party Libraries | Long-term caching | react.[version].js |
Concurrent Module Loading Control
Concurrent Loading Optimization Strategies:
- HTTP/2 Concurrency Advantages:
- Supports multiplexing by default (typically 100+ parallel streams).
- Avoids HTTP/1.1 head-of-line blocking issues.
- Request Priority Control:
<link rel="preload" href="critical.js" as="script" importance="high">
<link rel="preload" href="non-critical.js" as="script" importance="low">- Resource Loading Order Optimization:
// Use Webpack magic comments to control loading priority
import(/* webpackPreload: true */ 'CriticalModule');
import(/* webpackPrefetch: true */ 'NonCriticalModule');Concurrency Limitation Solution:
// Custom concurrency controller
class ResourceLoader {
constructor(maxConcurrent = 6) {
this.maxConcurrent = maxConcurrent;
this.queue = [];
this.activeCount = 0;
}
load(resource) {
return new Promise((resolve, reject) => {
const task = () => {
this.activeCount++;
resource()
.then(resolve)
.catch(reject)
.finally(() => {
this.activeCount--;
this.next();
});
};
if (this.activeCount < this.maxConcurrent) {
task();
} else {
this.queue.push(task);
}
});
}
next() {
if (this.queue.length > 0 && this.activeCount < this.maxConcurrent) {
const task = this.queue.shift();
task();
}
}
}
// Usage example
const loader = new ResourceLoader(4); // Max 4 concurrent
const resources = [/* Array of resource loading functions */];
Promise.all(resources.map(r => loader.load(r)));Monitoring and Analyzing Module Loading Performance
Performance Monitoring Metrics:
- FP (First Paint): Time to first render.
- FCP (First Contentful Paint): Time to first content render.
- FMP (First Meaningful Paint): Time to first meaningful render.
- TTI (Time To Interactive): Time to interactivity.
- TBT (Total Blocking Time): Total blocking time.
Monitoring Tool Integration:
// Use web-vitals to monitor core web vitals
import { getCLS, getFID, getLCP, getFCP, getTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
navigator.sendBeacon('/analytics', body);
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);
getFCP(sendToAnalytics);
getTTFB(sendToAnalytics);
// Custom module loading performance monitoring
const moduleTimings = {};
function trackModuleLoad(moduleName) {
moduleTimings[moduleName] = {
start: performance.now(),
end: null,
duration: null
};
return {
end: () => {
moduleTimings[moduleName].end = performance.now();
moduleTimings[moduleName].duration =
moduleTimings[moduleName].end - moduleTimings[moduleName].start;
// Send monitoring data
if (moduleTimings[moduleName].duration > 100) {
console.warn(`Module ${moduleName} load time: ${moduleTimings[moduleName].duration.toFixed(2)}ms`);
// Can send to monitoring system
}
}
};
}
// Usage example
const timer = trackModuleLoad('heavy-component');
import('./heavy-component').then(() => {
timer.end();
});Performance Analysis Toolchain:
- Chrome DevTools Performance Panel
- Lighthouse CI Integration
- WebPageTest In-Depth Analysis
- RUM (Real User Monitoring) Systems
Module Bundle Size Optimization
Deep Application of Tree Shaking
Deep Tree Shaking Configuration:
// webpack.config.js
module.exports = {
optimization: {
usedExports: true, // Mark unused code
minimize: true, // Enable minification
concatenateModules: true, // Scope hoisting
sideEffects: true // Enable side effect analysis
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
plugins: ['@babel/plugin-transform-runtime']
}
}
}
]
}
};package.json Configuration:
{
"name": "my-library",
"sideEffects": [
"*.css",
"*.global.js"
],
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js"
}
}
}Advanced Tree Shaking Techniques:
- Dynamic Import Splitting:
// Split less commonly used features into separate modules
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));- Pure Function Marking:
/*#__PURE__*/
const result = expensiveCalculation();- Avoiding Side Effects:
// Avoid side effects at module top level
// Bad
console.log('Module loaded');
// Good
export function init() {
console.log('Explicit initialization');
}Code Splitting and Lazy Loading
Code Splitting Strategies:
Entry Splitting:
entry: {
main: './src/main.js',
admin: './src/admin.js'
}Dynamic Import Splitting:
const LazyComponent = React.lazy(() => import('./LazyComponent'));Common Code Extraction:
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20
}
}
}
}Route-Level Code Splitting:
// React Router example
const routes = [
{
path: '/dashboard',
component: React.lazy(() => import('./Dashboard'))
},
{
path: '/settings',
component: React.lazy(() => import('./Settings'))
}
];
function App() {
return (
<Suspense fallback={<LoadingSpinner />}>
<Routes>
{routes.map(route => (
<Route
key={route.path}
path={route.path}
element={<route.component />}
/>
))}
</Routes>
</Suspense>
);
}Compression and Obfuscation
Compression Tool Configuration:
// Webpack Terser configuration
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
compress: {
drop_console: true, // Remove console
pure_funcs: ['console.log'], // Remove specific functions
dead_code: true // Remove dead code
},
mangle: {
properties: {
regex: /^_/ // Only mangle properties starting with underscore
}
},
format: {
comments: false // Remove comments
}
}
})
]
}
};Advanced Compression Techniques:
- Conditional Compression:
new TerserPlugin({
terserOptions: {
compress: {
conditionals: true,
comparisons: true,
evaluate: true
}
}
})- Preserving Specific Names:
new TerserPlugin({
terserOptions: {
mangle: {
reserved: ['React', 'Component'] // Do not mangle these names
}
}
})- Source Map Optimization:
devtool: 'hidden-source-map' // Use in productionImage and Font Module Optimization
Image Optimization Strategies:
- Base64 Inlining:
// Webpack url-loader configuration
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // Convert to Base64 if smaller than 8KB
name: 'images/[name].[hash:8].[ext]'
}
}
]
}
]
}- Responsive Images:
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Example image">
</picture>- CDN Acceleration:
// Webpack publicPath pointing to CDN
output: {
publicPath: 'https://cdn.example.com/assets/'
}Font Optimization Strategies:
// Webpack font file configuration
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
]
}
]
}Bundle Size Analysis Tools
Webpack Bundle Analyzer:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'server', // or 'static'/'disabled'
analyzerHost: '127.0.0.1',
analyzerPort: 8888,
reportFilename: 'report.html',
defaultSizes: 'parsed',
openAnalyzer: true,
generateStatsFile: false,
statsFilename: 'stats.json',
statsOptions: null,
logLevel: 'info'
})
]
};Analysis Report Interpretation:
- Module Size Proportion: Identify the largest modules.
- Dependency Graph: Discover unnecessary dependencies.
- Duplicate Dependencies: Find libraries bundled multiple times.
- Unused Code: Identify parts eligible for Tree Shaking.
Other Analysis Tools:
- source-map-explorer:
npx source-map-explorer dist/main.js- webpack-bundle-analyzer Visualization:
npx webpack-bundle-analyzer stats.json- Lighthouse Performance Audit:
npm install -g lighthouse
lighthouse http://localhost:3000 --viewModularization and Runtime Performance
Module Initialization Performance
Reducing Initialization Overhead:
- Deferring Global Variables:
// Bad: Immediate execution polluting globals
const utils = { /* ... */ };
window.utils = utils;
// Good: Load on demand or defer exposure
export const utils = { /* ... */ };- Staged Initialization:
// Initialize core functionality immediately
initCore();
// Defer non-critical functionality initialization
setTimeout(initNonCritical, 0);
// or
window.requestIdleCallback(initNonCritical);Optimization Example:
// Module design optimization
// Bad: Immediate heavy computation on module load
export function init() {
const heavyData = computeHeavyData();
return { heavyData };
}
// Good: Compute on demand
export function createHeavyDataCalculator() {
return {
compute: () => computeHeavyData() // Deferred execution
};
}Module Caching and Reuse
Caching Strategy Implementation:
// Module-level caching
const moduleCache = new Map();
export function getModule(moduleName) {
if (moduleCache.has(moduleName)) {
return moduleCache.get(moduleName);
}
const module = loadModule(moduleName); // Actual loading logic
moduleCache.set(moduleName, module);
return module;
}
// Component-level caching
const componentCache = {};
function getCachedComponent(key, factory) {
if (!componentCache[key]) {
componentCache[key] = factory();
}
return componentCache[key];
}Memory Management:
// Cache with cleanup mechanism
class ModuleCache {
constructor(maxSize = 10) {
this.cache = new Map();
this.maxSize = maxSize;
}
get(key) {
if (!this.cache.has(key)) return null;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value); // Update access order
return value;
}
set(key, value) {
if (this.cache.size >= this.maxSize) {
const oldestKey = this.cache.keys().next().value;
this.cache.delete(oldestKey);
}
this.cache.set(key, value);
}
clear() {
this.cache.clear();
}
}Modularization and Virtual DOM Synergy Optimization
Virtual DOM Update Optimization:
- Component-Level Caching:
// React.memo for memoized components
const MemoizedComponent = React.memo(function MyComponent(props) {
/* Render using props */
});
// Memo with custom comparison function
const MemoizedComponent = React.memo(
MyComponent,
(prevProps, nextProps) => {
// Custom props comparison logic
return prevProps.id === nextProps.id;
}
);- Key Optimization:
<!-- Use stable unique IDs for keys -->
<ul>
{items.map(item => (
<ListItem
key={item.id}
item={item}
/>
))}
</ul>- Batch Updates:
// React batch updates
ReactDOM.unstable_batchedUpdates(() => {
setState1();
setState2();
});
// Or use automatic batching (React 18+)Modularization and Web Worker Integration
Web Worker Integration Patterns:
- Main Thread-Worker Communication:
// Main thread
const worker = new Worker('worker.js');
worker.postMessage({ type: 'CALCULATE', data: inputData });
worker.onmessage = (event) => {
const result = event.data;
// Process result
};
// worker.js
self.onmessage = (event) => {
if (event.data.type === 'CALCULATE') {
const result = heavyCalculation(event.data.data);
self.postMessage(result);
}
};- Modularized Worker:
// Use comlink to simplify Worker communication
import * as Comlink from 'comlink';
// worker.js
const api = {
heavyCalculation(data) {
// Computation-intensive task
}
};
Comlink.expose(api);
// Main thread
const workerApi = Comlink.wrap(new Worker('worker.js'));
const result = await workerApi.heavyCalculation(data);- Worker Pool Management:
class WorkerPool {
constructor(size, workerPath) {
this.pool = Array(size).fill().map(() => new Worker(workerPath));
this.queue = [];
this.activeCount = 0;
}
execute(task) {
return new Promise((resolve, reject) => {
const runTask = () => {
const worker = this.pool[this.activeCount++];
worker.onmessage = (e) => {
resolve(e.data);
this.activeCount--;
if (this.queue.length > 0) {
this.queue.shift()();
}
};
worker.onerror = reject;
worker.postMessage(task);
};
if (this.activeCount < this.pool.length) {
runTask();
} else {
this.queue.push(runTask);
}
});
}
}Modular Performance Testing and Benchmarking
Performance Testing Strategies:
- Unit Performance Testing:
// Use benchmark.js for benchmarking
const Benchmark = require('benchmark');
const suite = new Benchmark.Suite();
suite
.add('Module A', function() {
moduleA.heavyOperation();
})
.add('Module B', function() {
moduleB.heavyOperation();
})
.on('cycle', function(event) {
console.log(String(event.target));
})
.run({ 'async': true });- End-to-End Performance Testing:
// Use Lighthouse CI for performance testing
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000'],
numberOfRuns: 3
},
assert: {
assertions: {
'first-contentful-paint': ['error', { maxNumericValue: 1000 }],
'interactive': ['error', { maxNumericValue: 5000 }]
}
},
upload: {
target: 'temporary-public-storage'
}
}
};Performance Monitoring Metrics:
- Module Loading Time:
// Measure module loading time
const start = performance.now();
import('./module').then(module => {
const duration = performance.now() - start;
console.log(`Module load time: ${duration.toFixed(2)}ms`);
});- Initialization Performance:
// Measure component initialization time
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.initStart = performance.now();
}
componentDidMount() {
const duration = performance.now() - this.initStart;
console.log(`Component initialization time: ${duration.toFixed(2)}ms`);
}
render() {
return <div>My Component</div>;
}
}- Runtime Performance:
// Use Performance API to monitor runtime performance
function measurePerformance() {
performance.mark('start-task');
// Perform task...
performance.mark('end-task');
performance.measure('task-duration', 'start-task', 'end-task');
const measures = performance.getEntriesByName('task-duration');
console.log(`Task duration: ${measures[0].duration.toFixed(2)}ms`);
}



