Saltar a contenido

Webpack Cheat Sheet

(Note: "Cheatsheet" is typically translated as "Hoja de referencia rápida")

Webpack - Static Module Bundler

Webpack es un empaquetador de módulos estáticos para aplicaciones JavaScript modernas. Cuando webpack procesa su aplicación, internamente construye un grafo de dependencias desde uno o más puntos de entrada y luego combina todos los módulos que su proyecto necesita en uno o más paquetes.

(This section appears to be empty in the original text)

Tabla de Contenidos

Would you like me to continue translating the rest of the document? If so, I'll need the specific text for sections 4-20 to provide accurate translations.```bash

Install webpack globally

npm install -g webpack webpack-cli

Check version

webpack --version

### Local Installation (Recommended)
```bash
# Initialize npm project
npm init -y

# Install webpack locally
npm install --save-dev webpack webpack-cli

# Install webpack dev server
npm install --save-dev webpack-dev-server

# Install common loaders and plugins
npm install --save-dev html-webpack-plugin css-loader style-loader file-loader url-loader

Package.json Scripts

{
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack --mode development",
    "start": "webpack serve --mode development",
    "watch": "webpack --mode development --watch"
  }
}

Basic Configuration

Minimal webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

Complete Basic Configuration

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource'
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ]
};

TypeScript Configuration

const path = require('path');

module.exports = {
  entry: './src/index.ts',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js']
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

Entry Points

Single Entry Point

module.exports = {
  entry: './src/index.js'
};

Multiple Entry Points

module.exports = {
  entry: {
    main: './src/index.js',
    vendor: './src/vendor.js'
  }
};

Dynamic Entry Points

module.exports = {
  entry: () => {
    return {
      main: './src/index.js',
      admin: './src/admin.js'
    };
  }
};

Entry with Dependencies

module.exports = {
  entry: {
    main: {
      import: './src/index.js',
      dependOn: 'shared'
    },
    admin: {
      import: './src/admin.js',
      dependOn: 'shared'
    },
    shared: 'lodash'
  }
};

Output

Basic Output Configuration

const path = require('path');

module.exports = {
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

Multiple Entry Output

module.exports = {
  entry: {
    main: './src/index.js',
    admin: './src/admin.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

Output with Hashing

module.exports = {
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true
  }
};

Public Path Configuration

module.exports = {
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/assets/'
  }
};

Library Output

module.exports = {
  output: {
    filename: 'my-library.js',
    path: path.resolve(__dirname, 'dist'),
    library: {
      name: 'MyLibrary',
      type: 'umd'
    }
  }
};

Loaders

CSS Loaders

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.s[ac]ss$/i,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.less$/i,
        use: ['style-loader', 'css-loader', 'less-loader']
      }
    ]
  }
};

JavaScript Loaders

module.exports = {
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      },
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  }
};

File Loaders

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource'
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource'
      },
      {
        test: /\.(csv|tsv)$/i,
        use: ['csv-loader']
      },
      {
        test: /\.xml$/i,
        use: ['xml-loader']
      }
    ]
  }
};

Asset Modules

module.exports = {
  module: {
    rules: [
      {
        test: /\.png/,
        type: 'asset/resource'
      },
      {
        test: /\.html/,
        type: 'asset/resource'
      },
      {
        test: /\.txt/,
        type: 'asset/source'
      },
      {
        test: /\.jpg/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 4 * 1024 // 4kb
          }
        }
      }
    ]
  }
};

Loader Options

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              sourceMap: true
            }
          }
        ]
      }
    ]
  }
};

Plugins

HTML Webpack Plugin

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html',
      inject: 'body'
    })
  ]
};

Extract CSS Plugin

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css'
    })
  ]
};

Define Plugin

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production'),
      'process.env.API_URL': JSON.stringify('https://api.example.com')
    })
  ]
};

Copy Webpack Plugin

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  plugins: [
    new CopyWebpackPlugin({
      patterns: [
        { from: 'public', to: 'public' },
        { from: 'assets/images', to: 'images' }
      ]
    })
  ]
};

Bundle Analyzer Plugin

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      openAnalyzer: false
    })
  ]
};

Clean Webpack Plugin

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  plugins: [
    new CleanWebpackPlugin()
  ]
};

Mode

Development Mode

module.exports = {
  mode: 'development',
  devtool: 'eval-source-map'
};

Production Mode

module.exports = {
  mode: 'production',
  devtool: 'source-map'
};

Mode-specific Configuration

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';

  return {
    mode: argv.mode,
    devtool: isProduction ? 'source-map' : 'eval-source-map',
    optimization: {
      minimize: isProduction
    }
  };
};

Development Server

Basic Dev Server

module.exports = {
  devServer: {
    static: './dist',
    port: 3000,
    open: true
  }
};

Advanced Dev Server Configuration

module.exports = {
  devServer: {
    static: {
      directory: path.join(__dirname, 'dist')
    },
    compress: true,
    port: 3000,
    hot: true,
    open: true,
    historyApiFallback: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
};

HTTPS Dev Server

module.exports = {
  devServer: {
    https: true,
    // or with custom certificates
    https: {
      key: fs.readFileSync('/path/to/server.key'),
      cert: fs.readFileSync('/path/to/server.crt'),
      ca: fs.readFileSync('/path/to/ca.pem')
    }
  }
};

Code Splitting

Entry Point Splitting

module.exports = {
  entry: {
    main: './src/index.js',
    vendor: './src/vendor.js'
  }
};

Dynamic Imports

// In your JavaScript code
import('./math.js').then(math => {
  console.log(math.add(16, 26));
});

// Or with async/await
async function loadMath() {
  const math = await import('./math.js');
  return math.add(16, 26);
}

SplitChunks Plugin

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        },
        common: {
          name: 'common',
          minChunks: 2,
          chunks: 'all',
          enforce: true
        }
      }
    }
  }
};

Advanced Code Splitting

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 20000,
      maxSize: 244000,
      cacheGroups: {
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        },
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          reuseExistingChunk: true
        },
        react: {
          test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
          name: 'react',
          chunks: 'all'
        }
      }
    }
  }
};

Optimization

Minification

const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true
          }
        }
      })
    ]
  }
};

CSS Optimization

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [
      new CssMinimizerPlugin()
    ]
  }
};
```### Eliminación de Código Muerto (Tree Shaking)
```javascript
module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true,
    sideEffects: false
  }
};
```### Fragmento de Tiempo de Ejecución (Runtime Chunk)
```javascript
module.exports = {
  optimization: {
    runtimeChunk: 'single'
  }
};
```### Concatenación de Módulos
```javascript
module.exports = {
  optimization: {
    concatenateModules: true
  }
};
```## Resolución de Módulos
```javascript
const path = require('path');

module.exports = {
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      'components': path.resolve(__dirname, 'src/components'),
      'utils': path.resolve(__dirname, 'src/utils')
    },
    modules: [
      'node_modules',
      path.resolve(__dirname, 'src')
    ]
  }
};
```### Configuración de Resolución
```javascript
module.exports = {
  resolve: {
    fallback: {
      "fs": false,
      "path": require.resolve("path-browserify"),
      "crypto": require.resolve("crypto-browserify")
    }
  }
};
```### Resolución de Respaldo (Resolve Fallback)
```javascript
const webpack = require('webpack');

module.exports = {
  devServer: {
    hot: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
};
```## Reemplazo de Módulo Caliente (Hot Module Replacement)
```javascript
// In your JavaScript modules
if (module.hot) {
  module.hot.accept('./library.js', function() {
    console.log('Accepting the updated library module!');
    // Re-render or update your app
  });
}
```### Habilitar HMR
```javascript
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.[jt]sx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              plugins: ['react-refresh/babel']
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new ReactRefreshWebpackPlugin()
  ]
};
```### HMR en Código
```javascript
const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      'process.env.API_URL': JSON.stringify(process.env.API_URL || 'http://localhost:3000')
    })
  ]
};
```### Recarga Caliente de React (React Hot Reload)
```javascript
module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';

  return {
    mode: argv.mode,
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(argv.mode),
        'process.env.API_URL': JSON.stringify(
          isProduction ? 'https://api.production.com' : 'http://localhost:3000'
        )
      })
    ]
  };
};
```## Variables de Entorno
```javascript
const Dotenv = require('dotenv-webpack');

module.exports = {
  plugins: [
    new Dotenv({
      path: './.env',
      safe: true,
      systemvars: true
    })
  ]
};
```### DefinePlugin para Variables de Entorno
```javascript
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true
      }
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css'
    })
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true
          }
        }
      }),
      new CssMinimizerPlugin()
    ],
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    },
    runtimeChunk: 'single'
  }
};
```### Configuración Específica de Entorno
```json
{
  "scripts": {
    "build": "webpack --mode production",
    "build:analyze": "webpack --mode production --env analyze",
    "build:stats": "webpack --mode production --json > stats.json"
  }
}
```### Plugin DotEnv
```javascript
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    home: './src/home.js',
    about: './src/about.js',
    contact: './src/contact.js'
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'home.html',
      template: './src/home.html',
      chunks: ['home']
    }),
    new HtmlWebpackPlugin({
      filename: 'about.html',
      template: './src/about.html',
      chunks: ['about']
    }),
    new HtmlWebpackPlugin({
      filename: 'contact.html',
      template: './src/contact.html',
      chunks: ['contact']
    })
  ]
};
```## Compilación de Producción
```javascript
const ModuleFederationPlugin = require('@module-federation/webpack');

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'shell',
      remotes: {
        mfe1: 'mfe1@http://localhost:3001/remoteEntry.js',
        mfe2: 'mfe2@http://localhost:3002/remoteEntry.js'
      }
    })
  ]
};
```### Configuración de Producción
```javascript
const WorkboxPlugin = require('workbox-webpack-plugin');

module.exports = {
  plugins: [
    new WorkboxPlugin.GenerateSW({
      clientsClaim: true,
      skipWaiting: true
    })
  ]
};
```### Scripts de Compilación
```javascript
// custom-loader.js
module.exports = function(source) {
  // Transform the source
  return `export default ${JSON.stringify(source)}`;
};

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.custom$/,
        use: path.resolve(__dirname, 'custom-loader.js')
      }
    ]
  }
};
```## Configuración Avanzada
```javascript
class MyCustomPlugin {
  apply(compiler) {
    compiler.hooks.emit.tapAsync('MyCustomPlugin', (compilation, callback) => {
      console.log('This is an example plugin!');
      callback();
    });
  }
}

module.exports = {
  plugins: [
    new MyCustomPlugin()
  ]
};
```### Aplicación Multipágina
```javascript
module.exports = {
  performance: {
    maxAssetSize: 250000,
    maxEntrypointSize: 250000,
    hints: 'warning'
  }
};
```### Configuración de Micro-frontends
```javascript
// Dynamic imports for lazy loading
const LazyComponent = React.lazy(() => import('./LazyComponent'));

// Webpack magic comments
import(
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  './modules/my-module.js'
);
```### Prefetching and Preloading
```javascript
// Prefetch
import(
  /* webpackPrefetch: true */
  './modules/LoginModal.js'
);

// Preload
import(
  /* webpackPreload: true */
  './modules/ChartingLibrary.js'
);
```### Análisis de Bundle
```bash
# Generate stats file
webpack --profile --json > stats.json

# Analyze with webpack-bundle-analyzer
npx webpack-bundle-analyzer stats.json

# Use webpack-bundle-analyzer plugin
npm install --save-dev webpack-bundle-analyzer
```## Resolución de Problemas

### Problemas Comunes y Soluciones

#### Módulo No Encontrado
```javascript
// Check resolve configuration
module.exports = {
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  }
};

Problemas de Memoria

# Increase Node.js memory limit
node --max-old-space-size=4096 node_modules/.bin/webpack

# Or in package.json
{
  "scripts": {
    "build": "node --max-old-space-size=4096 node_modules/.bin/webpack"
  }
}

Tiempos de Compilación Lentos

module.exports = {
  // Use cache
  cache: {
    type: 'filesystem'
  },

  // Exclude node_modules from babel-loader
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      }
    ]
  },

  // Use thread-loader for expensive loaders
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          'thread-loader',
          'babel-loader'
        ]
      }
    ]
  }
};

Problemas de Source Map

module.exports = {
  // Different source map options
  devtool: 'eval-source-map', // Development
  devtool: 'source-map', // Production
  devtool: 'cheap-module-source-map', // Faster builds
  devtool: false // No source maps
};

Configuración de Depuración

module.exports = {
  stats: {
    colors: true,
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false
  }
};

Mejores Prácticas

Organización de Configuración

// webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ]
};

// webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-source-map',
  devServer: {
    static: './dist'
  }
});

// webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  devtool: 'source-map'
});

Optimización de Rendimiento

  • Usar modo de producción para optimizaciones
  • Habilitar tree shaking para eliminar código muerto
  • Dividir chunks para mejorar el caché
  • Usar hash de contenido para caché a largo plazo
  • Minimizar tamaño de bundle con loaders y plugins adecuados

Experiencia de Desarrollo

  • Usar HMR para desarrollo más rápido
  • Configurar source maps para depuración
  • Configurar servidor de desarrollo con proxy para llamadas API
  • Usar webpack-bundle-analyzer para entender la composición del bundle

Organización de Código

  • Separar configuración para diferentes entornos
  • Usar aliases para importaciones más limpias
  • Organizar loaders por tipo de archivo
  • Agrupar plugins relacionados

Resumen

Webpack es un potente y flexible module bundler que puede manejar requisitos de compilación complejos para aplicaciones web modernas. Características principales incluyen:

  • Bundling de Módulos: Combina módulos en bundles optimizados
  • Loaders: Transforman archivos durante el proceso de compilación
  • Plugins: Extienden la funcionalidad de webpack
  • Code Splitting: Divide código en chunks más pequeños para mejor rendimiento
  • Hot Module Replacement: Actualiza módulos sin recargar la página
  • Tree Shaking: Elimina código no utilizado de los bundles
  • Gestión de Assets: Maneja diversos tipos de archivos y assets

Dominando la configuración de webpack y siguiendo mejores prácticas, puedes crear procesos de compilación eficientes que mejoran tanto la experiencia de desarrollo como el rendimiento de la aplicación.