More than 1 year has passed since last update.

Webアプリのバージョン管理について、個人的に行っている内容のメモ。

Webアプリのバージョン

まずアプリケーションはセマンティックバージョニングで管理する。
http://semver.org/lang/ja/
APIの変更に互換性のない場合はメジャーバージョン、後方互換性があり機能性を追加した場合はマイナーバージョン、後方互換性を伴うバグ修正をした場合はパッチバージョンを上げる。

Webアプリということはnpmでgrunt・gulp・browserifyなどを使っていることが多いと思うので、package.jsonのversionを書き換えることによってアプリのバージョンを参照出来るようにする。

以下はbrowserifyを使っている場合の例

package.json
module.exports = function(grunt) {
  grunt.loadNpmTasks('grunt-browserify');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    browserify: {
      app: {
        files: {
          './app.js': ['src/index.js']
        },
        options: {
          banner: 'var version ="<%= pkg.version %>";'
        }
      }
    }
  });
};

bannerオプションでpackage.jsonのversionを埋め込んでいる。
この場合はグローバル変数として定義されてしまうので、concat等を使って無名関数で括ったり、何かオブジェクトに定義するようにしてもいいと思う。

メジャーバージョンを上げるとき

Ajaxなど通信インターフェースが変わるような、後方互換性がないリリースをしないといけないときについて。

URLにバージョンを含めて「/api/v1/getUser」などとするのは痛手になりやすい。
だいたいコードのコピペが発生してつらいし、バージョンアップ後にクライアント側でブラウザリロードが発生すればv1はもう使わないので残しておく意味もない。

というわけで、HTTPのレスポンスヘッダーにAPIバージョンを埋め込む。

X-Api-Version: 1

という感じで、APIのバージョンはメジャーバージョンのみを使っている。
あとはフロントエンド側でAjax通信をする際にX-Api-Versionを参照して、バージョンが新しくなっていればダイアログを表示してユーザーにリロードを行う旨を通知し、リロードを行う。

jQueryを使っているならAjaxのコールバック関数中に以下で取れる。

jqXHR.getResponseHeader('X-Api-Version');

$.ajaxのラッパー関数としてrequest関数などを作り、そこにエラー処理やデフォルト設定を詰め込んで、全てのAPI通信がそこを通るようにすると楽。

追記

こういったバージョンアップを稼働中のサービスで行うときは、ユーザーへの事前告知をしている前提でブラウザリロードしています。