Rails Api and Vue.js with Webpack (Rails 5.2)

Rails since 5.1 comes with built in support for Webpack. When issuing a rails new command we can add [--webpack=WEBPACK] which has the explanation:
# Preconfigure for app-like JavaScript with Webpack (options: react/vue/angular/elm/stimulus) and here I’m going to show how Vue.js is set up out of the box. As we’re letting Vue.js handle the front-end let’s install rails with the --api option which makes controllers render models as JSON by default and slims the V part of the MVC in Rails – bonus, no more TurboLinks (it being the work of the devil) and no more CoffeeScript either which reduces our cognitive load. Plain ol’ Javascript for the proverbial. The command line I use is: rails new [my app] --api --webpack=vue -T where the -T skips test files because I use the RSpec testing framework. Webpack is handled by the Webpacker gem, deets here. A lot of Ruby and Node.js magic happens courtesy of this command compared to a simple Rails install.

The main reason I’m writing this tutorial is because even though there are other tutorials out there that show how to use Rails API with Vue.js they all use Vue-CLI to install a batteries-included Vue.js instance with Vue.js handling the routing. Now given that I’m using Rails I sort of want Rails to handle the routing and given that I’m handling Vue.js via the Webpacker gem I just hand the off the view to Mr. Vue from within Rails.

The problem is that rails --api makes controllers inherit from an ApplicationController which in turn inherits from ActionController::API! This is great for apps which have complete separation of concerns but as it stops us from rendering regular Rails views out of the box it blocks us from testing out the installed Vue.js quickly. If we want to get up and running then we can tell one controller to inherit from ActionController::Base (note, that says Action, not Application) and then use the javascript_pack_tag method in our html.erb file like so: <%= javascript_pack_tag 'foo' %>

Webpacker creates a tiny Hello Vue! app for us. To see it in operation this is what we do:

Run the Webpack dev server. Bundler installs the binary stub in ./bin like any other binary stub. Open two new terminal windows or tabs in your application directory and run: ./bin/rails s to get Rails Server up and running in one and run: ./bin/webpack-dev-server to get Webpack building and serving modules in the other. Both Rails server and the Webpack dev server monitor file changes, the latter even does hot reloading out of the box for Rails which is novelty for Rails developers.

  1. Generate a simple scaffold: ./bin/rails g scaffold Example.
  2. Edit app/controllers/examples_controller.rb and change the class parent to ActionController::Base.
  3. Add a simple method, say hello,
  4. and a route to config/routes.rb, say get 'hello_example', to: 'examples#hello' to route to the method.
  5. Add a folder examples for the view,
  6. and a html.erb file which loads Hello Vue! app/views/examples/hello.html.erb and lastly as a bonus,
  7. observe that changing the data field in the example code app/javascript/app.vue causes the browser to refresh.

Neat. No messing with Vue-CLI, Vue routing, or what have you. Incrementally add Javascript features with ./bin/rails webpacker:yarn_install by adding the dependencies you need to package.json the same way we do with bundle install by adding dependencies to Gemfile. The only change I would like to make is to have both Gem packages and Node.js packages together in a special vendor directory.

Any questions? Did I get something wrong or leave out something important? Leave a comment.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.