157 lines
4.3 KiB
Markdown
157 lines
4.3 KiB
Markdown
# 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"
|
|
}
|
|
} |