# Application.js Size Optimization Guide ## Current Issue The `application.js` bundle is 1.4MB (2.3MB with source maps), which is significantly larger than recommended. ## Root Causes 1. **Single bundle includes everything**: All dependencies, React, controllers, and components 2. **No code splitting**: Everything is bundled into one file 3. **Development dependencies**: Alpine.js and other dev tools included 4. **No minification/optimization**: Source maps and uncompressed code ## Optimization Strategies ### 1. Split Bundles (Recommended) Create separate bundles for different parts of the application: **Update package.json build scripts:** ```json { "scripts": { "build": "npm run build:main && npm run build:components", "build:main": "esbuild app/javascript/application.js --bundle --minify --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets", "build:components": "esbuild app/javascript/components/*.* --bundle --minify --format=esm --outdir=app/assets/builds/components --public-path=/assets --loader:.js=jsx", "build:css": "postcss ./app/assets/stylesheets/application.postcss.css -o ./app/assets/builds/application.css" } } ``` ### 2. Remove Unused Dependencies **package.json optimization:** ```json { "dependencies": { "@hotwired/stimulus": "^3.2.2", "@hotwired/turbo-rails": "^8.0.13", "@radix-ui/react-slot": "^1.2.3", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "esbuild": "^0.25.4", "postcss": "^8.5.3", "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.4", "tailwindcss-animate": "^1.0.7" } } ``` **Remove these from devDependencies:** - `alpinejs` - if not used - `@types/alpinejs` - if Alpine.js removed - `cssnano` - if using Tailwind's built-in minification - `pm2` - production deployment tool ### 3. Dynamic Imports (Code Splitting) **Update application.js:** ```javascript // Instead of importing everything statically import "@hotwired/turbo-rails" import "./controllers" // Use dynamic imports for heavy components const loadComponent = async (componentName) => { const { default: component } = await import(`./components/${componentName}`) return component } ``` ### 4. Tree Shaking & Minification **Enhanced build command:** ```json { "build": "esbuild app/javascript/application.js --bundle --minify --tree-shaking --drop:console --drop:debugger --sourcemap=external --format=esm --outdir=app/assets/builds --public-path=/assets" } ``` ### 5. Separate Vendor Bundle **Create vendor.js:** ```javascript // app/javascript/vendor.js import "react" import "react-dom" import "@radix-ui/react-slot" ``` **Update build to create vendor bundle:** ```json { "build:vendor": "esbuild app/javascript/vendor.js --bundle --minify --format=esm --outdir=app/assets/builds --public-path=/assets", "build:app": "esbuild app/javascript/application.js --bundle --minify --external:react --external:react-dom --format=esm --outdir=app/assets/builds --public-path=/assets" } ``` ### 6. Conditional Loading **Lazy load heavy components:** ```javascript // app/javascript/application.js if (document.querySelector('[data-controller="shadcn-test"]')) { import('./controllers/shadcn_test_controller') } ``` ### 7. Production Optimization Checklist **Step 1: Analyze bundle size** ```bash npm install --save-dev webpack-bundle-analyzer npx esbuild app/javascript/application.js --bundle --analyze ``` **Step 2: Implement optimizations** ```bash # Remove unused dependencies npm uninstall alpinejs @types/alpinejs cssnano pm2 # Update build scripts npm run build ``` **Step 3: Verify size reduction** Should reduce from 1.4MB to ~200-400KB ## Quick Fix Commands ```bash # 1. Remove Alpine.js (if unused) npm uninstall alpinejs @types/alpinejs # 2. Update build with optimization npm install --save-dev esbuild@latest # 3. Modify package.json scripts # (Copy the optimized scripts above) # 4. Build with optimization npm run build ``` ## Expected Results - **Before**: 1.4MB application.js - **After**: 200-400KB with code splitting - **Vendor bundle**: ~100KB (cached) - **App bundle**: ~100-300KB (dynamic) ## Monitoring Add bundle size monitoring to CI/CD: ```json { "size-limits": { "app/assets/builds/application.js": "500kb", "app/assets/builds/application.css": "50kb" } }