Rails5.1から導入されたWebpacker。
1回簡単に触ってみたことはあったのですが、開発する際は基本的にRailsとフロントエンド、それぞれ独立させていたのですが、そろそろちゃんといじってみようということで、WebpackerでReact + TypeScriptをRailsに導入してみましたので、その手順を紹介して行こうと思います。
導入手順
Railsプロジェクト作成
まずはいつも通りRailsのプロジェクトを作成していきます。極力システムを汚したくないので、ディレクトリを先に作り、作成したディレクトリにrails newを実行する手順で進めていきます。
ディレクトリ作成&移動
~/workspace $ mkdir myapp1 ~/workspace $ cd myapp1/
bundle init
~/workspace/myapp1 $ bundle init
Gemfile編集
Railsのバージョンを指定する形でGemfileを編集します。今回は5.1.4で進めていきます。
# frozen_string_literal: true source "https://rubygems.org" # gem "rails" gem 'rails', '~> 5.1.4'
bundle install & 初期コマンド
あとはbundle installを行い、webpakerとmysqlの指定を追加した形でrails newを実行します。
DBに関してはお好みでどうぞ。
プロジェクトが作成されたらDB作成とマイグレーションも行っておきます。
~/workspace/myapp1 $ bundle install --path vendor/bundle ~/workspace/myapp1 $ bundle exec rails new . --webpack=react --database=mysql ~/workspace/myapp1 $ bundle exec rails db:create ~/workspace/myapp1 $ bundle exec rails db:migrate
Webpacker動作確認
コントローラー作成
Webpakcer及びReactの導入を確認するために新規コントローラーを作成します。
~/workspace/myapp1 $ bundle exec rails g controller top index
ルーティング作成
rootパスに先ほど作成したコントローラーのアクションを指定しておきます。
Rails.application.routes.draw do root 'top#index' end
javascript_pack_tagの追加
webpackerをビューに反映されるためにjavascirpt_pack_tagをテンプレートファイルに記述します。
ひとまずは以下を追加しておけばOKです。
- <%= javascript_pack_tag 'application' %>
- <%= javascript_pack_tag 'hello_react' %>
<!DOCTYPE html> <html> <head> <title>Nanieta</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application' %> <%= javascript_pack_tag 'hello_react' %> </head> <body> <%= yield %> </body> </html>
ここまでで基本的なwebpack & react の構築は完了。
localhost:3000にアクセスすると、consoleにはHello World from Webpacker、画面にはHello React!が表示されます。
TypeScript導入
次にTypeScriptを導入していきます。
gemの指定バージョン変更
Gemfileのgem 'webpacker'の部分をリポジトリから取得するように書き換えます。
gem 'webpacker', git: 'https://github.com/rails/webpacker.git'
書き換えたら再度bundle installを実行。
~/workspace/myapp1 $ bundle install
TypeScriptをwebpackerに追加
上記の手順で以下のコマンドが使えるようになります。
~/workspace/myapp1 $ bundle exec rails webpacker:install:typescript
サンプルソースの書き換え
app/javascript/packs/hello_react.jsxの拡張子をtsxに書き換え後、以下のように内容を修正しましょう。
import * as React from 'react' import * as ReactDOM from 'react-dom' import PropTypes from 'prop-types' interface HelloProps { name: string } const Hello: React.SFC<HelloProps> = props => ( <div>Hello {props.name}!</div> ) Hello.defaultProps = { name: 'David' } Hello.propTypes = { name: PropTypes.string } document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hello name="React with TypeScript" />, document.body.appendChild(document.createElement('div')), ) })
webpakerの拡張子設定にtsxを追加
webpackerの拡張子を追加します。
extensions: - .coffee - .erb - .js - .jsx - .ts - .tsx - .vue - .sass - .scss - .css - .png - .svg - .gif - .jpeg - .jpg
その後webpackを実行すれば、すでにTypeScriptを導入したReactをwebpackerで使えるようになっています。
~/workspace/myapp1 $ bin/webpack ~/workspace/myapp1 $ bundle exec rails s
その他
ここまでの手順で基本的な開発はできるようになりましたので、以下の設定はお好みで。
tslintの導入
礼儀正しく開発していくためにtslintを導入します。
パッケージの追加
個人開発でルールをこねこねするのも億劫なのでairbnbのテンプレートを設定します。
~/workspace/myapp1 $ yarn add -D tslint tslint-loader tslint-config-airbnb
tslint設定ファイルの作成&設定
~/workspace/myapp1 $ touch tslint.json
とりあえず今回はairbnbのコンフィグを設定するだけです。
{ "extends": "tslint-config-airbnb" }
webpackのローダーを追加&設定
~/workspace/myapp1 $ touch config/webpack/loaders/tslint.js
対象はひとまずtsxファイルのみに設定しておきます。
module.exports = { enforce: 'pre', test: /\.tsx$/, exclude: /node_modules/, use: 'tslint-loader', }
webpakerの設定
あとはビルド時にチェックが走るように設定を行います。tslintのconst宣言とloaderを追加してください。
const { environment } = require('@rails/webpacker') const typescript = require('./loaders/typescript') const tslint = require('./loaders/tslint') environment.loaders.append('typescript', typescript) environment.loaders.append('tslint', tslint) module.exports = environment
foremanでRailsとwebpack-dev-serverを同時起動
rails sのログで確認できればよかったのですが、いい方法が見つからなかったので、webpack-dev-serverをforemanで起動して置くようにしました。
group :development do gem 'foreman' end
~/workspace/myapp1 $ bundle install
~/workspace/myapp1 $ touch Procfile
rails: bundle exec rails s frontend: ./bin/webpack-dev-server
~/workspace/myapp1 $ bundle exec foreman start
これでtslintに引っかかる部分があった時にコンソールに警告が表示されるようになります。
ローダーを変更する
TypeScriptのローダーはデフォルトだとts-loaderなのですが、awesome-typescript-loaderの方が速いとの噂を耳にしたので、変えてみます。速さはロマンです。
~/workspace/myapp1 $ yarn add -D awesome-typescript-loader
module.exports = { test: /\.(ts|tsx)?(\.erb)?$/, use: [{ loader: 'awesome-typescript-loader' }] }
ts-loaderの部分をawesome-typescript-loaderに変更するだけでOKです。