Rails 5.1 with Webpack
Rails 5.1 introduced Webpacker, making it easy to integrate Webpack for managing JavaScript modules in Rails applications. Webpacker provides a Rails-friendly way to use modern JavaScript tooling without complex configuration.
What is Webpacker?
Webpacker is a Rails gem that wraps Webpack, providing:
- Easy integration with Rails
- Sprockets compatibility
- Hot module replacement in development
- Production asset compilation
- Support for modern JavaScript features
Installation
Add Webpacker to Gemfile
# Gemfile
gem 'webpacker', '~> 5.1'
Install Webpacker
bundle install
rails webpacker:install
This creates:
app/javascript/directory- Webpack configuration files
package.jsonwith dependencies
Basic Setup
Directory Structure
Webpacker creates this structure:
app/
javascript/
packs/
application.js
channels/
src/
config/
webpack/
environment.js
development.js
production.js
test.js
package.json
yarn.lock
Entry Point
Your main JavaScript entry point:
// app/javascript/packs/application.js
import '../src/application'
Using Webpacker
Including in Views
Include compiled JavaScript in your views:
<!-- app/views/layouts/application.html.erb -->
<%= javascript_pack_tag 'application' %>
Using with Sprockets
You can use both Webpacker and Sprockets:
<!-- Sprockets for legacy code -->
<%= javascript_include_tag 'application' %>
<!-- Webpacker for modern JavaScript -->
<%= javascript_pack_tag 'application' %>
Writing JavaScript
ES6 Modules
Use modern JavaScript syntax:
// app/javascript/src/application.js
import { createApp } from 'vue'
import App from './components/App.vue'
createApp(App).mount('#app')
Importing Dependencies
Install and import npm packages:
yarn add axios
// app/javascript/src/api.js
import axios from 'axios'
export function fetchUsers() {
return axios.get('/api/users')
}
Configuration
Webpack Environment
Customize Webpack configuration:
// config/webpack/environment.js
const { environment } = require('@rails/webpacker')
// Add custom loaders
environment.loaders.append('vue', {
test: /\.vue$/,
use: [{ loader: 'vue-loader' }]
})
module.exports = environment
Development Configuration
Configure development settings:
// config/webpack/development.js
const { environment } = require('@rails/webpacker')
environment.config.merge({
devtool: 'eval-source-map'
})
module.exports = environment
Real-World Examples
React Setup
Set up React with Webpacker:
rails webpacker:install:react
// app/javascript/packs/application.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from '../src/App'
ReactDOM.render(<App />, document.getElementById('root'))
Vue Setup
Set up Vue with Webpacker:
rails webpacker:install:vue
// app/javascript/packs/application.js
import { createApp } from 'vue'
import App from '../src/App.vue'
createApp(App).mount('#app')
TypeScript Setup
Set up TypeScript:
rails webpacker:install:typescript
// app/javascript/src/application.ts
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
Asset Pipeline Integration
Using Images
Reference images in JavaScript:
// app/javascript/src/components/Logo.jsx
import logo from '../images/logo.png'
function Logo() {
return <img src={logo} alt="Logo" />
}
Using Stylesheets
Import CSS/SCSS:
// app/javascript/src/application.js
import '../styles/application.scss'
Development Workflow
Running Webpack Dev Server
Start the development server:
bin/webpack-dev-server
This provides:
- Hot module replacement
- Fast compilation
- Live reloading
Compiling Assets
Compile assets for production:
rails assets:precompile
# or
bin/webpack
Best Practices
- Organize code: Keep JavaScript organized in
app/javascript/src/ - Use packs: Entry points go in
app/javascript/packs/ - Leverage npm: Use npm packages instead of vendor files
- Keep it simple: Don't over-complicate Webpack config
Common Patterns
Component Organization
// app/javascript/src/components/UserCard.jsx
import React from 'react'
export default function UserCard({ user }) {
return (
<div className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
)
}
API Integration
// app/javascript/src/api/users.js
import axios from 'axios'
export const usersApi = {
index: () => axios.get('/api/users'),
show: (id) => axios.get(`/api/users/${id}`),
create: (data) => axios.post('/api/users', data)
}
Troubleshooting
Common Issues
- Assets not compiling: Run
bin/webpackorrails webpacker:compile - Module not found: Check
package.jsonand runyarn install - Hot reload not working: Ensure
webpack-dev-serveris running
Migration from Sprockets
Gradual Migration
You can migrate gradually:
- Keep existing Sprockets assets
- Add new features with Webpacker
- Migrate old code incrementally
Coexistence
Both can coexist:
<!-- Legacy Sprockets -->
<%= stylesheet_link_tag 'application' %>
<%= javascript_include_tag 'application' %>
<!-- New Webpacker -->
<%= stylesheet_pack_tag 'application' %>
<%= javascript_pack_tag 'application' %>
Conclusion
Rails 5.1's Webpacker integration makes it easy to use modern JavaScript tooling in Rails applications. By providing a Rails-friendly wrapper around Webpack, Webpacker enables you to use ES6 modules, npm packages, and modern frameworks like React and Vue without complex configuration. This makes Rails applications more capable of handling modern frontend requirements while maintaining the Rails developer experience.