Rails+webpackerでAngularをさわってみる

出遅れた感はありますが今回はRails5.1からrailsで使用できるようになったwebpackerを使用してみようと思います
※ 2017/05/20時点の情報をもとにかいてます

webpackerとは?

rails/webpackerはRails5.1からRails配下に入ったyarnでパッケージを管理してくれたりjsでビルドをしてくれる 現状はAngular, React, Vue.jsを指定してはじめられる

準備

Rails5.1からnew時に--webpackを指定するとyarn installや--webpack=[angular|react|vue]でそれぞれに必要なパッケージを追加してインストールなど開発に必要なものを用意してくれるようになりました

$ rails -v
Rails 5.1.1
# 今回はAngularを使いたいのでオプションで指定
$ rails new --webpack=angular sample

ディレクトリの中身を覗いてみる

Gemfileには gem 'webpacker' が追加されていて
app/javascript配下に下記のようなものが展開されている app/javascript/packs配下のものがエントリーポイントとしてデフォルトとして指定されている

.
├── hello_angular
│   ├── app
│   │   ├── app.component.ts
│   │   └── app.module.ts
│   ├── index.ts
│   └── polyfills.ts
└── packs
    ├── application.js
    └── hello_angular.js

とりあえず動かす

まずは適当な画面を作成する

$ rails g controller home index
$ open http://localhost:3000/home/index

f:id:hatappi1225:20170520180145p:plain

次に

application.html.erb内にjavascript_include_tagのかわりでも良いですし追加で<%= javascript_pack_tag 'application' %>を記載します
そしてrails serverとは別にコマンドラインから./bin/webpack-dev-serverでwebpack-dev-serverを起動

これでアクセスをすると画面上は変更はないのですがブラウザのコンソール上には

f:id:hatappi1225:20170520180211p:plain

と出ていると思います

これはapp/javascript/packs/application.jsがwebpackによってビルドされたものが見えており
このファイルを編集してあげるとwebpack-dev-serverによって自動でビルドしてブラウザもリロードしてくれます :tada:

次にAngularのプロジェクトを読み込んでみます
rails new --webpack=angularした時にapp/javascript/packs/hello_angular.jsにサンプルがおかれているのでこれを使います

例えば先程作成した home#indexのviewに<%= javascript_pack_tag 'hello_angular' %>を追加してあげて
タグとしては<hello-angular>Loading...</hello-angular>を追加します

<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>

<hello-angular>Loading...</hello-angular>

<%= javascript_pack_tag 'hello_angular' %>
<!-- タグよりも上にjavascript_pack_tagをおくとERROR Error: The selector "hello-angular" did not match any elementsとエラーが出ます --> 

今回はviewをいじっただけなのでwebpack-dev-serverによって自動ではリロードされないので自分でブラウザをリロードします

f:id:hatappi1225:20170520180415p:plain

でた!!

コンポーネントを追加してみる

テキストをうけとったらそれでButtonを作成してくれるコンポーネントを追加してみます

まずapp/javascript/hello_angular/app/text-button.component.tsを作成して下記のように記載します

import { Component, Input } from '@angular/core';

@Component({
  selector: 'text-button',
  template: `<button>{{text}}</button>`
})
export class TextButtonComponent {
  @Input() text: string;
}

次にapp/javascript/hello_angular/app/app.module.tsに先程のTextButtonComponentを追加してあげます

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { TextButtonComponent } from './text-button.component';

@NgModule({
  declarations: [
    AppComponent,
    TextButtonComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

そして最後にapp/javascript/hello_angular/app/app.component.tsのtemplateに下記のように<text-button text="WORLD!"></text-button>に追加したら終わりです

import { Component } from '@angular/core';

@Component({
  selector: 'hello-angular',
  template: `
    <h1>Hello {{name}}</h1>
    <text-button text="WORLD!"></text-button>
  `
})
export class AppComponent {
  name = 'Angular!';
}

そうすると画面は自動でリロードされ

f:id:hatappi1225:20170520180547p:plain

と表示される!!

最後に

今回はRailsにwebpacker gemを追加してAngularを使ってみました

ここからは個人的な思いになるのですが
Angularは公式サイトにもかかれている通り

One framework

とかかれているので本来はhttp clientやrouterがAngular側で提供されているのでそれを使ってアプリケーションを作成していきます
今回のようにRailsのviewの一部のコンポーネントとして使用するイメージがあまりわきませんでした

個人的にはAngularをやるなら下記を使用していくと思います

github.com