Madogiwa Blog

主に技術系の学習メモに使っていきます。

【Rails】Webpackerを使ってRailsにフロントエンド開発環境を作ってみた

みなさん、こんにちは。まどぎわです(・∀・)
今日は、RailsアプリにWebpackerを使って、フロントエンド環境を整えて少し開発してみたので、そのあたりをブログに整理しておこうと思います🙌

WebPackerとは?

WebPackerとは、RailsでWebpackをいい感じに扱うことができる機能です。
私もまだ全然理解が足りてない部分がありますが、公式ドキュメントや下記にまとまってますので、興味がある方は読んでみてくださいm( )m

github.com

techracho.bpsinc.jp

今回やったこと

今回は私の開発している「Quizアプリ Quiq」に評価機能を作ってみました。

こんな感じ
f:id:madogiwa0124:20180826181920g:plain

下記から実際に触ることができます🙌

quiz-quiq.herokuapp.com

Webpackerの導入手順

Gemfileに書きを追記してbundle installを実施

gem 'webpacker', github: 'rails/webpacker'

その後、webpackervueをinstallします。

bundle exec rails webpacker:install
# 下記は導入したいフレームワークに合わせて修正してください。
bundle exec rails webpacker:install:vue

これで、bin/webpackでwebpackのビルドが走るようになり、railsでvueを扱えるようになります(・∀・)

フロントエンドの実装

今回は下記のような機能をRails上にVue.jsを使って実装しました。 デフォルトのルールでは、下記のようなディレクトリ構成で実装していきます。
(vue.jsの実装の仕方等は、tutorial等が充実してますので、そちらをご確認ください。)

# viewから読み込むEndpoint
app/javascript/packs
# その他
app/javascript

実際に私が書いたコードが下記です(お見苦しいかもしれません。。。)

QuizLike.vue

ここでは、実際のVueコンポーネントを実装してます。rails側へのpost処理等を実装してます。

<template>
  <div style="text-align: right">
    <button class="btn btn-success btn-sm" @click="create(1)"><i class="fas fa-thumbs-up"></i></button>
    <button class="btn btn-danger btn-sm" @click="create(-1)"><i class="fas fa-thumbs-down"></i></button>
    <span class="text-secondary">評価 : {{ like_count }} pt</span>
  </div>
</template>

<script>
import axios from 'axios';
import { csrfToken } from 'rails-ujs'
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken()
export default {
  data: function () {
    return {
      like_count: this.init_like_count
    }
  },
  props: {
    init_like_count: {
      type: Number,
      required: true
    },
    quiz_id: {
      type: Number,
      required: true
    }
  },
  methods: {
    create: function (value) {
      this.like_count += value
      axios.post(`/quizzes/${this.quiz_id}/like`, {
        like: { value: this.like_count }
      });
    }
  }
}
</script>

packs/quizzes.js

ここでは、作成したコンポーネントの読み込み、Vueインスタンスの作成を行うEndpointを定義してます。

import Vue from 'vue/dist/vue.esm'
import QuizLike from '../QuizLike.vue';

new Vue({
  el: '#like_area',
  components: { QuizLike },
})

result.html.haml

ここでは、javascript_pack_tagを使って、Endpointの読み込みをおこなっています。

= javascript_pack_tag 'quizzes'

point

railsにpostする

railsにpostを送るときには、axiosを使用するの結構メジャーみたいです。
初めて使ってみましたが、下記のようにjsonでパラメーターを作成して簡単にpostがおくれました🙌

axios.post(`/quizzes/${this.quiz_id}/like`, {
    like: { value: this.like_count }
});

postする際の注意点

特に何も考えずにpostメソッドを送ろうとすると、RailsCSRF対策に引っかかり、InvalidAuthenticityTokenが発生してしまいます。Vueコンポーネントからrailsにpostする場合は、下記のように明示的にTokenを作成し、headerに付与してあげる必要があります👀

import axios from 'axios';
import { csrfToken } from 'rails-ujs'
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken()

Tips

上でも少し触れましたが、いろいろハマったところをtipsとして、対応方法を軽くですがメモしておきますφ(・

Uglifier::Error: Unexpected token

下記Issueを参考にproduction.rbを修正して対応しました。

config.assets.js_compressor = Uglifier.new(harmony: true)

github.com

Module build failed: ReferenceError: Unknown plugin "@babel/plugin-transform-destructuring"

下記Issueを参考にyarn add https://github.com/rails/webpacker.gitを実行して対応しました。

Module build failed, Unknown plugin "@babel/plugin-syntax-dynamic-import" after webpacker:install:vue · Issue #1565 · rails/webpacker · GitHub

herokuデプロイ時にnode系のmodule fetchで500Errorで落ちる

何回かリトライしたら正常終了しました。

おわりに

今回はWebpacker使って、フロントエンド開発環境を作ってみました。
良いんだか悪いんだかわからないですが、webpack等フロントエンド関連技術をしらない自分でも結構簡単にフロントエンド環境を作ることができました🙌

これからはフロントエンド技術も学んで、よりユーザーに優しいサービスを作っていきたいです👀

参考

top-men.hatenablog.com

qiita.com

tech.medpeer.co.jp