Files
aperonight/docs/application-optimization.md
2025-08-28 15:11:42 +02:00

4.3 KiB
Executable File

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

Create separate bundles for different parts of the application:

Update package.json build scripts:

{
  "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:

{
  "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:

// 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:

{
  "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:

// app/javascript/vendor.js
import "react"
import "react-dom"
import "@radix-ui/react-slot"

Update build to create vendor bundle:

{
  "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:

// 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

npm install --save-dev webpack-bundle-analyzer
npx esbuild app/javascript/application.js --bundle --analyze

Step 2: Implement optimizations

# 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

# 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:

{
  "size-limits": {
    "app/assets/builds/application.js": "500kb",
    "app/assets/builds/application.css": "50kb"
  }
}