Build Tools and Development Workflow

1. Webpack and Polyfill Integration

Approach Configuration Use Case Bundle Impact
Entry Polyfills entry: ['core-js', './src'] Global polyfills Large bundle
ProvidePlugin Auto-inject globals Replace globals like Promise On-demand injection
Dynamic Import import() with magic comments Code splitting Separate chunks
splitChunks Vendor chunk optimization Cache polyfills separately Better caching
Polyfill Service Loader Custom webpack loader Conditional loading Minimal for modern browsers

Example: Webpack 5 polyfill configuration

// webpack.config.js
const webpack = require('webpack');
const path = require('path');

module.exports = {
    mode: 'production',
    
    entry: {
        // Separate polyfill entry
        polyfills: './src/polyfills.js',
        app: './src/index.js'
    },
    
    output: {
        filename: '[name].[contenthash].js',
        path: path.resolve(__dirname, 'dist'),
        clean: true
    },
    
    // Webpack 5 doesn't auto-polyfill Node.js modules
    resolve: {
        fallback: {
            "buffer": require.resolve("buffer/"),
            "process": require.resolve("process/browser"),
            "stream": require.resolve("stream-browserify"),
            "util": require.resolve("util/")
        }
    },
    
    plugins: [
        // Provide global polyfills automatically
        new webpack.ProvidePlugin({
            Promise: ['es6-promise', 'Promise'],
            fetch: ['whatwg-fetch', 'fetch'],
            process: 'process/browser',
            Buffer: ['buffer', 'Buffer']
        })
    ],
    
    optimization: {
        runtimeChunk: 'single',
        
        splitChunks: {
            cacheGroups: {
                // Separate polyfills into their own chunk
                polyfills: {
                    test: /[\\/]node_modules[\\/](core-js|regenerator-runtime|whatwg-fetch)[\\/]/,
                    name: 'polyfills',
                    chunks: 'all',
                    priority: 20
                },
                
                // Vendor chunk for other libraries
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendor',
                    chunks: 'all',
                    priority: 10
                }
            }
        },
        
        minimize: true,
        
        usedExports: true
    },
    
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            ['@babel/preset-env', {
                                useBuiltIns: 'usage',
                                corejs: 3,
                                targets: '> 0.25%, not dead'
                            }]
                        ]
                    }
                }
            }
        ]
    }
};

// src/polyfills.js - Manual polyfill entry
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import 'whatwg-fetch';
import 'intersection-observer';

// Or selective imports
import 'core-js/features/promise';
import 'core-js/features/array/includes';
import 'core-js/features/object/assign';

// HTML template with separate polyfill chunk
// <script src="polyfills.bundle.js"></script>
// <script src="vendor.bundle.js"></script>
// <script src="app.bundle.js"></script>

Example: Conditional polyfill loading with Webpack

// src/polyfill-loader.js
export function loadPolyfills() {
    const polyfills = [];
    
    // Check what's needed
    if (!window.Promise) {
        polyfills.push(
            import(/* webpackChunkName: "polyfill-promise" */ 'es6-promise/auto')
        );
    }
    
    if (!window.fetch) {
        polyfills.push(
            import(/* webpackChunkName: "polyfill-fetch" */ 'whatwg-fetch')
        );
    }
    
    if (!('IntersectionObserver' in window)) {
        polyfills.push(
            import(/* webpackChunkName: "polyfill-intersection-observer" */ 
                   'intersection-observer')
        );
    }
    
    return Promise.all(polyfills);
}

// src/index.js
import { loadPolyfills } from './polyfill-loader';

loadPolyfills().then(() => {
    // Now safe to use polyfilled features
    import('./app').then(app => {
        app.init();
    });
});

// Custom webpack loader for auto-injection
// webpack-polyfill-injector-loader.js
module.exports = function(source) {
    const polyfillCode = `
        // Auto-injected polyfill detection
        (function() {
            const polyfills = [];
            
            if (!window.Promise) {
                polyfills.push(import('es6-promise/auto'));
            }
            
            if (polyfills.length > 0) {
                Promise.all(polyfills).then(() => {
                    // Original code executes after polyfills load
                    ${source}
                });
            } else {
                // No polyfills needed, execute immediately
                ${source}
            }
        })();
    `;
    
    return polyfillCode;
};
Note: Webpack 5 removed automatic Node.js polyfills. Use resolve.fallback to manually configure needed polyfills for browser compatibility.

2. Babel and Transform Plugin Configuration

Plugin/Preset Purpose Configuration Impact
@babel/preset-env Smart polyfill injection useBuiltIns: 'usage' Optimal bundle size
@babel/transform-runtime Helper deduplication Avoid helper duplication Smaller output
core-js ECMAScript polyfills corejs: 3 Feature complete
regenerator-runtime async/await support Auto-injected +7 KB
Custom transforms Project-specific needs Custom plugins Variable

Example: Babel configuration for polyfills

// babel.config.js
module.exports = {
    presets: [
        ['@babel/preset-env', {
            // Automatic polyfill injection based on usage
            useBuiltIns: 'usage',
            
            // core-js version
            corejs: {
                version: 3,
                proposals: true // Include stage 3 proposals
            },
            
            // Target browsers
            targets: {
                browsers: [
                    '>0.25%',
                    'not dead',
                    'not ie 11',
                    'not op_mini all'
                ]
            },
            
            // Enable all spec transformations
            spec: false,
            
            // Loose mode for smaller output (less spec-compliant)
            loose: false,
            
            // Module transformation
            modules: false, // Keep ES modules for webpack tree-shaking
            
            // Debug output
            debug: false,
            
            // Include polyfills needed by dependencies
            include: [],
            
            // Exclude specific polyfills
            exclude: ['es.promise.finally']
        }]
    ],
    
    plugins: [
        ['@babel/plugin-transform-runtime', {
            // Don't polyfill (let preset-env handle it)
            corejs: false,
            
            // Extract Babel helpers into a module
            helpers: true,
            
            // Transform regenerator (async/await)
            regenerator: true,
            
            // Use ES modules
            useESModules: true
        }]
    ],
    
    // Environment-specific configuration
    env: {
        production: {
            plugins: [
                // Remove console.log in production
                ['transform-remove-console', { exclude: ['error', 'warn'] }]
            ]
        },
        
        test: {
            presets: [
                ['@babel/preset-env', {
                    targets: { node: 'current' }
                }]
            ]
        }
    }
};

// .browserslistrc - Alternative browser targets
> 0.25%
not dead
not ie 11
not op_mini all
last 2 versions
Firefox ESR

// package.json browserslist (another alternative)
{
    "browserslist": {
        "production": [
            ">0.2%",
            "not dead",
            "not op_mini all"
        ],
        "development": [
            "last 1 chrome version",
            "last 1 firefox version",
            "last 1 safari version"
        ],
        "legacy": [
            "ie 11"
        ]
    }
}

Example: Custom Babel plugin for polyfills

// babel-plugin-custom-polyfill.js
module.exports = function({ types: t }) {
    return {
        name: 'custom-polyfill-injector',
        
        visitor: {
            // Detect usage of specific APIs
            MemberExpression(path) {
                const { object, property } = path.node;
                
                // Detect Array.prototype.includes
                if (
                    t.isMemberExpression(object) &&
                    t.isIdentifier(object.object, { name: 'Array' }) &&
                    t.isIdentifier(object.property, { name: 'prototype' }) &&
                    t.isIdentifier(property, { name: 'includes' })
                ) {
                    // Add import at top of file
                    const program = path.findParent(p => p.isProgram());
                    const importDeclaration = t.importDeclaration(
                        [],
                        t.stringLiteral('core-js/features/array/includes')
                    );
                    
                    // Check if import already exists
                    const hasImport = program.node.body.some(node =>
                        t.isImportDeclaration(node) &&
                        node.source.value === 'core-js/features/array/includes'
                    );
                    
                    if (!hasImport) {
                        program.unshiftContainer('body', importDeclaration);
                    }
                }
            },
            
            // Detect Promise usage
            Identifier(path) {
                if (path.node.name === 'Promise' && path.isReferencedIdentifier()) {
                    const program = path.findParent(p => p.isProgram());
                    const importDeclaration = t.importDeclaration(
                        [],
                        t.stringLiteral('core-js/features/promise')
                    );
                    
                    const hasImport = program.node.body.some(node =>
                        t.isImportDeclaration(node) &&
                        node.source.value === 'core-js/features/promise'
                    );
                    
                    if (!hasImport) {
                        program.unshiftContainer('body', importDeclaration);
                    }
                }
            }
        }
    };
};
Note: Use useBuiltIns: 'usage' for automatic polyfill injection based on code analysis. Reduces bundle size by 40-60% compared to 'entry' mode.

3. Rollup and ES Module Polyfill Building

Plugin Purpose Configuration Output
@rollup/plugin-babel Transform and inject polyfills Babel integration ES5 + polyfills
@rollup/plugin-node-resolve Resolve node_modules Find polyfill packages Bundled dependencies
@rollup/plugin-commonjs Convert CJS to ESM Legacy polyfills ES modules
@rollup/plugin-replace Build-time replacements Environment variables Optimized code
rollup-plugin-terser Minification Dead code elimination Smaller bundles

Example: Rollup configuration for polyfills

// rollup.config.js
import babel from '@rollup/plugin-babel';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import { terser } from 'rollup-plugin-terser';

export default [
    // Modern build (ES2015+)
    {
        input: 'src/index.js',
        
        output: {
            file: 'dist/bundle.modern.js',
            format: 'esm',
            sourcemap: true
        },
        
        plugins: [
            replace({
                'process.env.NODE_ENV': JSON.stringify('production'),
                preventAssignment: true
            }),
            
            resolve({
                browser: true,
                preferBuiltins: false
            }),
            
            commonjs(),
            
            babel({
                babelHelpers: 'bundled',
                exclude: 'node_modules/**',
                presets: [
                    ['@babel/preset-env', {
                        targets: { esmodules: true },
                        bugfixes: true,
                        modules: false,
                        useBuiltIns: false // No polyfills for modern build
                    }]
                ]
            }),
            
            terser({
                ecma: 2015,
                module: true,
                compress: {
                    passes: 2,
                    pure_getters: true
                }
            })
        ]
    },
    
    // Legacy build (ES5 + polyfills)
    {
        input: 'src/index.js',
        
        output: {
            file: 'dist/bundle.legacy.js',
            format: 'iife',
            name: 'MyApp',
            sourcemap: true
        },
        
        plugins: [
            replace({
                'process.env.NODE_ENV': JSON.stringify('production'),
                preventAssignment: true
            }),
            
            resolve({
                browser: true,
                preferBuiltins: false
            }),
            
            commonjs(),
            
            babel({
                babelHelpers: 'bundled',
                exclude: 'node_modules/**',
                presets: [
                    ['@babel/preset-env', {
                        targets: 'ie 11',
                        modules: false,
                        useBuiltIns: 'usage',
                        corejs: 3
                    }]
                ]
            }),
            
            terser({
                ecma: 5,
                compress: {
                    passes: 2
                },
                safari10: true
            })
        ]
    },
    
    // Library build (UMD)
    {
        input: 'src/lib.js',
        
        output: [
            {
                file: 'dist/lib.umd.js',
                format: 'umd',
                name: 'MyLib',
                sourcemap: true
            },
            {
                file: 'dist/lib.esm.js',
                format: 'esm',
                sourcemap: true
            }
        ],
        
        external: ['core-js'], // Don't bundle polyfills for libraries
        
        plugins: [
            resolve(),
            commonjs(),
            
            babel({
                babelHelpers: 'runtime',
                exclude: 'node_modules/**',
                plugins: [
                    ['@babel/plugin-transform-runtime', {
                        corejs: 3,
                        helpers: true,
                        regenerator: true,
                        useESModules: true
                    }]
                ]
            }),
            
            terser()
        ]
    }
];

// package.json exports for dual builds
{
    "name": "my-library",
    "version": "1.0.0",
    "main": "dist/lib.umd.js",
    "module": "dist/lib.esm.js",
    "unpkg": "dist/lib.umd.js",
    "types": "dist/types/index.d.ts",
    "exports": {
        ".": {
            "types": "./dist/types/index.d.ts",
            "import": "./dist/lib.esm.js",
            "require": "./dist/lib.umd.js"
        }
    },
    "files": [
        "dist"
    ]
}
Note: Rollup excels at tree-shaking ES modules. Create separate modern and legacy builds for optimal performance across browsers.

4. PostCSS and CSS Polyfill Processing

Plugin Polyfills Browser Support Output
Autoprefixer Vendor prefixes Based on browserslist -webkit-, -moz-, etc.
postcss-preset-env Modern CSS features Stage-based adoption Transformed CSS
postcss-custom-properties CSS variables IE11 Static values
postcss-flexbugs-fixes Flexbox bugs All browsers Workarounds
postcss-normalize CSS normalize/reset Cross-browser Baseline styles

Example: PostCSS configuration for CSS polyfills

// postcss.config.js
module.exports = {
    plugins: [
        // Modern CSS features
        require('postcss-preset-env')({
            stage: 3, // Stage 3+ features
            features: {
                'custom-properties': {
                    preserve: false // Convert CSS variables to static values
                },
                'custom-media-queries': true,
                'nesting-rules': true,
                'color-mod-function': { unresolved: 'warn' }
            },
            browsers: 'last 2 versions',
            autoprefixer: {
                flexbox: 'no-2009',
                grid: 'autoplace'
            }
        }),
        
        // Autoprefixer
        require('autoprefixer')({
            overrideBrowserslist: [
                '> 1%',
                'last 2 versions',
                'not dead',
                'IE 11'
            ],
            grid: 'autoplace',
            flexbox: 'no-2009'
        }),
        
        // Flexbox bug fixes
        require('postcss-flexbugs-fixes'),
        
        // CSS custom properties polyfill
        require('postcss-custom-properties')({
            preserve: true, // Keep original for modern browsers
            importFrom: './src/css-variables.css'
        }),
        
        // Normalize CSS
        require('postcss-normalize')({
            forceImport: true
        }),
        
        // Minification (production only)
        process.env.NODE_ENV === 'production' ? require('cssnano')({
            preset: ['default', {
                discardComments: {
                    removeAll: true
                },
                normalizeWhitespace: true
            }]
        }) : false
    ].filter(Boolean)
};

// Input CSS
:root {
    --primary-color: #007bff;
    --spacing: 1rem;
}

.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: var(--spacing);
    color: var(--primary-color);
}

.flex-container {
    display: flex;
    flex-wrap: wrap;
}

.custom-selector:has(> .child) {
    background: color-mod(var(--primary-color) alpha(50%));
}

// Output CSS (after PostCSS)
.container {
    display: -ms-grid;
    display: grid;
    -ms-grid-columns: (minmax(250px, 1fr))[auto-fit];
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1rem;
    color: #007bff;
}

.flex-container {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
}

// Fallback for :has() selector
.custom-selector {
    background: rgba(0, 123, 255, 0.5);
}
Note: PostCSS can polyfill modern CSS features at build time. Use postcss-preset-env for automatic feature detection and transformation.

5. ESLint Rules for Polyfill Code Quality

Rule Category ESLint Rules Purpose Severity
ES5 Compatibility no-restricted-syntax Prevent modern syntax Error
Globals no-undef, no-global-assign Protect global scope Error
Best Practices no-extend-native Safe prototype extension Warning
Security no-eval, no-new-func Prevent code injection Error
Performance no-loop-func Avoid closure overhead Warning

Example: ESLint configuration for polyfills

// .eslintrc.js
module.exports = {
    env: {
        browser: true,
        es6: true
    },
    
    extends: [
        'eslint:recommended'
    ],
    
    parserOptions: {
        ecmaVersion: 2015,
        sourceType: 'module'
    },
    
    rules: {
        // Prevent extending native prototypes unsafely
        'no-extend-native': 'error',
        
        // Protect global objects
        'no-global-assign': 'error',
        'no-undef': 'error',
        
        // Security rules
        'no-eval': 'error',
        'no-new-func': 'error',
        'no-implied-eval': 'error',
        
        // Best practices
        'eqeqeq': ['error', 'always'],
        'no-proto': 'error',
        'no-with': 'error',
        
        // ES5 compatibility (for polyfills targeting old browsers)
        'no-restricted-syntax': [
            'error',
            {
                selector: 'ArrowFunctionExpression',
                message: 'Arrow functions not supported in ES5'
            },
            {
                selector: 'TemplateLiteral',
                message: 'Template literals not supported in ES5'
            },
            {
                selector: 'SpreadElement',
                message: 'Spread operator not supported in ES5'
            }
        ],
        
        // Prevent console in production
        'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
        
        // Performance
        'no-loop-func': 'warn'
    },
    
    // Override for polyfill files
    overrides: [
        {
            files: ['**/polyfills/**/*.js', '**/*.polyfill.js'],
            rules: {
                // Allow extending native prototypes in polyfill files
                'no-extend-native': 'off',
                
                // Allow function constructors for polyfills
                'no-new-func': 'off',
                
                // Polyfills need to check globals
                'no-undef': 'warn'
            }
        },
        
        // Stricter rules for modern code
        {
            files: ['src/**/*.js'],
            excludedFiles: ['src/polyfills/**/*.js'],
            parserOptions: {
                ecmaVersion: 2022
            },
            rules: {
                'no-var': 'error',
                'prefer-const': 'error',
                'prefer-arrow-callback': 'warn'
            }
        }
    ]
};

// Custom ESLint plugin for polyfill validation
// eslint-plugin-polyfill-checker.js
module.exports = {
    rules: {
        'check-feature-detection': {
            meta: {
                type: 'problem',
                docs: {
                    description: 'Ensure polyfills include feature detection'
                }
            },
            
            create(context) {
                return {
                    AssignmentExpression(node) {
                        // Check if assigning to prototype
                        if (
                            node.left.type === 'MemberExpression' &&
                            node.left.property.name === 'prototype'
                        ) {
                            // Look for if statement checking existence
                            const parent = context.getAncestors()[context.getAncestors().length - 2];
                            
                            if (!parent || parent.type !== 'IfStatement') {
                                context.report({
                                    node,
                                    message: 'Polyfill should include feature detection guard'
                                });
                            }
                        }
                    }
                };
            }
        },
        
        'no-unsafe-polyfill': {
            meta: {
                type: 'problem',
                docs: {
                    description: 'Prevent unsafe polyfill patterns'
                }
            },
            
            create(context) {
                return {
                    MemberExpression(node) {
                        // Detect Object.prototype modification
                        if (
                            node.object.name === 'Object' &&
                            node.property.name === 'prototype'
                        ) {
                            const parent = context.getAncestors()[context.getAncestors().length - 1];
                            
                            if (parent.type === 'AssignmentExpression') {
                                context.report({
                                    node,
                                    message: 'Modifying Object.prototype is dangerous'
                                });
                            }
                        }
                    }
                };
            }
        }
    }
};
Warning: Configure ESLint overrides for polyfill files to allow necessary prototype extensions while maintaining strict rules for application code.

6. TypeScript Declaration Files for Polyfills

Approach File Type Use Case Type Safety
Ambient Declarations .d.ts files Global polyfills Full type checking
Module Augmentation declare module Extend existing types Merged declarations
Global Augmentation declare global Add global types Global scope
Triple-slash /// <reference /> Include type definitions Explicit imports
@types packages npm packages Published type definitions Community maintained

Example: TypeScript declarations for polyfills

// types/polyfills.d.ts - Ambient declarations
/// <reference lib="es2015" />

// Extend Array interface with includes method
interface Array<T> {
    includes(searchElement: T, fromIndex?: number): boolean;
}

// Extend Object with assign
interface ObjectConstructor {
    assign<T, U>(target: T, source: U): T & U;
    assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;
    assign(target: object, ...sources: any[]): any;
}

// Extend String with startsWith and endsWith
interface String {
    startsWith(searchString: string, position?: number): boolean;
    endsWith(searchString: string, endPosition?: number): boolean;
    includes(searchString: string, position?: number): boolean;
    padStart(targetLength: number, padString?: string): string;
    padEnd(targetLength: number, padString?: string): string;
}

// Promise polyfill types
interface PromiseConstructor {
    allSettled<T>(promises: Array<Promise<T>>): Promise<Array<PromiseSettledResult<T>>>;
    any<T>(promises: Array<Promise<T>>): Promise<T>;
}

type PromiseSettledResult<T> = PromiseFulfilledResult<T> | PromiseRejectedResult;

interface PromiseFulfilledResult<T> {
    status: 'fulfilled';
    value: T;
}

interface PromiseRejectedResult {
    status: 'rejected';
    reason: any;
}

// Web APIs
interface Window {
    IntersectionObserver?: typeof IntersectionObserver;
    ResizeObserver?: typeof ResizeObserver;
    fetch?: typeof fetch;
}

// IntersectionObserver types
interface IntersectionObserverInit {
    root?: Element | null;
    rootMargin?: string;
    threshold?: number | number[];
}

interface IntersectionObserverEntry {
    readonly boundingClientRect: DOMRectReadOnly;
    readonly intersectionRatio: number;
    readonly intersectionRect: DOMRectReadOnly;
    readonly isIntersecting: boolean;
    readonly rootBounds: DOMRectReadOnly | null;
    readonly target: Element;
    readonly time: number;
}

type IntersectionObserverCallback = (
    entries: IntersectionObserverEntry[],
    observer: IntersectionObserver
) => void;

declare class IntersectionObserver {
    constructor(callback: IntersectionObserverCallback, options?: IntersectionObserverInit);
    readonly root: Element | null;
    readonly rootMargin: string;
    readonly thresholds: ReadonlyArray<number>;
    disconnect(): void;
    observe(target: Element): void;
    takeRecords(): IntersectionObserverEntry[];
    unobserve(target: Element): void;
}

// Module augmentation example
declare module 'my-polyfill-library' {
    export function polyfillAll(): void;
    export function polyfillFeature(featureName: string): void;
    
    export interface PolyfillConfig {
        features?: string[];
        force?: boolean;
        debug?: boolean;
    }
    
    export function configure(config: PolyfillConfig): void;
}

// Global augmentation in module
export {};

declare global {
    interface Window {
        myPolyfillLibrary: {
            version: string;
            isPolyfilled(feature: string): boolean;
        };
    }
}

// tsconfig.json configuration
{
    "compilerOptions": {
        "target": "ES5",
        "lib": ["ES2015", "DOM"],
        "module": "ESNext",
        "moduleResolution": "node",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": false,
        "types": ["node"],
        "typeRoots": ["./types", "./node_modules/@types"],
        "declaration": true,
        "declarationMap": true,
        "sourceMap": true
    },
    "include": ["src/**/*", "types/**/*"],
    "exclude": ["node_modules", "dist"]
}

Example: Publishing TypeScript polyfill library

// src/index.ts - Polyfill library with types
export function polyfillArrayIncludes(): void {
    if (!Array.prototype.includes) {
        Array.prototype.includes = function<T>(
            this: T[],
            searchElement: T,
            fromIndex?: number
        ): boolean {
            const O = Object(this);
            const len = parseInt(String(O.length)) || 0;
            
            if (len === 0) {
                return false;
            }
            
            const n = parseInt(String(fromIndex)) || 0;
            let 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;
        };
    }
}

export function polyfillObjectAssign(): void {
    if (!Object.assign) {
        Object.assign = function<T extends object, U extends object>(
            target: T,
            ...sources: U[]
        ): T & U {
            if (target == null) {
                throw new TypeError('Cannot convert undefined or null to object');
            }
            
            const to = Object(target) as T & U;
            
            for (const source of sources) {
                if (source != null) {
                    for (const key in source) {
                        if (Object.prototype.hasOwnProperty.call(source, key)) {
                            (to as any)[key] = source[key];
                        }
                    }
                }
            }
            
            return to;
        };
    }
}

// Generate declaration files
// dist/index.d.ts (auto-generated by tsc)
export declare function polyfillArrayIncludes(): void;
export declare function polyfillObjectAssign(): void;

// package.json for TypeScript library
{
    "name": "my-polyfill-library",
    "version": "1.0.0",
    "main": "dist/index.js",
    "module": "dist/index.esm.js",
    "types": "dist/index.d.ts",
    "typings": "dist/index.d.ts",
    "files": [
        "dist",
        "types"
    ],
    "scripts": {
        "build": "tsc && rollup -c",
        "typecheck": "tsc --noEmit"
    }
}

Key Takeaways - Build Tools & Workflow

  • Webpack: Use splitChunks for separate polyfill bundles, ProvidePlugin for globals
  • Babel: useBuiltIns: 'usage' reduces bundle size by 40-60%
  • Rollup: Excellent tree-shaking, create modern + legacy dual builds
  • PostCSS: Polyfill modern CSS features at build time with preset-env
  • ESLint: Configure overrides for polyfill files, enforce safety rules
  • TypeScript: Provide .d.ts files for type safety with polyfilled features