💡 Quick Start: For a concise guide to migrating from Babel to SWC, see Common Upgrades Guide - Babel to SWC.
Shakapacker v10 transpiler defaults depend on the bundler and installation:
- New installations (v9+, including v10):
swc- Installation template explicitly sets SWC (20x faster than Babel) - Webpack runtime default:
babel- Used when no explicit config is provided (maintains backward compatibility) - Rspack runtime default:
swc- Rspack defaults to SWC as it's a newer bundler with modern defaults
Key distinction: The installation template (lib/install/config/shakapacker.yml) explicitly sets javascript_transpiler: "swc" for new projects, but if you're upgrading or have no explicit config, webpack falls back to Babel for backward compatibility.
babel- Traditional JavaScript transpiler with wide ecosystem supportswc- Rust-based transpiler, 20-70x faster than Babelesbuild- Go-based transpiler, extremely fastnone- No transpilation (use native JavaScript)
Set the transpiler in your config/shakapacker.yml:
default: &default # Choose one transpiler:
javascript_transpiler: swc # default, recommended
# javascript_transpiler: babel
# javascript_transpiler: esbuild
# assets_bundler: webpack # default; for rspack, set: assets_bundler: rspackSWC offers significant performance improvements while maintaining high compatibility with Babel.
yarn add --dev @swc/core swc-loader# config/shakapacker.yml
default: &default
javascript_transpiler: swcIf you need custom transpilation settings, create config/swc.config.js:
// config/swc.config.js
// This file is merged with Shakapacker's default SWC configuration
// See: https://swc.rs/docs/configuration/compilation
module.exports = {
options: {
jsc: {
transform: {
react: {
runtime: "automatic"
}
}
}
}
}Important: Use config/swc.config.js instead of .swcrc. The .swcrc file completely overrides Shakapacker's default SWC settings and can cause build failures. config/swc.config.js properly merges with Shakapacker's defaults.
For React projects, ensure you have the correct refresh plugin:
# For webpack
yarn add --dev @pmmmwh/react-refresh-webpack-plugin
# For rspack
yarn add --dev @rspack/plugin-react-refreshTypical build time improvements when migrating from Babel to SWC:
| Project Size | Babel | SWC | Improvement |
|---|---|---|---|
| Small (<100 files) | 5s | 1s | 5x faster |
| Medium (100-500 files) | 20s | 3s | 6.7x faster |
| Large (500+ files) | 60s | 8s | 7.5x faster |
- Some experimental/stage-0 proposals
- Custom Babel plugins (need SWC equivalents)
- Babel macros
- Back up your current configuration
- Install SWC dependencies
- Update
shakapacker.yml - If using Stimulus, ensure
keepClassNames: trueis set inconfig/swc.config.js(automatically included in v9.1.0+, including v10) - Test your build locally
- Run your test suite
- Check browser compatibility
- Deploy to staging environment
- Monitor for any runtime issues
If you're using Stimulus, you must configure SWC to preserve class names. See the Using SWC with Stimulus section for detailed instructions.
Quick summary: Add keepClassNames: true to your config/swc.config.js:
module.exports = {
options: {
jsc: {
keepClassNames: true // Required for Stimulus
}
}
}Starting with Shakapacker v9.1.0 (and continuing in v10), running rake shakapacker:migrate_to_swc automatically creates a configuration with this setting.
If you encounter issues, rolling back is simple:
# config/shakapacker.yml
default: &default
javascript_transpiler: babel # Revert to babelThen rebuild your application:
bundle exec rake shakapacker:clobber
bundle exec rake shakapacker:compileYou can also control the transpiler via environment variables:
# Override config file setting
SHAKAPACKER_JAVASCRIPT_TRANSPILER=swc bundle exec rake shakapacker:compile
# For debugging
SHAKAPACKER_DEBUG_CACHE=true bundle exec rake shakapacker:compileSolution: Ensure all SWC dependencies are installed:
yarn add --dev @swc/core swc-loaderSolution: Install the correct refresh plugin for your bundler:
# Webpack
yarn add --dev @pmmmwh/react-refresh-webpack-plugin
# Rspack
yarn add --dev @rspack/plugin-react-refreshSolution: Enable decorator support in config/swc.config.js:
// config/swc.config.js
module.exports = {
options: {
jsc: {
parser: {
decorators: true,
decoratorsBeforeExport: true
}
}
}
}