patorashのブログ

方向性はまだない

GraphQLのスキーマ情報からドキュメントを生成する

漠然と考えていたことが既に書かれていたので、非常に参考になったし面白かった。

developer.kaizenplatform.com

GraphQL APIの設計を中心にフロントエンド、バックエンドをそれぞれ作っていくと、それぞれの実装待ちが発生しなくてよい。しかもAPI仕様のドキュメントを作成することも簡単だった。

graphql-rubyからGraphQLのスキーマ情報を作成する

Railsプロジェクトでgraphql-rubyを使ってスキーマ情報を生成するのは簡単。Rakefileに以下を追記して、rake taskを追加する。

#!/usr/bin/env rake

require File.expand_path('../config/application', __FILE__)
require 'graphql/rake_task' # 追加
Rails.application.load_tasks

GraphQL::RakeTask.new(schema_name: 'SampleSchema') # 追加

確認してみる。

$ bin/rake -T | grep graphql
rake graphql:pro:validate[gem_version] # Get the checksum of a graphql-pro version and compare it to published versions on GitHub and graphql-ruby.org
rake graphql:schema:dump               # Dump the schema to JSON and IDL
rake graphql:schema:idl                # Dump the schema to IDL in ./schema.graphql
rake graphql:schema:json               # Dump the schema to JSON in ./schema.json

rake graphql:schema:dumpで、schema.graphqlとschema.jsonを生成してくれるようになった。

ドキュメントHTMLの生成

ドキュメントHTMLの生成も簡単だけれど、実は結構ハマった。

さきほどの参考記事では、graphdocが紹介されていて、最初はそれを使おうとしたのだけれど、schema.graphqlからドキュメントを作成するときにエラーになった。どうもコメントに対応できていないらしい…。また、リポジトリが1年以上メンテされてないみたいでこれ大丈夫か???と思っていた。 すると、どうもgraphidocsにフォークしてメンテナンスされているらしい。そのため、npmパッケージの名前もgraphdocからgraphidocsに変わっていた。

graphidocsorg.github.io

以下で、グローバル環境にインストールできる。

npm install -g @graphidocs/docs

しかし、node-gyp rebuildが走ってエラーが出ていた(ただ、インストール自体は成功していた…)。 解決方法がわからなかったので(Nodeを6系までダウングレードすれば通る、みたいなのはあったが、今は10系を使っているから嫌だった)、エラーメッセージは放置した。

ただ、プロジェクトのドキュメントを作るのにグローバルにインストールしたくないなぁと思って、そこは変更した。

$ yarn add @graphidocs/docs --dev

エンドポイントからドキュメントを作る

既にGraphQLのAPIがあるのであれば、そこをエンドポイントして指定して実行すれば、生成してくれる。ローカルでやるのであれば、bin/rails sをした状態で、以下を実行する

$ yarn run graphidocs -e http://localhost:3000/graphql -o ./doc/schema

毎回オプションをつけるのは大変なので、package.jsonにオプションを設定しておくことも可能。

{
  "dependencies": {
    # 省略
  },
  "devDependencies": {
    "@graphidocs/docs": "^1.0.4"
  },
  "graphidocs": {
    "endpoint": "http://localhost:3000/graphql",
    "output": "./doc/schema"
  }
}

こうすると、以下でOK。

$ yarn run graphidocs

スキーマからドキュメントを作る

しかし、エンドポイントからドキュメントを作るのでは、さきほどの参考記事のようにフロントエンド、バックエンドでAPI仕様を議論しながらは進められない。必ずバックエンドの実装後になってしまうので、やはりスキーマ情報からドキュメントを作りたい。

スキーマ情報からドキュメントを作るには、オプションを変更する。既にある程度API実装があるのであれば、先ほど追加したrake taskを実行して、スキーマ情報をダンプしておく。

$ bin/rake graphql:schema:dump # schema.graphqlとschema.jsonを生成
$ yarn run graphidocs -schema ./schema.graphql -o ./doc/schema

ここでは、schema.graphqlを指定したが、schema.jsonでも動く。

こちらも毎回オプションをつけるのは大変なので、package.jsonにオプションを設定できる。

{
  "dependencies": {
    # 省略
  },
  "devDependencies": {
    "@graphidocs/docs": "^1.0.4"
  },
  "graphidocs": {
    "schemaFile": "./schema.graphql",
    "output": "./doc/schema"
  }
}

こうすると、以下でOK。

$ yarn run graphidocs

これで、schema.graphqlを介してフロントエンド、バックエンドの人で意見交換して、ドキュメントを生成してそれぞれが開発する土台ができたかなと思う。

GraphQLのドキュメントを見るためのWebサーバを定義する

ドキュメントは./doc/schema配下にできたものの、そこを開きにいくのも面倒なので、WEBrickでWebサーバを作った。 プロジェクトのルートフォルダにgraphidocs.rbを作成した。

# graphidocsで生成したgraphqlのスキーマ情報を見るためのサーバを立ち上げます。
# ./doc/schemaが存在しないか古い場合、まず`yarn run graphidocs`を実行してください。
# その後、`ruby graphidocs.rb`を実行してください。
require 'webrick'
include WEBrick
server = HTTPServer.new(
  DocumentRoot: './doc/schema',
  BindAddress: '0.0.0.0',
  Port: 8000
)

%w(INT TERM).each do |sig|
  trap(sig) { server.shutdown }
end
server.start

これを実行する。

$ ruby graphidocs.rb
[2019-04-03 10:53:47] INFO  WEBrick 1.4.2
[2019-04-03 10:53:47] INFO  ruby 2.5.5 (2019-03-15) [x86_64-darwin16]
[2019-04-03 10:53:47] INFO  WEBrick::HTTPServer#start: pid=4858 port=8000

http://localhost:8000 にアクセスすると、GraphQLのドキュメントが読めるようになった。サーバの終了はCtrl + CでOK。

プロジェクト配下のnodeのコマンドを実行する

Rubyでいうところのbundle exec 〜に該当するNodeのコマンドってなんだろう?と思って雑に呟いたら、色々と教えてもらえました。

というわけで、yarn run 〜がよさそう。npxもいいけれど、間違えて入れていないパッケージの命令を書いたらその場でダウンロードが始まるので遅いし。

GraphQLでWebAPIを作っている

自分が担当のプロダクトのWebAPIを整理していかんとほんまヤバいなぁ〜と思いつつ、数年過ごしていましたが、ここ最近で急激にGraphQL熱が湧き上がり、今お試しで実装していってる最中です。

ビビッときたのは、@gfxさんの書かれたGraphQL徹底入門の記事からです。

employment.en-japan.com

これを元に簡単な実装をしてみて、他の情報を探して…という感じ。

qiita.com

N+1にはgraphql-batch

概要を掴んだら、ModelにマッピングするようにTypeを生成していってたのですが、N+1問題が発生しやすいみたいな話を聞いていた通り、すぐ出始めました。graphql-batchを使えば、発生が抑えられるとのことだったので、情報を集めてやってみたところ、N+1は収まりました。

blog.agile.esm.co.jp

blog.kymmt.com

preloadして、極力クエリの発行を抑えるようになっています。ありがたい。

ちなみに最初は『preloadやeager_loadを使えば別にN+1起きないんじゃない?』と思って、Foo.preload(:bar)とかしていたのですが、これだとbarの情報にアクセスしていなくてもbarの情報を取得するためのクエリが実行されてしまいました(N+1にはならないけれど、無駄なクエリ)。graphql-batchは、barの情報にアクセスするときだけ、barをpreloadしてくれたので、graphql-batchを使った方がいいでしょう。

Loaderの実装は、サンプルからそのまま拝借しました。

graphql-batch/examples at 058213b78775c791135bf7db784b7d10007d5ade · Shopify/graphql-batch · GitHub

Loaderの記述がしんどい

とはいえ、Loaderの記述が多くなると、同じようなコードになってしまい辛いです。

module Types
  class HogeType < Types::BaseObject
    field :id, ID, null: false
    field :piyos, [Types::PiyoType], null: false
    field :fugas, [Types::FugaType], null: false

    # piyosもfugasも殆ど同じ…
    def piyos
      Loaders::AssociationLoader.for(Hoge, :piyos).load(object)
    end

    def fugas
      Loaders::AssociationLoader.for(Hoge, :fugas).load(object)
    end
  end
end

というわけでメタプログラミングします。継承元のTypes::BaseObjectにクラスメソッドpreload_associationsを追加しました。やってることは、引数のシンボル名のメソッドを定義してしまうということだけです。

module Types
  class BaseObject < GraphQL::Schema::Object

    def self.preload_associations(*assciations)
      model_name = self.class_name[0..-5] # HogeTypeのTypeを削除する
      model = Kernel.const_get model_name # model Hoge を取得
      assciations.each do |association_name|
        define_method association_name do
          Loaders::AssociationLoader.for(model, association_name).load(object)
        end
      end
    end
  end
end

これにより、preload_assciationsを呼べば済むようになりました🎉

module Types
  class HogeType < Types::BaseObject
    field :id, ID, null: false
    field :piyos, [Types::PiyoType], null: false
    field :fugas, [Types::FugaType], null: false

    # これでOK
    preload_associations :piyos, :fugas
  end
end

配列型のせいでN+1発生もLoaderで解決

PostgreSQLの配列型を一部で使っているのですが、これもN+1問題が発生しました。配列型ではRailsのAssociationを表現しているわけではないので、自分でLoadしてあげないといけません。

module Types
  class HogeType < Types::BaseObject
    field :id, ID, null: false

    # これらはAssociation
    field :piyos, [Types::PiyoType], null: false 
    field :fugas, [Types::FugaType], null: false

    preload_associations :piyos, :fugas

    # これらは配列型
    field :foos, [Types::FooType], null: false
    field :bars, [Types::BarType], null: false

    # 配列型はload_manyを使って登録しておくとよい
    def foos
      Loaders::RecordLoader.for(Foo).load_many(object.foo_ids)
    end

    def bars
      Loaders::RecordLoader.for(Bar).load_many(object.bar_ids)
    end
  end
end

今の所の感想

graphqlの実装していくのは楽しい!!graphiqlからクエリ発行して芋づる式にデータが取れるのがめちゃくちゃ面白いです。ただし、クエリのネストが深くなると途端に重くなりますが…。 まだ更新系のクエリの実装はしていないので、そちらでも知見が貯まったら何か書こうと思います。

CircleCIでエラーコードを無視して処理する

昨日書いてたやつで、rake releaseが実行されないパターンにあうとどうもエラーで落ちることがわかった。 grepの条件に該当しなかったのでエラーコードが1になっているんだが、それがダメらしい。

しゃーないから最後の行でexit 0を返すようにしてみたんだけれど、それも意味なし。どうもエラーコードが0以外になった時点でもうダメっぽい。 回避策を探していたところ、CircleCIのDiscussがヒットした。

discuss.circleci.com

set +eしろとある。これってなんなのだろう?

journal.lampetty.net

調べたところ、set -eしてあると、エラーコードに0以外が入った時点でスクリプトが終了するという設定らしい。CircleCIはそうなっているのだろう。それを解除するのが、set +eのようだ。

ローカルで該当job(release)を実行して確認したところ、成功するようになった。

$ circleci config process .circleci/config.yml > .circleci/config.processed.yml
$ circleci local execute --config .circleci/config.processed.yml --job release

# 色々あって…
Success!

CircleCIのテストが通ったらrake releaseする

前回の記事で、TravisCIからCircleCIに移行したことを書いた。

patorash.hatenablog.com

今回は、テストが通ったら自動的にrake releaseする仕組みを作ったので、それについて書く。 ただし、今回のやつは結構面倒であった。

gemをリリースするorbsは既にある

実はもう既にある模様だが、なんとなく実装が好きになれなかった。

https://circleci.com/orbs/registry/orb/doximity/gem-publisher

  • gem/nameとgem/versionというファイルにgemの名前とバージョン情報を書かなければならないこと
  • rake releaseを使わずにgemをrubygemsにpushしていること
  • たぶん、gemの名前が部分一致してしまうものだと機能しない

そこで、とりあえず自分でやってみることにした。が、実装は参考にさせてもらった。

実装

先に実装を載せておく。結構面倒です。何をやっているのかを書いていく。

  1. チェックアウト
  2. GitHubにアクセスするためのSSH鍵の登録
  3. bundle install
  4. RubygemsにgemをリリースするためのAPI KEYを設定
  5. gitのセットアップ(githubにタグを打つために必要)
  6. 同バージョンがまだリリースされていなければ、rake releaseする
  7. RubygemsにリリースするためのAPI KEY情報を消す

このうち、4,6,7は先ほどのorbsをかなり参考にさせてもらった。

jobs:
  release:
    executor:
      name: ruby
    parallelism: 1
    steps:
      - checkout
      - add_ssh_keys:
          fingerprints:
            - "e7:e8:17:c5:03:05:fd:0c:0e:9b:3b:d3:90:53:c6:5c"
      - run:
          name: bundle install
          command: bundle check || bundle install --jobs=4 --retry=3
      - run:
          name: RubyGems.org | Set credential
          command: |
            mkdir -p ~/.gem
            echo ":rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials
            chmod 0600 ~/.gem/credentials
      - run:
          name: Setup git
          command: |
            git config push.default current
            git config user.email "chariderpato@gmail.com"
            git config user.name "patorash"
      - run:
          name: rake release
          command: |
            gem list --prerelease --all --remote imyou \
              | grep -E "^imyou" \
              | sed -e "s/^.*(\(.*\)).*\$/\1/" \
              | grep -q -v "`bundle exec ruby -e "print Imyou::VERSION"`"
            result=$?
            if [ $result = 0 ]; then
              bundle exec rake build
              bundle exec rake release
            fi
      - run:
          name: Delete credentials
          command: |
            shred -u ~/.gem/credentials

GitHubにアクセスするためのSSH鍵の登録

rale releaseでタグを打つには、読み書き可能なSSH鍵が必要なため、以下のサイトを参考にして作業した。

sue445.hatenablog.com

qiita.com

SSH秘密鍵、公開鍵の作成

まず、秘密鍵と公開鍵を作る。

$ cd ~/.ssh
$ ssh-keygen -t rsa -b 4096 -m pem -C "CircleCI" -f id_rsa_circleci -N ""
GitHubに公開鍵を登録

次に、https://github.com/[username]/[reponame]/settings/keys にアクセスして、公開鍵を登録する。

f:id:patorash:20190327155104p:plain

id_rsa_circleci.pubの内容を貼り付けて保存する。このとき、Allow write accessにチェックを入れるのを忘れないこと。 保存できたら、もともと登録されていたであろうread onlyの鍵を削除しておく。

CircleCIに秘密鍵を登録

次に、https://circleci.com/gh/[username]/[reponame]/edit#ssh にアクセスして、秘密鍵を登録する。

f:id:patorash:20190327155755p:plain

id_rsa_circleciの内容を貼り付けて保存する。

その後、https://circleci.com/gh/[username]/[reponame]/edit#checkout にアクセスして、デプロイキーを削除する(これがread onlyのやつの秘密鍵)。

RubygemsAPI KEYを環境変数に保存

RubygemsAPI KEYはRubygemsにログインしてプロフィールの編集画面にいったら書いてある。

f:id:patorash:20190327160520p:plain

この値を、CircleCIの環境変数に登録する。変数名は、RUBYGEMS_API_KEYにする。

f:id:patorash:20190327160712p:plain

gitの設定

タグを打つ時にgitの設定が必要なので行なっておく。

rake releaseする

テストが通ったらrake releaseしたいが、もしgemのバージョンアップを含まない変更だった場合、実行されてしまうと既にリリース済みというメッセージと共にCIが落ちるので、バージョンアップしていない場合は無視したい。

先のorbsの実装のコマンドを実行したところ、gem list 〜の結果に自分のgemとは異なるgemまで出てきた。

$ gem list --prerelease --all --remote imyou                                                                                                                                                                                     16:12:18

*** REMOTE GEMS ***

bimyou_segmenter (1.2.0, 1.1.1, 1.0.1)
imyou (1.3.1, 1.3.0, 1.2.0, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.0)

imyouというgem名なのだが、bimyou_segmenterまで引っかかった。bimyou_segmenterという名前なので仕方がない…。なので、imyouで先頭一致する行を抽出した。

$ gem list --prerelease --all --remote imyou | grep -E "^imyou"
imyou (1.3.1, 1.3.0, 1.2.0, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.0)

あとは、バージョン情報だけ抽出し(括弧の中のみ)、現在のgemのバージョンの文字列があるかどうかチェックした。

gem list --prerelease --all --remote imyou \
  | grep -E "^imyou" \
  | sed -e "s/^.*(\(.*\)).*\$/\1/" \
  | grep -q -v "`bundle exec ruby -e "print Imyou::VERSION"`"
result=$?
if [ $result = 0 ]; then
  bundle exec rake build
  bundle exec rake release
fi

細かいことを言うと、1.3.1をリリースする前に1.3.1.preとかがあると、ヒットしてしまって正式リリースがこのワークフローでは行えない。しかし、文字列を分割して配列に入れて完全一致するバージョンの有無を調べるのがbashだと面倒そうだったので、こうしている。簡単な方法があれば採用したい…。

あと、gem名とバージョン情報がハードコーディングになっている。多分、これがうまく取れないからorbsの作者も、gem/nameとgem/versionというファイルを保存するという苦肉の策をしているのだろう…。ここをエレガントに取得する方法があったら知りたい。

ワークフローに組み込む

テストが通ったらrake releaseする(ただしmasterブランチのみ)とした。

workflows:
  build:
    jobs:
      - test:
          name: 'Ruby 2.4.5-Rails 4.2'
          ruby_version:  '2.4.5'
          rails_version: '4.2'
      - test:
          name: 'Ruby 2.5.5-Rails 4.2'
          ruby_version:  '2.5.5'
          rails_version: '4.2'
      - test:
          name: 'Ruby 2.6.2-Rails 4.2'
          ruby_version:  '2.6.2'
          rails_version: '4.2'
      # 略
      - release:
          requires:
            - 'Ruby 2.4.5-Rails 4.2'
            - 'Ruby 2.5.5-Rails 4.2'
            - 'Ruby 2.6.2-Rails 4.2'
            # 略
          filters:
            branches:
              only: master

実行したところ、成功!

f:id:patorash:20190327162845p:plain

releaseジョブの中身を確認しても、ちゃんとpushできていた。

#!/bin/bash -eo pipefail
gem list --prerelease --all --remote imyou \
  | grep -E "^imyou" \
  | sed -e "s/^.*(\(.*\)).*\$/\1/" \
  | grep -q -v "`bundle exec ruby -e "print Imyou::VERSION"`"
result=$?
if [ $result = 0 ]; then
  bundle exec rake build
  bundle exec rake release
fi
imyou 1.3.1 built to pkg/imyou-1.3.1.gem.
imyou 1.3.1 built to pkg/imyou-1.3.1.gem.
Tagged v1.3.1.
Pushed git commits and tags.
Pushed imyou 1.3.1 to rubygems.org

課題

  • ハードコーディングをなんとかしたい(できればorbs化ができそう)
  • SSH鍵の登録が作業のハードルが高いと思う。API Tokenにできればいいが、rake releaseで使われるのがSSH鍵のほうだろうから、難しそうにも思う。

追記

ハードコーディングは、なんとかなった。

Before

gem list --prerelease --all --remote imyou \
  | grep -E "^imyou" \
  | sed -e "s/^.*(\(.*\)).*\$/\1/" \
  | grep -q -v "`bundle exec ruby -e "print Imyou::VERSION"`"
result=$?
if [ $result = 0 ]; then
  bundle exec rake build
  bundle exec rake release
fi

After

  1. gemspecファイルを探し出す
  2. ruby -e内で*.gemspecをロードして、gem名とバージョンを出力して変数に入れる
  3. ハードコーディングしていた箇所をそれらの変数で置き換える
set +e
filename=$(for n in *; do printf '%s\n' "$n"; done | grep gemspec)
gem_name=`ruby -e "require 'rubygems'; spec = Gem::Specification::load('${filename}'); puts spec.name"`
gem_version=`ruby -e "require 'rubygems'; spec = Gem::Specification::load('${filename}'); puts spec.version"`
gem list --prerelease --all --remote $gem_name \
  | grep -E "^${gem_name}" \
  | sed -e "s/^.*(\(.*\)).*\$/\1/" \
  | grep -q -v $gem_version
result=$?
if [ $result = 0 ]; then
  bundle exec rake build
  bundle exec rake release
fi

ということで、これをOrb化したいなぁ〜。

gemのCIをTravisCIからCircleCIに変更した

gem imyouのCIをTravisCIからCircleCIに変更した。

理由は単純で、普段からCircleCIを使っているので、CIの構築がやりやすいから。TravisCIは滅多に使わないのでわからなくなることが多く、それがストレスだった。他のgemもCircleCIに変更していこうと思うが、まぁ時間が取れたらやっていく…。

CircleCIに変更した際に、業務では使わなかったCircleCI 2.1の機能があったので、それを使えたのはいい経験だった。主にparametersである。

parametersを使う

parametersを使うと、executor, command, jobの一部を書き換えることができる。 gemのテストは複数のRubyのバージョンやRailsのバージョンで行いたいため、重宝した。

executorsの定義

定義は、以下のようにする。<< parameters.ruby_version >>に指定されたバージョンが入る。

executors:
  ruby:
    parameters:
      ruby_version:
        default: '2.6.2'
        type: enum
        enum: ['2.4.5', '2.5.5', '2.6.2']
    working_directory: ~/repo
    docker:
      - image: circleci/ruby:<< parameters.ruby_version >>-node-browsers

使う際は、以下のようにruby_versionを指定する。

jobs:
  test:
    executor:
      name: ruby
      ruby_version: '2.4.5'
    parallelism: 1
    steps:
      - run_test

commandsの定義

commandsでもparametersは使える。RubyのバージョンはexecutorsでRubyのdockerイメージのバージョン指定でなんとかなるが、RailsのほうはGemfileを変えないといけない。このあたりはTravisCIを使っていたときに実行されていた処理(BUNDLE_GEMFILEという環境変数を定義する)を拝借して作った。

commands:
  run_test:
    parameters:
      rails_version:
        default: '5.2'
        type: enum
        enum: ['4.2', '5.0', '5.1', '5.2']
    steps:
      - checkout
      - run:
          name: bundle install
          command: |
            export BUNDLE_GEMFILE=$PWD/gemfiles/rails_<< parameters.rails_version >>.gemfile
            bundle check || bundle install --jobs=4 --retry=3
      - rspec
      # 略

このbundle installの際に、--path=vendor/bundleを指定すると、なぜかgemfiles/vendor/bundleにgemがインストールされ、しかもパスが通っていないという謎でrspecコマンドが見つからないと言われてしまったので、敢えてpath指定を消した。しかし、そのせいでgemのキャッシュができないので、いい方法があったら教えてほしいところ。まぁgemのテストなので、毎回bundle installが実行されるほうがいいのかもしれない、とポジティブに捉えている(が、遅いのは気になる)。

jobsの定義

これらを組み合わせて、jobsでも引数を使えるようにする。

jobs:
  test:
    parameters:
      ruby_version:
        type: enum
        enum: ['2.4.5', '2.5.5', '2.6.2']
      rails_version:
        type: enum
        enum: ['4.2', '5.0', '5.1', '5.2']
    executor:
      name: ruby
      ruby_version: << parameters.ruby_version >>
    parallelism: 1
    steps:
      - run_test:
          rails_version: << parameters.rails_version >>

workflowsからjobを呼ぶ

あとは、先ほど作ったtestジョブにRubyのバージョンとRailsのバージョンを渡してテストを実行する。RubyのバージョンとサポートするRailsのバージョンとの組み合わせの数だけテストが並列になるので、書くのがしんどい。TravisCIは配列でRubyのバージョンと配列でgemfileを定義したらよしなに組み合わせしてくれていたので、その点はTravisCIのほうがいいなと思う。

workflows:
  build:
    jobs:
      - test:
          name: 'Ruby 2.4.5-Rails 4.2'
          ruby_version:  '2.4.5'
          rails_version: '4.2'
      - test:
          name: 'Ruby 2.5.5-Rails 4.2'
          ruby_version:  '2.5.5'
          rails_version: '4.2'
      - test:
          name: 'Ruby 2.6.2-Rails 4.2'
          ruby_version:  '2.6.2'
          rails_version: '4.2'
      # 略

実行結果

実行結果のワークフローの見た目はこんな感じになって気持ち良い。

f:id:patorash:20190327151340p:plain
CircleCIでRubyRailsのバージョンの組み合わせてgemの並列テスト

課題

せっかくなので、masterでテストが通ったらrake releaseするようにしたいなと思い、試行錯誤中。 ハードコーディングなら、一応できたので、また後日記事にしようかなと思う。

WSL + Docker for WindowsでRailsアプリを動かしたが遅すぎた

これはノウハウとかじゃなくてただの日記。

この前久々にLenovoのPCを触れたので、Docker for Windowsの設定をして、WSLでdocker-compose upできて喜んでいたが、Railsアプリを起動するところまで時間が取れなかった。昨日ようやく少し時間が取れたのでやってみたところ、動いた。WSLでbin/rails sしてから普通にhttp://localhost:3000にアクセスして画面を表示することもできた。

できたが、めちゃくちゃ遅かった。画面遷移するのに10秒以上かかっていたんじゃないかと思う。初回のアクセスはJSとCSSのトランスパイルが実行されるからもっと遅かった。1分半くらいかかっていたように思う。さすがに開発に使うには厳しい。

WSLの起動自体はめっちゃ速いし、普通に使う分には問題ないのだけれど、どうしたもんかなぁ…という気持ち。vagrantUbuntuを入れてそこに開発環境をセットアップしたほうがいいのかな?いい方法をご存知の方がいれば教えてください。