| name | webpack-vite |
| description | Frontend bundler configuration for Webpack and Vite. Use when user mentions "webpack", "vite", "bundler", "vite config", "webpack config", "code splitting", "tree shaking", "hot module replacement", "HMR", "build optimization", "bundle size", "chunk splitting", "loader", "plugin", "esbuild", "rollup", "dev server", or configuring JavaScript build tools. |
Webpack and Vite Reference
Vite Configuration
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
},
},
server: { port: 3000, open: true, strictPort: true },
build: {
outDir: 'dist',
sourcemap: true,
target: 'esnext',
minify: 'esbuild',
rollupOptions: {
output: {
manualChunks: { vendor: ['react', 'react-dom'], router: ['react-router-dom'] },
},
},
},
optimizeDeps: {
include: ['lodash-es', 'axios'],
exclude: ['your-local-package'],
},
css: {
modules: { localsConvention: 'camelCaseOnly' },
preprocessorOptions: { scss: { additionalData: `@use "@/styles/variables" as *;` } },
},
});
Vite Environment Variables
VITE_API_URL=https://api.example.com
DB_PASSWORD=secret
const apiUrl = import.meta.env.VITE_API_URL;
const isDev = import.meta.env.DEV;
const mode = import.meta.env.MODE;
interface ImportMetaEnv { readonly VITE_API_URL: string }
Vite Plugins
import react from '@vitejs/plugin-react';
import reactSWC from '@vitejs/plugin-react-swc';
import vue from '@vitejs/plugin-vue';
import svgr from 'vite-plugin-svgr';
import { VitePWA } from 'vite-plugin-pwa';
import legacy from '@vitejs/plugin-legacy';
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
reactSWC(),
svgr(),
VitePWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg}'] } }),
legacy({ targets: ['defaults', 'not IE 11'] }),
visualizer({ open: true, gzipSize: true, brotliSize: true }),
],
});
Vite Dev Server and Proxy
export default defineConfig({
server: {
proxy: {
'/api': { target: 'http://localhost:4000', changeOrigin: true, rewrite: (p) => p.replace(/^\/api/, '') },
'/ws': { target: 'ws://localhost:4000', ws: true },
},
https: { key: './certs/key.pem', cert: './certs/cert.pem' },
cors: true,
fs: { allow: ['../..'] },
},
});
Webpack 5 Configuration
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'production',
entry: { main: './src/index.tsx', admin: './src/admin.tsx' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
clean: true,
publicPath: '/',
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.jsx'],
alias: { '@': path.resolve(__dirname, 'src') },
},
module: {
rules: [
{ test: /\.(ts|tsx|js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader',
options: { : [, , ] } } },
{ : , : [., , ] },
{ : , : [.,
{ : , : { : } }, ] },
{ : , : [., , , ] },
{ : , : , : { : { : * } } },
{ : , : },
],
},
: [
({ : , : { : } }),
({ : }),
],
};
Webpack Plugins
const { DefinePlugin, ProvidePlugin } = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
plugins: [
new DefinePlugin({
'process.env.API_URL': JSON.stringify(process.env.API_URL),
__DEV__: JSON.stringify(process.env.NODE_ENV === 'development'),
}),
new ProvidePlugin({ React: 'react' }),
new CopyWebpackPlugin({ patterns: [{ from: 'public/assets', to: 'assets' }] }),
new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false }),
],
};
Code Splitting
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
const Admin = React.lazy(() => import( './AdminPanel'));
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
maxInitialRequests: 20,
minSize: 20000,
cacheGroups: {
vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: -10 },
commons: { minChunks: 2, priority: -20, reuseExistingChunk: true },
},
},
runtimeChunk: 'single',
},
};
export default defineConfig({
build: {
rollupOptions: {
output: {
() {
(id.()) {
(id.()) ;
;
}
},
},
},
},
});
Tree Shaking
{ "sideEffects": false }
{ "sideEffects": ["*.css", "*.scss", "./src/polyfills.ts"] }
import { debounce } from 'lodash-es';
const { debounce } = require('lodash');
Bundle Analysis
npx webpack --profile --json > stats.json && npx webpack-bundle-analyzer stats.json
Webpack Dev Server
module.exports = {
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
compress: true,
proxy: [{ context: ['/api'], target: 'http://localhost:4000', changeOrigin: true,
pathRewrite: { '^/api': '' } }],
https: true,
static: { directory: path.join(__dirname, 'public') },
},
};
Production Optimization
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
mode: 'production',
devtool: 'source-map',
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({ terserOptions: { compress: { drop_console: true, drop_debugger: true } } }),
new CssMinimizerPlugin(),
],
},
plugins: [
new CompressionPlugin({ algorithm: 'gzip', test: /\.(js|css|html|svg)$/, threshold: 10240 }),
],
};
export default defineConfig({
build: {
sourcemap: 'hidden',
minify: 'terser',
terserOptions: { compress: { drop_console: true } },
cssCodeSplit: true,
assetsInlineLimit: 4096,
chunkSizeWarningLimit: 500,
},
});
CSS Handling
module.exports = {
plugins: {
'tailwindcss': {},
'autoprefixer': {},
'cssnano': process.env.NODE_ENV === 'production' ? {} : false,
},
};
Migration from Webpack to Vite
npm install -D vite @vitejs/plugin-react
| Webpack | Vite |
|---|
require() / module.exports | import / export (ESM only) |
process.env.X | import.meta.env.VITE_X |
file-loader / url-loader | Native static asset handling |
webpack.DefinePlugin | define option in vite.config.ts |
webpackChunkName comments | rollupOptions.output.manualChunks |
require.context() | import.meta.glob() |
| webpack-dev-server proxy | server.proxy in vite config |
Monorepo Bundling
export default defineConfig({
resolve: { alias: { '@shared/ui': path.resolve(__dirname, '../../packages/ui/src') } },
optimizeDeps: { include: ['@shared/ui'] },
server: { fs: { allow: ['../..'] } },
});
module.exports = {
resolve: { alias: { '@shared/ui': path.resolve(__dirname, '../../packages/ui/src') }, symlinks: false },
module: { rules: [{
test: /\.(ts|tsx)$/,
include: [path.resolve(__dirname, 'src'), path.resolve(__dirname, '../../packages')],
use: 'babel-loader',
}] },
};
Performance Budgets
module.exports = {
performance: {
hints: 'error',
maxAssetSize: 250000,
maxEntrypointSize: 400000,
assetFilter: (file) => !/\.map$/.test(file),
},
};
npm install -D size-limit @size-limit/preset-app
npx size-limit