GameWith Developer Blog

GameWith のエンジニア、デザイナーが技術について日々発信していきます。

ダッシュボードの新機能開発にVue.jsを導入した背景と苦労したこと #GameWith #TechWith

こんにちは!サーバサイドエンジニアのkuromokaです!

こちらの記事でもあったように、GameWithのリプレイス開発ではVue.jsを使っています。 tech.gamewith.co.jp

今回はリプレイスではなく、GameWithの社員の方が使っているダッシュボードの新機能開発に、Vue.jsを導入した背景と苦労したことについて、お話します。

Vue.jsを導入した背景

GameWithのダッシュボードは社員の方しか見れない画面で、フロント側は次のような技術が使われています。

  • Bootstrap v2.0.3
  • jQuery v1.8.3

それぞれのリリース日を調べてみたら、Bootstrap v2.0.3は2012年の4月*1、jQuery v1.8.3は2012年の11月*2のようです。

2020年の今となってはかなり昔のバージョンを使っているのですが、裏側の画面のためにフロント側で凝った画面にする機会があまりなく、苦労さは感じつつ開発はしていました。

ただダッシュボードが使い辛いことでの作業効率が下がっているという話はたびたび聞いていて、今回もそういった作業効率を改善するための新機能開発でした。

今回の新機能はかなり根本的な改善を行うための機能だったため、フロントの改修も大幅に必要な見込みになりました。

開発チームでも相談して、この開発を今のフロント環境でやるのはちょっと辛いなということになりました。 あとはダッシュボードなので比較的新しい技術を取り入れやすいというのもありました。

そういった経緯で、今回はVue.jsを採用することにしました。具体的には次のような技術を使いました。

  • Vue.js v2.6.11
  • Composition API
    • Vue.js3系に備えて採用。v2系のため@vue/composition-api を導入
  • BootstrapVue
    • Bootstrap v4ベースのコンポーネントを、Vueコンポーネントとしてコーディングするため
  • Vue CLI
  • TypeScript
  • Jest
  • Go(バックエンドAPI)
    • Vue.jsからは基本的にGoのAPI経由で、データの取得や更新を行う

Vue.jsの導入で苦労したこと

今回の新機能開発に関しては、開発環境が整ってからはVue.jsの恩恵も受けながらスムーズに開発できたので、新しい環境にして良かったと思っています。*3

ただVue.jsの導入までが、既存プロジェクトへ導入するような事例があまり見つからないのと、私自身もそこまでVue.jsに詳しいわけではなかったので結構苦労しました。

細かいところを含めればもっと紹介したいのですが長くなってしまうので、今回は「既存プロジェクトへのVue.jsの導入で苦労したこと」について、3点紹介します。

1. Vue.jsのインストールからビルドまで

Vue.js公式ドキュメントには、CDN・NPM・Vue CLIでのインストールが紹介されています。最初は一番手軽なCDNにしようとも思ったのですが、今後規模が大きくなることやビルド設定が最初から入っていることもあり「Vue CLI」でインストールをしました。 jp.vuejs.org

ダッシュボードの画面はPHPで動いています。PHPのプロジェクト内に、Vue CLIで「frontend」プロジェクトを作りました。

$ cd ${DASHBOARD_APP_PATH}
$ vue create frontend


Vue CLI v4.1.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Linter, Unit
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Pick a linter / formatter config: Basic
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
? Pick a unit testing solution: Jest
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No

Vue CLIはビルド設定が最初から入っているため、$ npm run build するだけで、ビルド結果が出力されるのはすごく楽でした。

ただそのままだとVue CLIで作った、「frontend」プロジェクト内にビルド結果が出力されます。公開フォルダにはしていないため、PHPから参照することができません。

そのためアセットの公開フォルダに対して、ビルド結果が出力されるように、vue.config.jsファイル*4を作って設定を調整しました。

具体的には、次のようにoutputDirassetsDir を調整しました(いろいろな事情がありVue CLIのプロジェクトが深くなっているので、こんな相対パスになっています)。

module.exports = {  
  outputDir: '../../../../../public/', 
  assetsDir: './assets/frontend/',
}

最後に公開フォルダに出力するようにしたビルドファイルを、PHPから読み込むようにしました。

<script src="/assets/frontend/js/app.js"></script>

2. カレントパスによるコンポーネントの切り替え

見ているページのカレントパスでVueコンポーネントを切り替えるために、「vue-router」を使いました。 router.vuejs.org

初期化時に追加していなかったので$ vue add routerで後から追加しました。このコマンドでvue-routerのインストールとサンプル用のルーティング設定まで一通りやってくれます。

Vue CLIはデフォルト設定だと #appの要素にApp.vueがマウントされる設定になっています。今回App.vue<router-view/>を追加して、この部分をvue-routerで切り替えるようにしました。

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

PHPからは、Vueコンポーネントを表示したい箇所に#appを書きます。あとはvue-routerのルーティング設定を調整すれば、カレントパスによって#appの部分が切り替わるようになります。

<div id="wrap">
  <div id="app"></div>
</div>

3. ホットリロードで開発する

今回一番苦労した点です。

Vue CLIには最初からホットリロードが有効な開発サーバが$ npm run serveで起動できるようになっています。
ただ今回は「PHPの一部分をVue.jsにした環境で、Vue.jsの部分だけホットリロード」するような挙動にしたかったので、そのままでは開発サーバが使えませんでした。

そのためしばらくは$ npm run buildで毎回ビルドして確認していましたが面倒で開発効率が悪いので、なんとかホットリロードを使えないか調べてみました。

調べていく中で、vue.config.jsdevServer.proxyという、設定が使えそうなことが分かりました。この設定を使うと開発サーバの特定パスへリクエストがあったときに、別サーバにプロキシさせてリクエストすることができるようになります。 cli.vuejs.org

一部省略していますが、実際に設定したvue.config.jsは次のような感じです。http://php-local-server/はPHPのローカル開発サーバです。/なので全てのリクエストをPHPにプロキシさせています。

module.exports = {  
  host: '0.0.0.0', 
  port: 9000,   
  proxy: {   
    '/': {  
      target: 'http://php-local-server/',  
      secure: false,   
      cookieDomainRewrite: 'localhost',        
    },
}

PHPではサーバ変数の$_SERVER['HTTP_X_FORWARDED_HOST']でプロキシ時のホスト名を取ることができます。
この値を見てlocalhost:9000の場合にhttp://localhost:9000からのパスで、ビルドファイルを読み込むようにしました。

<script src="http://localhost:9000/assets/frontend/js/app.js"></script>

ここまで設定すれば、

  • $ npm run serveで、Vue CLIの開発サーバを起動
  • http://localhost:9000/vue-js-pathで、Vue.jsを使っているページを見る
    (PHPのhttp://php-local-server/vue-js-pathがプロキシ経由で表示される)
  • Vueコンポーネントを更新するとビルドが走って、Vue.jsの部分だけ自動でリロードされる

という感じで開発ができるようになって毎回のビルドが不要になりました!これで当初目指した「PHPの一部分をVue.jsにした環境で、Vue.jsの部分だけホットリロード」を実現することができました。

まとめ

今回はダッシュボードの新機能開発に伴う、「Vue.jsを導入した背景」と「Vue.jsの導入で苦労したこと」をお伝えしました。

記事で紹介した「frontend」プロジェクトは、今は「GameWithのリプレイスについて vol.2 ~Web Components を Vue で書いたら最高だった編~ #GameWith #TechWith - GameWith Developer Blog」で紹介した「GameWithDesignSystem」のように別システム化をして、PHPのプロジェクトから独立して開発できる環境に改善をしています。

今回の内容が同じような悩みの人に対して、少しでも参考になる情報だったら嬉しいです!

終わりに

GameWithのDeveloper向けTwitterアカウントを開設しました。

技術やブログの更新情報などを発信するので良かったらフォロー宜しくお願いします!

https://twitter.com/gamewith_devtwitter.com

*1:https://blog.getbootstrap.com/2012/04/24/bootstrap-2-0-3-released/

*2:https://blog.jquery.com/2012/11/13/jquery-1-8-3-released/

*3:Composition APIだけは苦労したのですが、RFCを見たりGitHubでコード検索をしたりして、書き方に慣れていくようにしました

*4:https://cli.vuejs.org/config/ 今回このファイルを触る機会が多かったので、とても参考になったページです