Nwht0xn1

WikiHubのJavaScript管理をNode.jsベースに切り替えたCreated on 2016-08-06 by r7kamura

移行の経緯

そもそもWikiHubの外部ライブラリでない部分のJavaScriptは、10行ぐらいしかなかった。記事に絵文字でリアクションを付ける部分を、Reactで実装して非同期で処理したいなと思ったので、JavaScriptを書く機会が出来て移行することに。

移行前

  • 外部ライブラリを利用するときはnpmを利用する
  • 外部ライブラリはSprocketsのrequire経由で利用する
  • ES5相当のコードを記述する
  • SprocketsでprecompileしてS3に配置

移行後

  • 外部ライブラリを利用するときはnpmを利用する (変わらず)
  • 外部ライブラリはBrowserifyのrequire経由で利用する
  • ES6〜7相当のコードを記述し、babelでES5相当のコードに変換する
  • SprocketsでprecompileしてS3に配置 (変わらず)

詳細

ファイル構造

アプリ開発者が編集するJavaScriptのコードは、source/javascripts以下に置くようにした。

  • source/javascripts/bundles/*.js
  • source/javascripts/initializers/*.js
  • source/javascripts/lib/*.js

bundlesディレクトリには、最終的に出力されるJavaScriptファイルと一対一の関係になるようなファイルを置いている。例えば bundles/application.js などがある。initializersディレクトリには、JavaScriptが読み込まれたら実行してほしい処理を書いたファイルを置いている。application.jsからimportされる。libディレクトリには、クラスを定義したファイルを置いている。

ビルド

npm run build を実行すると source/javascirpts/bundles/application.js が変換されて app/assets/javascripts/application.js に結果が配置されるようにした。開発中は、JavaScriptに関係するファイルが変更されるたびに npm run build を実行してもらう...というのは面倒なので、npm run watch を別のプロセスで実行してもらうことにした。このへん複数人開発だとビルド方法を共有しないといけないので面倒だったりする。そもそも「CSSやJavaScriptは変換した結果生成されるもので、コードを書いただけでブラウザがそれを直接読み取ってくれるものではない」という認識づくりから始めないといけなかったりする。しかしWikiHubは個人で開発してるので何の問題も無し...。

{
  ...,
  "scripts": {
    "build": "npm run build:rm && npm run build:mkdir && npm run build:js",
    "build:js": "browserify source/javascripts/bundles/application.js -t babelify -o app/assets/javascripts/application.js",
    "build:mkdir": "mkdir -p app/assets/javascripts",
    "build:rm": "rm -rf app/assets/javascripts",
    "watch": "npm run build && watchify source/javascripts/bundles/application.js -t babelify -o app/assets/javascripts/application.js -v"
  }
}

Git

app/assets/javascripts/application.js はビルドで生成される二次データなので、Gitには登録しないことに。

# .gitignore
/app/assets/javascripts

デプロイ

元々Capistranoを利用していたので、deploy:assets:precompile が実行される直前に npm run build を実行して、app/assets/javascripts/application.js が生成されるようにした。

namespace :npm do
  desc "npm run build"
  task :build do
    on release_roles(fetch(:assets_roles)) do
      within release_path do
        execute :npm, "run build"
      end
    end
  end
end
before "deploy:assets:precompile", "npm:build"

capistrano-npmを利用していたので、npm install --production --silent --no-progress がデプロイ時に実行される状態だったが、今回からビルドのために devDependencies のライブラリも使うことになったので、--production は外した。

# config/deploy.rb
set :npm_flags, "--silent --no-progress"

良かったこと

  • 移行作業が20分ぐらいで終わった
  • ES6以上の機能を利用してコードを書けるようになった
  • 依存ライブラリの依存しているライブラリが勝手に解決されるようになった
  • watchifyが高速なおかげで、変換中にアクセスしてしまう恐れは無かった

悪かったこと

  • 一瞬で終わったとはいえ移行が面倒だった