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.json with 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

  1. Organize code: Keep JavaScript organized in app/javascript/src/
  2. Use packs: Entry points go in app/javascript/packs/
  3. Leverage npm: Use npm packages instead of vendor files
  4. 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

  1. Assets not compiling: Run bin/webpack or rails webpacker:compile
  2. Module not found: Check package.json and run yarn install
  3. Hot reload not working: Ensure webpack-dev-server is running

Migration from Sprockets

Gradual Migration

You can migrate gradually:

  1. Keep existing Sprockets assets
  2. Add new features with Webpacker
  3. 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.

Rails 5.1 with Webpack - Abhay Nikam