Do you really need that fancy JavaScript framework?

Patrik Bóna
Patrik on Rails
Published in
5 min readJun 20, 2017
Wait, what? (unsplash.com)

People are going crazy about single page applications and client side rendering. But, do we really need them?

As opposite to that, Ajax in Ruby on Rails works like this:

  1. Client send an Ajax request to the server.
  2. Server generates new HTML, wrap it in JavaScript and send it to the client.
  3. The JavaScript code is executed by the client and DOM modifications are applied.

Sounds boring? Well, it isn’t! Continue reading to learn about Server-generated JavaScript Responses and see what you can do with this simple but powerful technique in real world examples.

Rails makes Ajax development experience seamless. In order to understand how it works, we need to know how it’s particular pieces work and how they all fit together.

rails-ujs

rails-ujs is an unobtrusive JavaScript adapter. Unobtrusive means, that you don’t need to write any JavaScript to create behaviour which is handled by JavaScript. For example you can create forms submitted via Ajax and you don’t need to write any JavaScript in order to do that.

See the following example:

<form action="/users" data-remote="true" method="post">
...
</form>

data-remote="true" is the unobtrusive part. When you add it to your form, rails-ujs will catch the form submit action, submit the form via Ajax and automatically execute JavaScript code received in the response.

We call such responses “Server-generated JavaScript Responses”. Or in short SJR. You can read about them in this post from DHH.

rails-ujs does much more than just sending Ajax requests. Check out my definitive guide to rails-ujs to learn more.

Turbolinks

Turbolinks is unobtrusive, too. You include it in your project, it binds to the click action on all links and then automatically submit them via Ajax once they are clicked.

But unlike rails-ujs, Turbolinks expects an HTML response. Once it arrives, Turbolinks replaces <body> of your page with <body> from the response.

This is faster than full page reload because browser doesn’t need to request and process all JavaScript and CSS files again.

Rails + rails-ujs + Turbolinks

Both, rail-ujs and Turbolinks are included in Rails by default. They work very nicely together. See the following example.

View:

# app/views/users/_form.html.erb<%= form_with model: @user do |form| %>
...
<% end %>

This generates the following HTML:

<form action="/users" data-remote="true" method="post">
...
</form>

Notice the data-remote="true" part. It was added automatically by form_with.

form_with is a new Rails 5.1’s addition which is going to replace form_tag and form_for. Learn more about it in my previous post.

When you submit this form, then rails-ujs will submit it as an Ajax request and it will expect JavaScript code in the response.

Controller:

# app/controllers/users_controller.rbclass UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.create
redirect_to user_path(@user)
end
end
end

When a user is created, then we want to redirect client to the user page. We can’t use standard redirects, because they don’t work with JavaScript requests.

Fortunately turbolinks-rails got us covered and

redirect_to user_path(@user)

generates the following JavaScript code:

Turbolinks.clearCache()
Turbolinks.visit("http://web.dev/users/1",{"action":"replace"})

This code is executed by rails-ujs and the current page is replaced by the page from http://web.dev/users/1.

So, the happy path, when there are no validation errors is working. But what happens when the user model isn’t valid? Then the controller will render a JavaScript template for the create action:

# app/views/users/create.js.erb (jQuery version)$("form").replaceWith("<%= j render "form" %>");

It’s just one line of code, but the code itself might be not obvious so let’s deconstruct it.

render "form" will generate HTML for our form.

j is an alias for escape_javascript and it will escape our HTML so we can use it in the JavaScript response.

$("form").replaceWith(...) will replace the old HTML form code with the new one which should contain validation errors.

To put it all together, we generated a new HTML code and wrapped it in the JavaScript code which replaces the old form with the new one.

Summary

We just learned how to do two things with Server-generated JavaScript Responses:

  1. Perform Ajax redirects with Turbolinks.
  2. Modify DOM with a response from the server.

It doesn’t sound so exciting, right? Well, you can do quite a lot with this simple technique. This brings us to the next section.

Real-world examples

Sending test emails.
Subscription management.
Modals!

So, what do you say? Maybe you really don’t need that fancy JavaScript framework after all.

SJR pros

  • No duplication of logic, because all logic lives on the server.
  • No duplication of views, because all views live on the server.
  • Simple, but powerful technique which allows us to create a better user experience with a very little overhead.

SJR cons

  • Not suitable for complex UI interactions.

Conclusion

I’m not saying that there is no place for single page applications. But I really think that they are overrated and people often use them even if they don’t need to. What the heck. I believe that vast majority of web applications can live without them and that they create more problems than they solve.

If you are learning to program web applications, and you are not sure which JavaScript framework you should learn, then maybe none is the answer. Just learn a full-stack framework like Ruby on Rails and you will be able to do much more with less effort.

Hey you! Please consider subscribing to my newsletter if you enjoyed this article.

--

--