Loading...
Loading...
Webpack build optimization expert with deep knowledge of configuration patterns, bundle analysis, code splitting, module federation, performance optimization, and plugin/loader ecosystem. Use PROACTIVELY for any Webpack bundling issues including complex optimizations, build performance, custom plugins/loaders, and modern architecture patterns. If a specialized expert is a better fit, I will recommend switching and stop.
npx skill4agent add duck4nh/antigravity-kit webpack-expert# Core Webpack detection
webpack --version || npx webpack --version
node -v
# Detect Webpack ecosystem and configuration
find . -name "webpack*.js" -o -name "webpack*.ts" -type f | head -5
grep -E "webpack|@webpack" package.json || echo "No webpack dependencies found"
# Framework integration detection
grep -E "(react-scripts|next\.config|vue\.config|@craco)" package.json && echo "Framework-integrated webpack"# Validate configuration
webpack --config webpack.config.js --validate
# Fast build test (avoid watch processes)
npm run build || webpack --mode production
# Bundle analysis (if tools available)
command -v webpack-bundle-analyzer >/dev/null 2>&1 && webpack-bundle-analyzer dist/stats.json --no-openmodule.exports = {
entry: {
// Modern shared dependency pattern
app: { import: "./src/app.js", dependOn: ["react-vendors"] },
admin: { import: "./src/admin.js", dependOn: ["react-vendors"] },
"react-vendors": ["react", "react-dom", "react-router-dom"]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash:8].js',
chunkFilename: '[name].[chunkhash:8].chunk.js',
publicPath: '/assets/',
clean: true, // Webpack 5+ automatic cleanup
assetModuleFilename: 'assets/[hash][ext][query]'
}
}module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'components': path.resolve(__dirname, 'src/components'),
'utils': path.resolve(__dirname, 'src/utils')
},
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
// Performance: Limit extensions to reduce resolution time
modules: [path.resolve(__dirname, "src"), "node_modules"],
symlinks: false, // Speeds up resolution in CI environments
// Webpack 5 fallbacks for Node.js polyfills
fallback: {
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"buffer": require.resolve("buffer"),
"path": require.resolve("path-browserify"),
"fs": false,
"net": false,
"tls": false
}
}
}module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
maxInitialRequests: 6, // Balance parallel loading vs HTTP/2
maxAsyncRequests: 10,
cacheGroups: {
// Vendor libraries (stable, cacheable)
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
priority: 20,
reuseExistingChunk: true
},
// Common code between pages
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
priority: 10,
reuseExistingChunk: true,
enforce: true
},
// Large libraries get their own chunks
react: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'react',
chunks: 'all',
priority: 30
},
// UI library separation
ui: {
test: /[\\/]node_modules[\\/](@mui|antd|@ant-design)[\\/]/,
name: 'ui-lib',
chunks: 'all',
priority: 25
}
}
},
// Enable concatenation (scope hoisting)
concatenateModules: true,
// Better chunk IDs for caching
chunkIds: 'deterministic',
moduleIds: 'deterministic'
}
}module.exports = {
mode: 'production', // Enables tree shaking by default
optimization: {
usedExports: true,
providedExports: true,
sideEffects: false, // Mark as side-effect free
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // Remove console logs
drop_debugger: true,
pure_funcs: ['console.log', 'console.info'], // Specific function removal
passes: 2 // Multiple passes for better optimization
},
mangle: {
safari10: true // Safari 10 compatibility
}
}
})
]
},
// Package-specific sideEffects configuration
module: {
rules: [
{
test: /\.js$/,
sideEffects: false,
// Only for confirmed side-effect-free files
}
]
}
}const ModuleFederationPlugin = require("@module-federation/webpack");
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "host_app",
remotes: {
// Remote applications
shell: "shell@http://localhost:3001/remoteEntry.js",
header: "header@http://localhost:3002/remoteEntry.js",
product: "product@http://localhost:3003/remoteEntry.js"
},
shared: {
// Critical: Version alignment for shared libraries
react: {
singleton: true,
strictVersion: true,
requiredVersion: "^18.0.0"
},
"react-dom": {
singleton: true,
strictVersion: true,
requiredVersion: "^18.0.0"
},
// Shared utilities
lodash: {
singleton: false, // Allow multiple versions if needed
requiredVersion: false
}
}
})
]
}module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "shell",
filename: "remoteEntry.js",
exposes: {
// Expose specific components/modules
"./Shell": "./src/Shell.jsx",
"./Navigation": "./src/components/Navigation",
"./utils": "./src/utils/index"
},
shared: {
// Match host shared configuration exactly
react: { singleton: true, strictVersion: true },
"react-dom": { singleton: true, strictVersion: true }
}
})
]
}module.exports = {
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(__dirname, '.cache'),
buildDependencies: {
// Invalidate cache when config changes
config: [__filename],
// Track package.json changes
dependencies: ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']
},
// Cache compression for CI environments
compression: 'gzip'
}
}module.exports = {
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: [
// Parallel processing for expensive operations
{
loader: "thread-loader",
options: {
workers: require('os').cpus().length - 1,
workerParallelJobs: 50,
poolTimeout: 2000
}
},
{
loader: "babel-loader",
options: {
cacheDirectory: true, // Enable Babel caching
cacheCompression: false // Disable compression for speed
}
}
]
}
]
}
}const isDevelopment = process.env.NODE_ENV === 'development';
module.exports = {
mode: isDevelopment ? 'development' : 'production',
// Faster source maps for development
devtool: isDevelopment
? 'eval-cheap-module-source-map'
: 'source-map',
optimization: {
// Disable optimizations in development for speed
removeAvailableModules: !isDevelopment,
removeEmptyChunks: !isDevelopment,
splitChunks: isDevelopment ? false : {
chunks: 'all'
}
},
// Reduce stats output for faster builds
stats: isDevelopment ? 'errors-warnings' : 'normal'
}module.exports = {
optimization: {
splitChunks: {
// Prevent overly large chunks
maxSize: 244000, // 244KB limit
cacheGroups: {
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
maxSize: 244000
},
vendor: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
maxSize: 244000
}
}
}
}
}class BundleAnalysisPlugin {
constructor(options = {}) {
this.options = {
outputPath: './analysis',
generateReport: true,
...options
};
}
apply(compiler) {
const pluginName = 'BundleAnalysisPlugin';
// Hook into the emit phase
compiler.hooks.emit.tapAsync(pluginName, (compilation, callback) => {
const stats = compilation.getStats().toJson();
// Analyze bundle composition
const analysis = this.analyzeBundles(stats);
// Generate analysis files
const analysisJson = JSON.stringify(analysis, null, 2);
compilation.assets['bundle-analysis.json'] = {
source: () => analysisJson,
size: () => analysisJson.length
};
if (this.options.generateReport) {
const report = this.generateReport(analysis);
compilation.assets['bundle-report.html'] = {
source: () => report,
size: () => report.length
};
}
callback();
});
// Hook into compilation for warnings/errors
compiler.hooks.compilation.tap(pluginName, (compilation) => {
compilation.hooks.optimizeChunkAssets.tap(pluginName, (chunks) => {
chunks.forEach(chunk => {
if (chunk.size() > 500000) { // 500KB warning
compilation.warnings.push(
new Error(`Large chunk detected: ${chunk.name} (${chunk.size()} bytes)`)
);
}
});
});
});
}
analyzeBundles(stats) {
// Complex analysis logic
return {
totalSize: stats.assets.reduce((sum, asset) => sum + asset.size, 0),
chunkCount: stats.chunks.length,
moduleCount: stats.modules.length,
duplicates: this.findDuplicateModules(stats.modules)
};
}
}// webpack-env-loader.js - Inject environment-specific code
module.exports = function(source) {
const options = this.getOptions();
const callback = this.async();
if (!callback) {
// Synchronous loader
return processSource(source, options);
}
// Asynchronous processing
processSourceAsync(source, options)
.then(result => callback(null, result))
.catch(error => callback(error));
};
function processSourceAsync(source, options) {
return new Promise((resolve, reject) => {
try {
// Environment-specific replacements
let processedSource = source.replace(
/process\.env\.(\w+)/g,
(match, envVar) => {
const value = process.env[envVar];
return value !== undefined ? JSON.stringify(value) : match;
}
);
// Custom transformations based on options
if (options.removeDebug) {
processedSource = processedSource.replace(
/console\.(log|debug|info)\([^)]*\);?/g,
''
);
}
resolve(processedSource);
} catch (error) {
reject(error);
}
});
}const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap({
// ... webpack config
plugins: [
// Bundle composition analysis
new BundleAnalyzerPlugin({
analyzerMode: process.env.ANALYZE ? 'server' : 'disabled',
analyzerHost: '127.0.0.1',
analyzerPort: 8888,
openAnalyzer: false,
generateStatsFile: true,
statsFilename: 'webpack-stats.json',
// Generate static report for CI
reportFilename: '../reports/bundle-analysis.html'
}),
// Compression analysis
new CompressionPlugin({
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 8192,
minRatio: 0.8,
filename: '[path][base].gz'
})
]
});# Generate comprehensive stats
webpack --profile --json > webpack-stats.json
# Analyze with different tools
npx webpack-bundle-analyzer webpack-stats.json dist/ --no-open
# Size comparison (if previous stats exist)
npx bundlesize
# Lighthouse CI integration
npx lhci autorun --upload.target=temporary-public-storageError: Can't resolve './component'# Check file existence and paths
ls -la src/components/
# Test module resolution
webpack --config webpack.config.js --validate
# Trace resolution process
npx webpack --mode development --stats verbose 2>&1 | grep -A5 -B5 "Module not found"resolve.extensions: ['.js', '.jsx', '.ts', '.tsx']resolve.aliasresolve.fallback# Generate bundle analysis
webpack --json > stats.json && webpack-bundle-analyzer stats.json
# Check largest modules
grep -E "size.*[0-9]{6,}" stats.json | head -10splitChunks: { chunks: 'all' }import()# Time the build process
time webpack --mode production
# Memory monitoring
node --max_old_space_size=8192 node_modules/.bin/webpack --profilecache: { type: 'filesystem' }# Test HMR endpoint
curl -s http://localhost:3000/__webpack_hmr | head -5
# Check HMR plugin configuration
grep -r "HotModuleReplacementPlugin\|hot.*true" webpack*.jsnew webpack.HotModuleReplacementPlugin()devServer: { hot: true }module.hot.accept()# Test remote entry accessibility
curl -I http://localhost:3001/remoteEntry.js
# Check shared dependencies alignment
grep -A10 -B5 "shared:" webpack*.js# Check webpack and plugin versions
webpack --version && npm list webpack-*
# Validate configuration
webpack --config webpack.config.js --validatemodule.exports = {
module: {
rules: [
// Asset/resource - emits separate file
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[name].[hash:8][ext]'
}
},
// Asset/inline - data URI
{
test: /\.svg$/,
type: 'asset/inline',
resourceQuery: /inline/ // Use ?inline query
},
// Asset/source - export source code
{
test: /\.txt$/,
type: 'asset/source'
},
// Asset - automatic choice based on size
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8KB
}
}
}
]
}
}module.exports = {
experiments: {
topLevelAwait: true
},
target: 'es2020' // Required for top-level await
}