Webpack Configuration
Configure webpack: loaders, plugins, code splitting, Module Federation for micro-frontends, and optimizing production builds.
Webpack remains relevant for enterprise apps requiring Module Federation (micro-frontends), complex multi-entry builds, and mature plugin ecosystems. Understanding webpack core concepts - loaders, plugins, resolvers, and the compilation pipeline - enables handling builds that simpler tools cannot.
Use webpack when you need Module Federation for micro-frontends, have a legacy codebase already on webpack, or require complex custom build logic. For new projects, prefer Vite. When on webpack, invest in configuration correctness and bundle analysis.
Workflow
- Understand the core configuration shapewebpack config has specific semantics - knowing entry/output/module/plugins/resolve enables reading and writing it correctly.
- Configure loaders for different file typesLoaders transform files before they're added to the dependency graph - TypeScript, CSS, images, SVGs.
- Implement code splittingCode splitting reduces initial bundle size, loading only code needed for the current route.
- Set up Module Federation for micro-frontendsModule Federation allows independently deployed apps to share code at runtime - enabling micro-frontend architectures.
- Analyze and optimize bundle sizeUnknown bundle contents lead to shipping unnecessary code; analysis reveals exactly what's included and why.
Output Format
Typed webpack config, loaders for TS/CSS/assets, splitChunks with cacheGroups, Module Federation with shared singleton React, BundleAnalyzerPlugin, content hash filenames.
Examples
Full config: `const { ModuleFederationPlugin } = require("webpack").container; module.exports = { mode: "production", entry: "./src/index.tsx", output: { filename: "[name].[contenthash:8].js", path: dist, publicPath: "auto" }, resolve: { extensions: [".tsx",".ts",".js"] }, module: { rules: [{ test: /\.tsx?$/, loader: "ts-loader" }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"] }] }, plugins: [new HtmlWebpackPlugin(), new MiniCssExtractPlugin()] }`MFE remote: `new ModuleFederationPlugin({ name: "checkout", filename: "remoteEntry.js", exposes: { "./Checkout": "./src/Checkout.tsx", "./CartSummary": "./src/CartSummary.tsx" }, shared: deps })`Tree-shake lodash: `import debounce from "lodash/debounce"` instead of `import { debounce } from "lodash"` - imports only the function's file, not the whole libraryEdge Cases & Gotchas
- Hot Module Replacement in dev: `devServer: { hot: true }` + `webpack-dev-server`; for React, add `react-refresh/babel` and `@pmmmwh/react-refresh-webpack-plugin` for component-level HMR
- CircularDependencyPlugin: add to detect circular imports that cause subtle runtime bugs: `new CircularDependencyPlugin({ exclude: /node_modules/, failOnError: true })`
- Source maps in production: use `devtool: "hidden-source-map"` - generates source maps but doesn't link them in the bundle; upload to error tracking (Sentry) separately
When to Break These Rules
- For new projects or when migrating from webpack, use Vite - it's faster, simpler to configure, and has better DX. Only stay on webpack if you need Module Federation or have irreplaceable webpack-specific plugins.
Reference Files
webpack docs: https://webpack.js.org/concepts/Module Federation: https://webpack.js.org/concepts/module-federation/webpack-bundle-analyzer: https://github.com/webpack-contrib/webpack-bundle-analyzerwebpack optimization: https://webpack.js.org/guides/tree-shaking/