算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
frontend-bundler-tools【设计与创意】Use this skill when the user says 'bundler', 'Vite', 'Webpack', 'Turbopack', 'build tool', 'bundle config', 'build optimization', 'tree shaking', 'code splitting', 'lazy loading', 'chunk splitting', 'asset bundling', 'build performance', 'bundler migration'. Configure and optimize frontend build tooling. Do NOT use for: framework-specific builds or d…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Description: Configures and optimizes frontend build tools -- bundler selection, code splitting, tree shaking, asset optimization, build performance. Triggered by "bundler", "Vite", "Webpack", "Turbopack", "build tool", "bundle config", "build optimization", "tree shaking", "code splitting", "lazy loading", "chunk splitting", "asset bundling", "build performance", "bundler migration".
Version: 2.0.0 Author: j4flmao License: MIT
Configure and optimize the frontend build pipeline for fast development iteration and lean production bundles -- leveraging modern bundlers, strategic code splitting, and aggressive tree shaking. Target: dev server < 2s, production entry chunk < 200KB gzipped.
User request includes any of: "bundler", "Vite", "Webpack", "Turbopack", "build tool", "bundle config", "build optimization", "tree shaking", "code splitting", "lazy loading", "chunk splitting", "asset bundling", "build performance", "bundler migration".
Build configuration with optimization strategy.
## Strategy
<bundle-selection, migration-plan>
## Config
<key-config-snippets>
## Splitting
<code-splitting, chunk-strategy>
## Optimization
<tree-shaking, assets, caching>
--
Compression footer: frontend-bundler-tools/v1 | 4 sections | bundler: <selected> | size: <current>-><target>
No preamble. No postamble. No explanations. No filler/hedging/transitions. Compress output.
4096 tokens
Project type?
|-- SPA (React, Vue, Svelte) --> Vite (default), Webpack (legacy)
|-- SSR framework -->
| |-- Next.js -> Turbopack (dev) + Webpack (prod) or Next.js 15+: Turbopack (both)
| |-- Nuxt -> Vite (built-in)
| |-- Remix -> Vite (built-in since v2)
| |-- Astro -> Vite (built-in)
|-- Library/package -->
| |-- ESM only -> tsup / bunchee
| |-- UMD + ESM + CJS -> Rollup
| |-- Micro-frontend -> Module Federation (Webpack 5 / Vite plugin)
|-- Monorepo -->
|-- Batch: TurboRepo + Vite
|-- Fine-grained: Nx + Vite/Webpack
Is this a route-level import?
|-- YES --> Use dynamic import: `const Page = lazy(() => import('./Page'))`
|-- NO --> Is this a heavy library (editor, chart, PDF)?
|-- YES --> Dynamic import on interaction trigger
|-- NO --> Is it shared across 3+ routes?
|-- YES --> Extract as vendor chunk
|-- NO --> Keep in route chunk (don't over-split)
Build times too slow?
|-- Dev server -->
| |-- Vite: Check optimizeDeps.include for slow deps
| |-- Webpack: Enable filesystem cache, swap babel for swc/esbuild
|-- Production -->
|-- Too many chunks? -> Merge small chunks, manualChunks
|-- Too slow? -> Enable parallelism, parallel minification
|-- Too large? -> Analyze with bundle-analyzer, find heavy deps
Option A: Vite with Rollup production build. Best for: Most projects. Fastest dev experience. Rich plugin ecosystem. Production via Rollup with tree shaking and code splitting.
Option B: Webpack 5 with persistent caching. Best for: Legacy projects, complex Module Federation setups, projects needing fine-grained loader configuration.
Option C: Turbopack (Next.js). Best for: Very large Next.js applications. Incremental computation for fast rebuilds. Limited to Next.js ecosystem.
Option D: Parcel with zero configuration. Best for: Small projects, prototypes, internal tools. Fast builds with zero configuration.
Option E: tsup/Rollup for library publishing. Best for: Publishing npm packages with multiple formats (ESM, CJS, UMD).
import() -- automatic chunk by bundler.node_modules (longer cache).// Route-level code splitting
const UserDashboard = lazy(() => import('./pages/UserDashboard'))
const AdminPanel = lazy(() => import('./pages/AdminPanel'))
// Interaction-triggered dynamic import
async function handleExport() {
const { generatePDF } = await import('./utils/pdf-generator')
generatePDF(data)
}
// Prefetch on hover for instant navigation
function SidebarLink({ to, label }: { to: string; label: string }) {
const prefetch = useCallback(() => {
const preloaded = import(`./pages/${to}`)
}, [to])
return (
<a href={to} onMouseEnter={prefetch} onFocus={prefetch}>
{label}
</a>
)
}
"sideEffects": false in package.json -- tells bundler to remove unused exports.import/export) -- CommonJS require() can't be tree-shaken.index.ts that re-export everything) -- bundler may retain unused exports./*#__PURE__*/ when they have no side effects.// BAD -- barrel file prevents tree shaking
// components/index.ts
export { Button } from './Button'
export { Card } from './Card'
export { Input } from './Input'
export { Modal } from './Modal'
// ... 50 more exports — all included even if only Button is used
// GOOD -- direct import enables tree shaking
import { Button } from './components/Button'
// Vite config with image optimization
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
export default defineConfig({
plugins: [
react(),
ViteImageOptimizer({
png: { quality: 80 },
jpeg: { quality: 80 },
webp: { quality: 80 },
avif: { quality: 60 },
}),
],
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
ui: ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu'],
},
},
},
},
})
[name].[contenthash:8].js.cache: { type: 'filesystem' }.// Webpack 5 persistent caching
module.exports = {
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
},
},
}
.env files: .env.development, .env.production, .env.local.import.meta.env.VITE_API_URL (Vite), process.env.API_URL (Webpack).__VERSION__, __COMMIT_HASH__, __BUILD_TIME__.process.env.* with import.meta.env.* (Vite) or inject via define# Analyze bundle composition
npx vite-bundle-analyzer
npx webpack-bundle-analyzer dist/stats.json
# Track over time in CI
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
proxy: {
'/api': 'http://localhost:8080',
},
},
build: {
target: 'es2020',
sourcemap: false,
minify: 'esbuild',
rollupOptions: {
output: {
manualChunks(id: string) {
if (id.includes('node_modules/react-dom')) return 'react-vendor'
if (id.includes('node_modules/lodash')) return 'lodash'
},
},
},
},
optimizeDeps: {
include: ['react', 'react-dom'],
},
})
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].chunk.js',
clean: true,
publicPath: '/',
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
module: {
rules: [
{ test: /\.tsx?$/, use: 'swc-loader', exclude: /node_modules/ },
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'] },
],
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendor', chunks: 'all' },
},
},
},
plugins: [
new HtmlWebpackPlugin({ template: './public/index.html' }),
new MiniCssExtractPlugin({ filename: '[name].[contenthash:8].css' }),
],
}
// BAD: re-exports everything, bundler includes unused exports
export { Button } from './Button';
export { Card } from './Card';
// ... 50 more exports
// GOOD: tree-shakeable, direct imports
import { Button } from './Button';
// BAD -- static analysis cannot resolve the import path
const Component = React.lazy(() => import(`./pages/${pageName}`));
// GOOD -- explicit mapping, fully analyzable
const pages = {
home: () => import('./pages/Home'),
about: () => import('./pages/About'),
};
Without this flag, bundlers assume every module import has side effects and will not tree-shake unused exports. Always set "sideEffects": false in library package.json files.
Some npm packages export as CommonJS (module.exports). These cannot be tree-shaken. Use "module" field in package.json or use bundler heuristics (Webpack's module.rules with sideEffects).
All node_modules in a single vendor chunk means a change to any dependency invalidates the entire cache. Split vendors by category: react-vendor, ui-lib, utility.
Generating full source maps in production slows the build and exposes source code. Use hidden-source-map for error monitoring or disable entirely.
If you use @/components/Button in code, the bundler must resolve it. Vite: resolve.alias. Webpack: resolve.alias.
When CSS is extracted per chunk, load order can cause styling race conditions. Use consistent CSS extraction strategy and test across chunks.
| Bundler | Dev Speed | Production Build | Config Complexity | Plugin Ecosystem | Use Case |
|---|---|---|---|---|---|
| Vite | < 2s HMR | Fast (Rollup) | Low | Growing | Default for new projects |
| Webpack 5 | 2-10s HMR | Moderate | High | Largest | Legacy, enterprise, Module Federation |
| Turbopack | < 50ms HMR | Fast | Low (Next.js) | Limited | Large Next.js apps |
| Parcel | < 1s HMR | Fast | Zero | Small | Prototypes, small projects |
| Rollup | N/A (no dev server) | Fast | Moderate | Large | Library publishing |
| esbuild | < 100ms | Very fast | Low | Minimal | Transpilation, simple builds |
| Rsbuild | < 1s HMR | Fast | Low | Growing | Webpack-compatible modern build |
optimizeDeps.include for deps that are slow to pre-bundlenode_modules/.vite -- invalidate by deleting this directorywatchOptions.aggregateTimeout reduces rebuild thrashing on file changeparallel: true for terser, Vite uses esbuild (parallel by default)mini-css-extract-plugin (Webpack) or Vite's built-in CSS splittingvite-plugin-image-optimizer (Vite) or image-minimizer-webpack-plugin (Webpack)font-subset CLI toolsvite-bundle-analyzer for Vite projectswebpack-bundle-analyzer for Webpack projectsnpm run build time, total output size, entry chunk size, vendor chunk count# Track bundle size in CI
name: Bundle Size
on: [pull_request]
jobs:
bundle-size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- run: npx bundlesize
- uses: andresz1/size-limit-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
@vitejs/plugin-react, @vitejs/plugin-vue, vite-plugin-pwa, vite-plugin-svgrhtml-webpack-plugin, mini-css-extract-plugin, copy-webpack-plugin@rollup/plugin-commonjs, @rollup/plugin-node-resolve, @rollup/plugin-typescriptimport() for every lazy route -- no eager imports for route components."sideEffects": false in library package.json for tree shaking.index.ts files that re-export everything from a directory.references/bundle-optimization.md -- Bundle Optimizationreferences/bundler-comparison.md -- Bundler Comparisonreferences/bundler-configuration.md -- Bundler Configurationreferences/bundler-optimization.md -- Bundler Optimizationreferences/module-federation.md -- Module Federationreferences/vite-config.md -- Vite Configurationreferences/bundler-performance-tuning.md -- Bundler Performance Tuningreferences/module-federation-code-splitting.md -- Module Federation & Code SplittingIf project requires custom Webpack plugin development, complex Module Federation setup, or migration from a legacy bundler (Grunt/Gulp/Browserify), flag for build engineer review. Otherwise implement complete bundler config.