kakakakakku blog

Weekly Tech Blog: Keep on Learning!

高機能な Feature Flag サービス「Unleash」の React SDK を試した

引き続き Feature Flag を実現するサービス「Unleash」を試していく.これまで「Unleash デモ」「Unleash Ruby SDK(サーバサイド SDK)」を試して以下の記事にまとめてある.今回は「Unleash React Proxy SDK(フロントエンド SDK)」を試す.

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Unleash Proxy

フロントエンドとネイティブアプリから「Unleash」を使う場合は,まず「Unleash Proxy」というコンポーネントを理解しておく必要がある.詳しくは以下のドキュメントに載っているけど,アプリケーションと Unleash server の間に位置するプロキシと言える.フラグをキャッシュしたり,API token を隠蔽したり,プロキシだけをセルフホスティングすることもできる.Unleash Proxyも GitHub に公開されている.

docs.getunleash.io

Unleash Proxy も Docker で簡単に構築できる.今回は Unleash serverUnleash Proxy をどちらも構築する必要があるため,前回使った Unleash serverdocker-compose.yml を拡張して,同時に構築できるようにした.以下の proxy エントリーを追加した.

version: "3.4"
services:
  web:
    build: .
    ports:
      - "4242:4242"
    environment:
      DATABASE_URL: "postgres://postgres:unleash@db/postgres"
      DATABASE_SSL: "false"
    depends_on:
      - db
    command: npm run start
    healthcheck:
      test: ["CMD", "nc",  "-z", "db", "5432"]
      interval: 1s
      timeout: 1m
      retries: 5
      start_period: 15s
  db:
    expose:
      - "5432"
    image: postgres:13
    environment:
      POSTGRES_DB: "db"
      POSTGRES_HOST_AUTH_METHOD: "trust"
    healthcheck:
      test: ["CMD", "pg_isready", "--username=postgres", "--host=127.0.0.1", "--port=5432"]
      interval: 2s
      timeout: 1m
      retries: 5
      start_period: 10s
  proxy:
    ports:
      - "3000:3000"
    depends_on:
      - web
    image: unleashorg/unleash-proxy
    environment:
      UNLEASH_PROXY_SECRETS: kakakakakku-secret
      UNLEASH_URL: http://web:4242/api/
      UNLEASH_API_TOKEN: 'xxxxx'

Unleash Proxyhttp://localhost:3000/proxy として構築されるため,以下のように API を実行できれば OK!Authorization ヘッダーには docker-compose.yml に設定したシークレット情報を乗せる.

$ docker-compose build
$ docker-compose up

$ curl -s http://localhost:3000/proxy/health
ok

$ curl -s http://localhost:3000/proxy -H 'Authorization: kakakakakku-secret' | jq .
{
  "toggles": []
}

フラグを追加する

実装をする前に「フラグ」「API token」を設定しておく.今回はサンプルとして「ウェブサイトのトップページに "関連リンク枠を表示する新機能"」というシナリオでフラグ管理をすることにする(適当すぎる!w).よって link というフラグを Release タイプとして設定しておく.「API token」は前回の記事と同じなので割愛する.

f:id:kakku22:20220114123440p:plain

React Proxy SDK

さっそく React Proxy SDK を試す.コードサンプルや設定値などは以下のドキュメントに載っている.

docs.getunleash.io

今回はドキュメントを参考にしつつ,create-react-app コマンドで作ったデフォルトアプリケーションに機能を追加していく.npm start で起動すると,http://localhost:4000/ で見慣れた Hello World 画面にアクセスできる.ポートに関しては,Unleash Proxy とカブってしまうため PORT=4000 にした.

$ npm install @unleash/proxy-client-react

$ npx create-react-app unleash-react
$ cd unleash-react

$ tree src
src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── reportWebVitals.js
└── setupTests.js

$ PORT=4000 npm start

f:id:kakku22:20220114123842p:plain

まず,src/index.js を以下のように実装する(一部抜粋して載せる).ポイントは config となり,Unleash Proxy のエンドポイントやシークレット情報を追加している.またフラグを再取得する秒数として refreshInterval も設定している.今回は2秒にした.

import FlagProvider from '@unleash/proxy-client-react';

const config = {
  url: 'http://localhost:3000/proxy',
  clientKey: 'kakakakakku-secret',
  refreshInterval: 2,
  appName: 'kakakakakku-blog'
};

ReactDOM.render(
  <React.StrictMode>
    <FlagProvider config={config}>
      <App />
    </FlagProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

次に src/App.js を以下のように実装する(一部抜粋して載せる).ポイントは useFlag() を使って link フラグを取得して,有効化されているときに <Link /> コンポーネントを表示している.あくまでサンプルを真似した最小実装になるため,実際にはもっと React のお作法に沿ってコンポーネントなどを構成する必要がある.

import logo from './logo.svg';
import './App.css';

import Link from './Components/Link';
import { useFlag } from '@unleash/proxy-client-react';

function App() {
  const enabled = useFlag('link');

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        { enabled ? <Link /> : null }
      </header>
    </div>
  );
}

export default App;

今回追加した <Link /> コンポーネント src/Components/Link.js は以下のように適当に実装した.

function Link() {
   return (
      <div className="Blog-header">
         <a className="Blog-link" href="https://kakakakakku.hatenablog.com/">kakakakakku blog</a>
      </div>
   );
}

export default Link;

管理画面でフラグを有効化すると「関連リンク枠を表示する新機能」を確認することができた!

f:id:kakku22:20220114123858p:plain

Variant

useFlag() と同様に useVariant() も使えるため,Variant を使って,機能を有効化しつつ,ユーザーによって異なる挙動を返すこともできる.前に紹介をした「Unleash デモ」のコード(src/App.jssrc/Components/*.js)を見るとイメージは掴める👍

github.com

まとめ

Feature Flag を実現するサービス「Unleash」で,今回は「Unleash React Proxy SDK(フロントエンド SDK)」を試した.Unleash Proxy など全体構成を理解することができた.「Unleash」のドキュメントを見ると本当に高機能でまだまだ多くの機能があるため,気になった機能があったらまた追加で試そうと思う!