Advanced Polyfill Patterns and Techniques

1. Lazy Loading and Conditional Polyfill Patterns

Pattern Loading Strategy Use Case Benefits
On-demand Loading Load when feature accessed Rarely used features Minimal initial bundle
Route-based Loading Load per route/page Page-specific features Split by functionality
Intersection Loading Load on viewport visibility Below-fold features Defer non-critical
Idle Loading Load during browser idle Future interactions No blocking
User Interaction Load on click/hover Interactive features Just-in-time loading

Example: Lazy polyfill loader with caching

// lazy-polyfill-loader.js
var LazyPolyfillLoader = (function() {
    var cache = {};
    var loading = {};
    
    function loadScript(url) {
        // Return cached promise if already loading
        if (loading[url]) {
            return loading[url];
        }
        
        // Return immediately if already loaded
        if (cache[url]) {
            return Promise.resolve(cache[url]);
        }
        
        // Load script
        loading[url] = new Promise(function(resolve, reject) {
            var script = document.createElement('script');
            script.src = url;
            script.async = true;
            
            script.onload = function() {
                cache[url] = true;
                delete loading[url];
                resolve(true);
            };
            
            script.onerror = function() {
                delete loading[url];
                reject(new Error('Failed to load: ' + url));
            };
            
            document.head.appendChild(script);
        });
        
        return loading[url];
    }
    
    return {
        // Lazy load polyfill for specific feature
        loadPolyfill: function(featureName, testFn, polyfillUrl) {
            // Check if feature is already available
            if (testFn()) {
                return Promise.resolve('native');
            }
            
            // Load polyfill
            return loadScript(polyfillUrl).then(function() {
                // Verify polyfill loaded correctly
                if (testFn()) {
                    return 'polyfilled';
                } else {
                    throw new Error('Polyfill loaded but feature still unavailable');
                }
            });
        },
        
        // Load multiple polyfills conditionally
        loadConditional: function(polyfills) {
            var promises = polyfills.map(function(polyfill) {
                return this.loadPolyfill(
                    polyfill.name,
                    polyfill.test,
                    polyfill.url
                );
            }.bind(this));
            
            return Promise.all(promises);
        },
        
        // Clear cache for testing
        clearCache: function() {
            cache = {};
            loading = {};
        }
    };
})();

// Usage - lazy load IntersectionObserver
document.addEventListener('DOMContentLoaded', function() {
    var lazyImages = document.querySelectorAll('.lazy-image');
    
    if (lazyImages.length > 0) {
        LazyPolyfillLoader.loadPolyfill(
            'IntersectionObserver',
            function() { return 'IntersectionObserver' in window; },
            '/polyfills/intersection-observer.min.js'
        ).then(function(status) {
            console.log('IntersectionObserver:', status);
            
            // Now use IntersectionObserver
            var observer = new IntersectionObserver(function(entries) {
                entries.forEach(function(entry) {
                    if (entry.isIntersecting) {
                        var img = entry.target;
                        img.src = img.dataset.src;
                        observer.unobserve(img);
                    }
                });
            });
            
            lazyImages.forEach(function(img) {
                observer.observe(img);
            });
        });
    }
});

Example: Route-based polyfill loading

// route-based-loader.js
var RoutePolyfillLoader = {
    routePolyfills: {
        '/dashboard': [
            { test: function() { return 'ResizeObserver' in window; }, 
              url: '/polyfills/resize-observer.js' }
        ],
        '/charts': [
            { test: function() { return 'Intl' in window && 'NumberFormat' in Intl; },
              url: '/polyfills/intl.js' }
        ],
        '/video': [
            { test: function() { return 'MediaRecorder' in window; },
              url: '/polyfills/media-recorder.js' }
        ]
    },
    
    loadForRoute: function(route) {
        var polyfills = this.routePolyfills[route] || [];
        
        var promises = polyfills.map(function(polyfill) {
            if (!polyfill.test()) {
                return LazyPolyfillLoader.loadPolyfill(
                    polyfill.name || 'unnamed',
                    polyfill.test,
                    polyfill.url
                );
            }
            return Promise.resolve('native');
        });
        
        return Promise.all(promises);
    }
};

// Router integration
var Router = {
    navigate: function(route) {
        RoutePolyfillLoader.loadForRoute(route).then(function() {
            console.log('Route polyfills loaded for:', route);
            // Render route
            this.renderRoute(route);
        }.bind(this));
    },
    
    renderRoute: function(route) {
        // Route rendering logic
    }
};
Note: Lazy loading reduces initial bundle size by 50-70% for polyfills. Load only what's needed, when it's needed.

2. Feature Flag Integration with Polyfills

Feature Flag Tool Integration Method Use Case Complexity
LaunchDarkly SDK + conditional loading Enterprise feature management Complex
Split.io Client SDK + targeting A/B testing polyfills Medium
Custom Flags localStorage/cookies Simple on/off toggles Simple
Environment Variables Build-time injection Per-environment control Simple
Query Parameters URL-based flags Testing/debugging Simple

Example: Feature flag-based polyfill loading

// feature-flag-loader.js
var FeatureFlagPolyfillLoader = {
    flags: {},
    
    // Initialize flags from various sources
    init: function() {
        // 1. Environment variables (build-time)
        if (typeof POLYFILL_FLAGS !== 'undefined') {
            Object.assign(this.flags, POLYFILL_FLAGS);
        }
        
        // 2. localStorage
        try {
            var stored = localStorage.getItem('polyfill_flags');
            if (stored) {
                Object.assign(this.flags, JSON.parse(stored));
            }
        } catch (e) {}
        
        // 3. Query parameters
        var params = new URLSearchParams(window.location.search);
        if (params.has('polyfills')) {
            var polyfillFlags = params.get('polyfills').split(',');
            polyfillFlags.forEach(function(flag) {
                this.flags[flag] = true;
            }.bind(this));
        }
        
        console.log('Polyfill feature flags:', this.flags);
    },
    
    // Check if polyfill should be loaded
    shouldLoad: function(polyfillName) {
        var flagName = 'enable_' + polyfillName.toLowerCase().replace(/[^a-z0-9]/g, '_');
        
        // Check explicit flag
        if (this.flags.hasOwnProperty(flagName)) {
            return this.flags[flagName] === true;
        }
        
        // Default: load if feature is missing
        return true;
    },
    
    // Load polyfill if flag is enabled
    loadConditional: function(polyfillName, testFn, url) {
        if (!this.shouldLoad(polyfillName)) {
            console.log('Polyfill disabled by flag:', polyfillName);
            return Promise.resolve('disabled');
        }
        
        if (testFn()) {
            return Promise.resolve('native');
        }
        
        return LazyPolyfillLoader.loadPolyfill(polyfillName, testFn, url);
    }
};

// Initialize
FeatureFlagPolyfillLoader.init();

// Usage
FeatureFlagPolyfillLoader.loadConditional(
    'IntersectionObserver',
    function() { return 'IntersectionObserver' in window; },
    '/polyfills/intersection-observer.js'
).then(function(status) {
    console.log('IntersectionObserver status:', status);
});

// A/B testing with feature flags
var PolyfillABTest = {
    groups: {
        A: ['Promise', 'fetch'],
        B: ['Promise', 'fetch', 'IntersectionObserver', 'ResizeObserver']
    },
    
    getUserGroup: function() {
        // Get from analytics or random assignment
        var group = localStorage.getItem('ab_test_group');
        if (!group) {
            group = Math.random() < 0.5 ? 'A' : 'B';
            localStorage.setItem('ab_test_group', group);
        }
        return group;
    },
    
    loadForGroup: function() {
        var group = this.getUserGroup();
        var polyfills = this.groups[group];
        
        console.log('Loading polyfills for group:', group, polyfills);
        
        var polyfillMap = {
            'Promise': {
                test: function() { return 'Promise' in window; },
                url: '/polyfills/promise.js'
            },
            'fetch': {
                test: function() { return 'fetch' in window; },
                url: '/polyfills/fetch.js'
            },
            'IntersectionObserver': {
                test: function() { return 'IntersectionObserver' in window; },
                url: '/polyfills/intersection-observer.js'
            },
            'ResizeObserver': {
                test: function() { return 'ResizeObserver' in window; },
                url: '/polyfills/resize-observer.js'
            }
        };
        
        var promises = polyfills.map(function(name) {
            var config = polyfillMap[name];
            return LazyPolyfillLoader.loadPolyfill(name, config.test, config.url);
        });
        
        return Promise.all(promises);
    }
};

// Load polyfills based on A/B test group
PolyfillABTest.loadForGroup().then(function() {
    console.log('A/B test polyfills loaded');
    initApp();
});
Note: Feature flags enable gradual rollout and A/B testing of polyfills. Test performance impact before full deployment.

3. Polyfill Composition and Dependency Management

Approach Dependencies Resolution Complexity
Manual Ordering Hard-coded load order Script tag sequence Simple
Dependency Graph Explicit declarations Topological sort Medium
Module Bundler Import statements Webpack/Rollup Low (automated)
Registry Pattern Centralized registry Lazy resolution Medium
Composite Polyfills Bundled dependencies Pre-resolved Simple

Example: Dependency-aware polyfill loader

// polyfill-dependency-manager.js
var PolyfillDependencyManager = (function() {
    var registry = {};
    var loaded = new Set();
    var loading = new Map();
    
    function registerPolyfill(name, config) {
        registry[name] = {
            name: name,
            test: config.test,
            url: config.url,
            dependencies: config.dependencies || [],
            load: config.load
        };
    }
    
    function isLoaded(name) {
        return loaded.has(name);
    }
    
    function loadPolyfill(name) {
        // Already loaded
        if (isLoaded(name)) {
            return Promise.resolve('already-loaded');
        }
        
        // Currently loading
        if (loading.has(name)) {
            return loading.get(name);
        }
        
        var polyfill = registry[name];
        if (!polyfill) {
            return Promise.reject(new Error('Unknown polyfill: ' + name));
        }
        
        // Check if native support exists
        if (polyfill.test()) {
            loaded.add(name);
            return Promise.resolve('native');
        }
        
        // Load dependencies first
        var depPromises = polyfill.dependencies.map(function(dep) {
            return loadPolyfill(dep);
        });
        
        var loadPromise = Promise.all(depPromises).then(function() {
            // Load this polyfill
            if (polyfill.load) {
                return polyfill.load();
            } else if (polyfill.url) {
                return loadScript(polyfill.url);
            } else {
                throw new Error('No load method for: ' + name);
            }
        }).then(function() {
            loaded.add(name);
            loading.delete(name);
            console.log('Loaded polyfill:', name);
            return 'loaded';
        }).catch(function(error) {
            loading.delete(name);
            throw error;
        });
        
        loading.set(name, loadPromise);
        return loadPromise;
    }
    
    function loadScript(url) {
        return new Promise(function(resolve, reject) {
            var script = document.createElement('script');
            script.src = url;
            script.async = true;
            script.onload = resolve;
            script.onerror = function() {
                reject(new Error('Failed to load: ' + url));
            };
            document.head.appendChild(script);
        });
    }
    
    return {
        register: registerPolyfill,
        load: loadPolyfill,
        isLoaded: isLoaded,
        getLoaded: function() {
            return Array.from(loaded);
        }
    };
})();

// Register polyfills with dependencies
PolyfillDependencyManager.register('Promise', {
    test: function() { return 'Promise' in window; },
    url: '/polyfills/promise.js',
    dependencies: []
});

PolyfillDependencyManager.register('fetch', {
    test: function() { return 'fetch' in window; },
    url: '/polyfills/fetch.js',
    dependencies: ['Promise'] // fetch requires Promise
});

PolyfillDependencyManager.register('async-await', {
    test: function() {
        try {
            eval('(async function() {})');
            return true;
        } catch (e) {
            return false;
        }
    },
    url: '/polyfills/regenerator-runtime.js',
    dependencies: ['Promise'] // async/await requires Promise
});

PolyfillDependencyManager.register('IntersectionObserver', {
    test: function() { return 'IntersectionObserver' in window; },
    url: '/polyfills/intersection-observer.js',
    dependencies: ['Promise', 'MutationObserver']
});

PolyfillDependencyManager.register('MutationObserver', {
    test: function() { return 'MutationObserver' in window; },
    url: '/polyfills/mutation-observer.js',
    dependencies: []
});

// Usage - load fetch (will automatically load Promise first)
PolyfillDependencyManager.load('fetch').then(function(status) {
    console.log('fetch loaded:', status);
    console.log('All loaded polyfills:', PolyfillDependencyManager.getLoaded());
    
    // Now safe to use fetch
    fetch('/api/data').then(function(response) {
        return response.json();
    });
});

Example: Composite polyfill bundles

// composite-polyfills.js
var CompositePolyfills = {
    bundles: {
        // ES6 basics bundle
        'es6-basics': {
            polyfills: ['Promise', 'Object.assign', 'Array.from', 'Array.includes'],
            url: '/polyfills/bundles/es6-basics.js',
            test: function() {
                return 'Promise' in window &&
                       'assign' in Object &&
                       'from' in Array &&
                       Array.prototype.includes;
            }
        },
        
        // Web APIs bundle
        'web-apis': {
            polyfills: ['fetch', 'URLSearchParams', 'FormData'],
            url: '/polyfills/bundles/web-apis.js',
            dependencies: ['es6-basics'],
            test: function() {
                return 'fetch' in window &&
                       'URLSearchParams' in window &&
                       'FormData' in window;
            }
        },
        
        // Observers bundle
        'observers': {
            polyfills: ['IntersectionObserver', 'ResizeObserver', 'MutationObserver'],
            url: '/polyfills/bundles/observers.js',
            dependencies: ['es6-basics'],
            test: function() {
                return 'IntersectionObserver' in window &&
                       'ResizeObserver' in window &&
                       'MutationObserver' in window;
            }
        }
    },
    
    loadBundle: function(bundleName) {
        var bundle = this.bundles[bundleName];
        if (!bundle) {
            return Promise.reject(new Error('Unknown bundle: ' + bundleName));
        }
        
        // Check if already available
        if (bundle.test()) {
            return Promise.resolve('native');
        }
        
        // Load dependencies first
        var depPromises = (bundle.dependencies || []).map(function(dep) {
            return this.loadBundle(dep);
        }.bind(this));
        
        return Promise.all(depPromises).then(function() {
            return loadScript(bundle.url);
        }).then(function() {
            console.log('Loaded bundle:', bundleName, bundle.polyfills);
            return 'loaded';
        });
    },
    
    loadBundles: function(bundleNames) {
        var promises = bundleNames.map(function(name) {
            return this.loadBundle(name);
        }.bind(this));
        
        return Promise.all(promises);
    }
};

// Usage - load multiple bundles
CompositePolyfills.loadBundles(['es6-basics', 'web-apis', 'observers'])
    .then(function() {
        console.log('All bundles loaded');
        initApp();
    });
Note: Proper dependency management prevents loading order issues. Bundle related polyfills together to reduce HTTP requests.

4. Tree Shaking and Dead Code Elimination

Technique Tool Configuration Savings
ES Module Imports Webpack/Rollup Import specific methods only 30-50%
Side Effect Marking package.json sideEffects "sideEffects": false 10-20%
Terser/UglifyJS Minifier dead_code: true 15-25%
Conditional Compilation Build-time flags DefinePlugin 20-40%
Babel Plugin babel-plugin-lodash Cherry-pick transforms 40-60%

Example: Tree-shakeable polyfill structure

// polyfills/index.js - ES Module entry point
export { default as arrayIncludes } from './array-includes';
export { default as objectAssign } from './object-assign';
export { default as promisePolyfill } from './promise';
export { default as fetchPolyfill } from './fetch';
export { default as intersectionObserver } from './intersection-observer';

// polyfills/array-includes.js
export default function polyfillArrayIncludes() {
    if (!Array.prototype.includes) {
        Array.prototype.includes = function(searchElement, fromIndex) {
            // Implementation
        };
    }
}

// Usage - import only what you need
import { arrayIncludes, objectAssign } from './polyfills';

arrayIncludes();
objectAssign();

// package.json
{
    "name": "my-polyfills",
    "version": "1.0.0",
    "main": "dist/index.js",
    "module": "src/index.js",
    "sideEffects": false,
    "exports": {
        ".": {
            "import": "./src/index.js",
            "require": "./dist/index.js"
        },
        "./array-includes": {
            "import": "./src/array-includes.js",
            "require": "./dist/array-includes.js"
        },
        "./object-assign": {
            "import": "./src/object-assign.js",
            "require": "./dist/object-assign.js"
        }
    }
}

// webpack.config.js
module.exports = {
    mode: 'production',
    optimization: {
        usedExports: true,
        sideEffects: true,
        minimize: true,
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    compress: {
                        dead_code: true,
                        drop_console: true,
                        drop_debugger: true,
                        pure_funcs: ['console.log']
                    }
                }
            })
        ]
    }
};

Example: Conditional compilation for polyfills

// Use webpack DefinePlugin for build-time flags
// webpack.config.js
const webpack = require('webpack');

module.exports = {
    plugins: [
        new webpack.DefinePlugin({
            'INCLUDE_IE11_POLYFILLS': JSON.stringify(process.env.TARGET_IE11 === 'true'),
            'INCLUDE_SAFARI_POLYFILLS': JSON.stringify(process.env.TARGET_SAFARI === 'true'),
            'PRODUCTION': JSON.stringify(true)
        })
    ]
};

// polyfills-conditional.js
if (INCLUDE_IE11_POLYFILLS) {
    require('./polyfills/ie11-polyfills');
}

if (INCLUDE_SAFARI_POLYFILLS) {
    require('./polyfills/safari-polyfills');
}

if (!PRODUCTION) {
    console.log('Polyfills loaded in development mode');
}

// Dead code elimination will remove unused branches
// Build: TARGET_IE11=false npm run build
// Result: IE11 polyfills completely removed from bundle
Warning: Tree shaking only works with ES modules. CommonJS modules cannot be tree-shaken. Use "sideEffects": false carefully.

5. Polyfill Versioning and Update Strategies

Strategy Versioning Scheme Update Policy Risk Level
Pinned Versions Exact version (1.2.3) Manual updates only Low
Patch Updates ~1.2.3 (1.2.x) Auto patch updates Low
Minor Updates ^1.2.3 (1.x.x) Auto minor updates Medium
Major Updates Latest (*) Breaking changes possible High
Hash-based Git SHA/Content hash Immutable references Very Low

Example: Versioned polyfill management

// polyfill-version-manager.js
var PolyfillVersionManager = {
    versions: {
        'promise': '8.1.0',
        'fetch': '3.6.2',
        'intersection-observer': '0.12.0',
        'resize-observer': '1.5.1'
    },
    
    cdn: 'https://cdn.jsdelivr.net/npm',
    
    getUrl: function(polyfillName) {
        var version = this.versions[polyfillName];
        if (!version) {
            throw new Error('No version defined for: ' + polyfillName);
        }
        
        var packageMap = {
            'promise': 'es6-promise@' + version + '/dist/es6-promise.auto.min.js',
            'fetch': 'whatwg-fetch@' + version + '/dist/fetch.umd.js',
            'intersection-observer': 'intersection-observer@' + version + '/intersection-observer.js',
            'resize-observer': 'resize-observer-polyfill@' + version + '/dist/ResizeObserver.js'
        };
        
        return this.cdn + '/' + packageMap[polyfillName];
    },
    
    // Check if update is available
    checkUpdates: function() {
        // In production, query registry for latest versions
        return fetch('https://registry.npmjs.org/es6-promise/latest')
            .then(function(res) { return res.json(); })
            .then(function(data) {
                console.log('Latest version:', data.version);
                console.log('Current version:', this.versions.promise);
                
                if (data.version !== this.versions.promise) {
                    console.log('Update available!');
                    return { hasUpdate: true, latest: data.version };
                }
                return { hasUpdate: false };
            }.bind(this));
    },
    
    // Generate integrity hash for SRI
    generateIntegrity: function(url) {
        return fetch(url)
            .then(function(response) { return response.arrayBuffer(); })
            .then(function(buffer) {
                return crypto.subtle.digest('SHA-384', buffer);
            })
            .then(function(hash) {
                var hashArray = Array.from(new Uint8Array(hash));
                var hashBase64 = btoa(String.fromCharCode.apply(null, hashArray));
                return 'sha384-' + hashBase64;
            });
    }
};

// package.json for self-hosted polyfills
{
    "dependencies": {
        "core-js": "~3.27.2",      // Patch updates only
        "whatwg-fetch": "^3.6.0",   // Minor updates allowed
        "intersection-observer": "0.12.0"  // Pinned version
    },
    "devDependencies": {
        "npm-check-updates": "^16.0.0"
    }
}

// Update check script
// npm run check-updates
{
    "scripts": {
        "check-updates": "ncu",
        "update-patches": "ncu -u -t patch",
        "update-minor": "ncu -u -t minor"
    }
}

Example: Automated polyfill update workflow

# .github/workflows/update-polyfills.yml
name: Update Polyfills

on:
    schedule:
        # Check weekly
        - cron: '0 0 * * 0'
    workflow_dispatch:

jobs:
    update:
        runs-on: ubuntu-latest
        
        steps:
            - uses: actions/checkout@v3
            
            - name: Setup Node.js
              uses: actions/setup-node@v3
              with:
                  node-version: 18
            
            - name: Install dependencies
              run: npm ci
            
            - name: Check for updates
              run: |
                  npm install -g npm-check-updates
                  ncu -u -t patch
            
            - name: Install updated dependencies
              run: npm install
            
            - name: Run tests
              run: npm test
            
            - name: Create Pull Request
              if: success()
              uses: peter-evans/create-pull-request@v4
              with:
                  title: 'chore: Update polyfill dependencies'
                  body: 'Automated update of polyfill patch versions'
                  branch: update-polyfills
                  commit-message: 'chore: Update polyfills'
Note: Use SRI hashes for CDN polyfills to ensure integrity. Pin versions for stability, update patches regularly for security.

6. Micro-polyfill Architecture Patterns

Pattern Size Scope Benefits
Single Method <1 KB One specific method Minimal overhead
Feature Group 1-3 KB Related methods Logical grouping
Ponyfill <1 KB Non-invasive alternative No prototype pollution
Shim Variable API compatibility layer Drop-in replacement
Partial Polyfill <2 KB Subset of spec Cover common cases only

Example: Micro-polyfill architecture

// Micro-polyfills: one file per method
// polyfills/micro/array-includes.js
(function() {
    if (!Array.prototype.includes) {
        Array.prototype.includes = function(searchElement, fromIndex) {
            var O = Object(this);
            var len = parseInt(O.length) || 0;
            if (len === 0) return false;
            
            var n = parseInt(fromIndex) || 0;
            var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            
            while (k < len) {
                if (O[k] === searchElement || 
                    (searchElement !== searchElement && O[k] !== O[k])) {
                    return true;
                }
                k++;
            }
            return false;
        };
    }
})();

// polyfills/micro/object-assign.js
(function() {
    if (!Object.assign) {
        Object.assign = function(target) {
            if (target == null) {
                throw new TypeError('Cannot convert undefined or null to object');
            }
            
            var to = Object(target);
            for (var i = 1; i < arguments.length; i++) {
                var nextSource = arguments[i];
                if (nextSource != null) {
                    for (var key in nextSource) {
                        if (Object.prototype.hasOwnProperty.call(nextSource, key)) {
                            to[key] = nextSource[key];
                        }
                    }
                }
            }
            return to;
        };
    }
})();

// Micro-polyfill loader
var MicroPolyfillLoader = {
    baseUrl: '/polyfills/micro/',
    
    load: function(methodName) {
        var filename = methodName.toLowerCase().replace(/[^a-z0-9]/g, '-') + '.js';
        var url = this.baseUrl + filename;
        
        return new Promise(function(resolve, reject) {
            var script = document.createElement('script');
            script.src = url;
            script.async = true;
            script.onload = function() {
                console.log('Loaded micro-polyfill:', methodName);
                resolve();
            };
            script.onerror = function() {
                reject(new Error('Failed to load: ' + methodName));
            };
            document.head.appendChild(script);
        });
    },
    
    loadMultiple: function(methodNames) {
        return Promise.all(methodNames.map(this.load.bind(this)));
    }
};

// Usage - load only what you need
MicroPolyfillLoader.loadMultiple([
    'Array.includes',
    'Object.assign',
    'String.startsWith'
]).then(function() {
    console.log('Micro-polyfills loaded');
    initApp();
});

Example: Ponyfill pattern (non-invasive)

// ponyfills/object-assign.js - Doesn't modify native prototypes
function objectAssign(target) {
    if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object');
    }
    
    var to = Object(target);
    for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource != null) {
            for (var key in nextSource) {
                if (Object.prototype.hasOwnProperty.call(nextSource, key)) {
                    to[key] = nextSource[key];
                }
            }
        }
    }
    return to;
}

// Export ponyfill
module.exports = objectAssign;

// Usage - explicit import, no prototype pollution
var objectAssign = require('./ponyfills/object-assign');

var merged = objectAssign({}, obj1, obj2);

// Or create polyfill wrapper
if (!Object.assign) {
    Object.assign = objectAssign;
}

// Ponyfill library structure
var ponyfills = {
    arrayIncludes: function(arr, searchElement, fromIndex) {
        // Implementation that doesn't modify Array.prototype
        var O = Object(arr);
        var len = parseInt(O.length) || 0;
        // ... rest of implementation
    },
    
    stringStartsWith: function(str, searchString, position) {
        // Implementation that doesn't modify String.prototype
        var pos = position > 0 ? position | 0 : 0;
        return str.substring(pos, pos + searchString.length) === searchString;
    },
    
    // Use native if available, ponyfill otherwise
    assign: Object.assign || objectAssign,
    includes: Array.prototype.includes 
        ? function(arr, val) { return arr.includes(val); }
        : function(arr, val) { return ponyfills.arrayIncludes(arr, val); }
};

module.exports = ponyfills;

Key Takeaways - Advanced Patterns

  • Lazy Loading: Reduce initial bundle by 50-70% with on-demand loading
  • Feature Flags: Enable gradual rollout and A/B testing of polyfills
  • Dependencies: Manage load order with dependency graphs and composition
  • Tree Shaking: Use ES modules and sideEffects: false for smaller bundles
  • Versioning: Pin versions for stability, use SRI hashes for security
  • Micro-polyfills: Load only specific methods needed, consider ponyfills