Saltar a contenido

Webpack Cheatsheet

■h1 títuloWebpack - Módulo estadístico Bundler "Clase de inscripción" Webpack es un paquete de módulos estáticos para aplicaciones JavaScript modernas. Cuando webpack procesa su aplicación, construye internamente un gráfico de dependencia de uno o más puntos de entrada y luego combina cada módulo que su proyecto necesita en uno o más paquetes. ▪/p] ■/div titulada

########################################################################################################################################################################################################################################################## Copiar todos los comandos
########################################################################################################################################################################################################################################################## Generar PDF seleccionado/button

■/div titulada ■/div titulada

Cuadro de contenidos

Instalación

Instalación global

# Install webpack globally
npm install -g webpack webpack-cli

# Check version
webpack --version

Instalación local (recomendada)

# 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

Paquete.json Scripts

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

Configuración básica

Minimal webpack.config.js

const path = require('path');

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

Configuración básica completa

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'
    })
  ]
};

Configuración TipoScript

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')
  }
};

Puntos de entrada

Punto de entrada único

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

Múltiples puntos de entrada

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

Puntos de entrada dinámicos

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

Entrada con dependencias

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

Producto

Configuración de salida básica

const path = require('path');

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

Múltiples entradas

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

Producto con Hashing

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

Configuración del Sendero Público

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

Producto de la Biblioteca

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

Cargadores

CSS Cargadores

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']
      }
    ]
  }
};

Cargadores de JavaScript

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/
      }
    ]
  }
};

Cargadores de archivos

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']
      }
    ]
  }
};

Módulos de activos

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
          }
        }
      }
    ]
  }
};

Opciones de préstamo

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'
    })
  ]
};

Extracto 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')
    })
  ]
};

Copiado 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
    })
  ]
};

Plugin Webpack limpio

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

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

Modo

Modo de desarrollo

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

Modo de producción

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

Modo específico Configuración

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

Servidor de Dev básico

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

Configuración avanzada del servidor de Dev

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')
    }
  }
};

Código de división

Punto de entrada

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

Importaciones dinámicas

// 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);
}

Plugin de SplitChunks

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

Código avanzado

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'
        }
      }
    }
  }
};

Optimización

Minificación

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

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

CSS Optimización

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

module.exports = {
  optimization: {
    minimizer: [
      new CssMinimizerPlugin()
    ]
  }
};

Árbol sacudiendo

module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true,
    sideEffects: false
  }
};

Runtime Chunk

module.exports = {
  optimization: {
    runtimeChunk: 'single'
  }
};

Módulo Concatenación

module.exports = {
  optimization: {
    concatenateModules: true
  }
};

Resolución

Configuración de solución

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')
    ]
  }
};

Resolver Fallback

module.exports = {
  resolve: {
    fallback: {
      "fs": false,
      "path": require.resolve("path-browserify"),
      "crypto": require.resolve("crypto-browserify")
    }
  }
};
```_

## Reemplazamiento del módulo caliente

### HMR HM
```javascript
const webpack = require('webpack');

module.exports = {
  devServer: {
    hot: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
};

HMR in Code

// 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
  });
}

React Recarga caliente

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()
  ]
};

Medio ambiente

DefinePlugin for Environment Variables

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')
    })
  ]
};

Medio ambiente específico Configuración

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'
        )
      })
    ]
  };
};
```_

### DotEnv Plugin
```javascript
const Dotenv = require('dotenv-webpack');

module.exports = {
  plugins: [
    new Dotenv({
      path: './.env',
      safe: true,
      systemvars: true
    })
  ]
};

Producción

Configuración de producción

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'
  }
};

Construir scripts

{
  "scripts": {
    "build": "webpack --mode production",
    "build:analyze": "webpack --mode production --env analyze",
    "build:stats": "webpack --mode production --json > stats.json"
  }
}

Configuración avanzada

Aplicación multipágina

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']
    })
  ]
};

Micro-frontends Configuración

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'
      }
    })
  ]
};

Aplicación Web progresiva

const WorkboxPlugin = require('workbox-webpack-plugin');

module.exports = {
  plugins: [
    new WorkboxPlugin.GenerateSW({
      clientsClaim: true,
      skipWaiting: true
    })
  ]
};

Cargadores personalizados

// 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')
      }
    ]
  }
};

Plugins personalizados

class MyCustomPlugin {
  apply(compiler) {
    compiler.hooks.emit.tapAsync('MyCustomPlugin', (compilation, callback) => {
      console.log('This is an example plugin!');
      callback();
    });
  }
}

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

Ejecución

Presupuestos de ejecución

module.exports = {
  performance: {
    maxAssetSize: 250000,
    maxEntrypointSize: 250000,
    hints: 'warning'
  }
};

Lazy Cargando

// 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 y Preloading

// Prefetch
import(
  /* webpackPrefetch: true */
  './modules/LoginModal.js'
);

// Preload
import(
  /* webpackPreload: true */
  './modules/ChartingLibrary.js'
);

Bundle Analysis

# 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

Solución de problemas

Problemas y soluciones comunes

Módulo no encontrado

// Check resolve configuration
module.exports = {
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  }
};

Cuestiones 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 construcció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'
        ]
      }
    ]
  }
};

Source Map Issues

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
  }
};

Buenas prácticas

Configuration Organization

```javascript // 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 del rendimiento

  • Use modo de producción para optimizaciones
  • Hable árbol de afeitar para eliminar el código muerto
  • Split chunks para mejorar el caching
  • Utilizar el contenido para el caché a largo plazo
  • Minimizar el tamaño del paquete con cargadores y plugins adecuados

Development Experience

  • Use HMR para un desarrollo más rápido
  • Configurar mapas fuente para depurar
  • Set up dev server con proxy para llamadas API
  • Use webpack-bundle-analyzer para entender la composición del paquete

Code Organization

  • Configuración separada para diferentes entornos
  • Use alias para las importaciones más limpias
  • Organizar cargadores por tipo de archivo
  • Grupo de plugins relacionados juntos

-...

Resumen

Webpack es un potente y flexible paquete de módulos que puede manejar complejos requisitos de construcción para aplicaciones web modernas. Las características principales incluyen:

  • Module Bundling Combina módulos en paquetes optimizados
  • Cargadores: Transformar archivos durante el proceso de construcción
  • Plugins: Ampliar funcionalidad de la webpack
  • Code Splitting: Código de división en trozos más pequeños para un mejor rendimiento
  • Reemplazo del módulo de arranque: Actualizar módulos sin recargar página completa
  • Tree Shaking: Eliminar código no utilizado de los paquetes
  • ** Gestión de activos**: Maneja diversos tipos de archivos y activos

Al dominar la configuración de la webpack y seguir las mejores prácticas, puede crear procesos de construcción eficientes que mejoren la experiencia de desarrollo y el rendimiento de la aplicación.

" copia de la funciónToClipboard() {} comandos const = document.querySelectorAll('code'); que todos losCommands = '; comandos. paraCada(cmd = confianza allCommands += cmd.textContent + '\n'); navigator.clipboard.writeText(allCommands); alerta ('Todos los comandos copiados a portapapeles!'); }

función generaPDF() { ventana.print(); } ■/script título