CloudFlareにデプロイするためのRemixプロジェクトでプレビュー環境にて動作を確認する

## 概要

プレビュー環境にて動作を確認する方法をまとめる

## 前提

下記の内容が完了していること

https://qiita.com/miriwo/items/48bc487a8cc796de61e2

## 説明

プレビュー環境とは、ローカル開発環境（`npm run dev`を実行して`http://localhost:5173/`とかでアクセスするやつ）と本番環境（`npm run deploy`を実行してクラウドフレアが用意した「サイトにアクセス」からアクセスするやつ）とは別にプレビュー環境なるものが存在する。
これはより本番環境に近い環境で動作確認をするためのものであり、一般的な開発で言われるステージング（STG）環境や開発（DEV）環境と呼ばれるものの役割に近い。
どうやらCloudFlareはこのプレビュー環境が簡単にデプロイできて、簡単に動作確認できるらしいので今回使ってみる。

## 方法

1. CloudFlare上でプレビュー環境用のDBを作成（筆者は「todo-cloudflare-d1-preview」というD1のデータベースを作成）

    ![CleanShot 2024-06-19 at 14.55.59@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/4d462daf-afc8-9ced-d6d1-7fd31a4d4374.png)

1. D1の一覧では下記のように2個のDBが表示されている状態

    ![CleanShot 2024-06-19 at 14.58.47@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/a9e19f1d-9278-26f6-5eba-1ebf5ab8ea56.png)

1. 今作成したプレビュー環境用のD1のデータベースIDをメモする
1. `wrangler.toml`のd1_databasesの設定に下記のキーバリューを追加

    ```wrangler.toml
    preview_database_id = "本記事で作成したプレビュー環境用D1のデータベースID"
    ```

1. `wrangler.toml`のd1_databasesの設定は下記のようになった

    ```wrangler.toml
    # Bind a D1 database. D1 is Cloudflare’s native serverless SQL database.
    # Docs: https://developers.cloudflare.com/pages/functions/bindings/#d1-databases
    [[d1_databases]]
    binding = "DB"
    database_name = "すでに設定済みの本番環境用D1のデータベース名"
    database_id = "すでに設定済みの本番環境用D1のデータベースID"
    preview_database_id = "本記事で作成したプレビュー環境用D1のデータベースID" # ここが今回追記された
    ```

1. `wrangler.toml`の`######## PREVIEW environment config ########`の付近を修正するのでまずは記載前の状態は下記

    ```wrangler.toml
    ######## PREVIEW environment config ########
    
    # [env.preview.vars]
    # API_KEY = "xyz789"
    
    # [[env.preview.kv_namespaces]]
    # binding = "MY_KV_NAMESPACE"
    # id = "<PREVIEW_NAMESPACE_ID>"
    ```

1. `wrangler.toml`の`######## PREVIEW environment config ########`の付近を下記のように修正

    ```wrangler.toml
    ######## PREVIEW environment config ########
    
    [env.preview]
    name = "todo-cloudflare-d1-preview"
    compatibility_date = "2024-06-05"
    
    [[env.preview.d1_databases]]
    binding = "DB" # [[d1_databases]]のbindingの値と同じものを設定
    database_name = "本記事で作成したプレビュー環境用D1のデータベース名"
    database_id = "本記事で作成したプレビュー環境用D1のデータベースID"
    
    # [env.preview.vars]
    # API_KEY = "xyz789"
    
    # [[env.preview.kv_namespaces]]
    # binding = "MY_KV_NAMESPACE"
    # id = "<PREVIEW_NAMESPACE_ID>"
    ```

1. 筆者の`wrangler.toml`の全体の状態を例として表示

    ```wrangler.toml
    #:schema node_modules/wrangler/config-schema.json
    name = "todo-cloudflare-d1"
    compatibility_date = "2024-06-05"
    pages_build_output_dir = "./build/client"
    
    # Automatically place your workloads in an optimal location to minimize latency.
    # If you are running back-end logic in a Pages Function, running it closer to your back-end infrastructure
    # rather than the end user may result in better performance.
    # Docs: https://developers.cloudflare.com/pages/functions/smart-placement/#smart-placement
    # [placement]
    # mode = "smart"
    
    # Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
    # Docs:
    # - https://developers.cloudflare.com/pages/functions/bindings/#environment-variables
    # Note: Use secrets to store sensitive data.
    # - https://developers.cloudflare.com/pages/functions/bindings/#secrets
    # [vars]
    # MY_VARIABLE = "production_value"
    
    # Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflare’s global network
    # Docs: https://developers.cloudflare.com/pages/functions/bindings/#workers-ai
    # [ai]
    # binding = "AI"
    
    # Bind a D1 database. D1 is Cloudflare’s native serverless SQL database.
    # Docs: https://developers.cloudflare.com/pages/functions/bindings/#d1-databases
    [[d1_databases]]
    binding = "DB"
    database_name = "すでに設定済みの本番環境用D1のデータベース名"
    database_id = "すでに設定済みの本番環境用D1のデータベースID"
    preview_database_id = "本記事で作成したプレビュー環境用D1のデータベースID" # ここが今回追記された
    
    # Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
    # Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
    # Docs: https://developers.cloudflare.com/workers/runtime-apis/durable-objects
    # [[durable_objects.bindings]]
    # name = "MY_DURABLE_OBJECT"
    # class_name = "MyDurableObject"
    # script_name = 'my-durable-object'
    
    # Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
    # Docs: https://developers.cloudflare.com/pages/functions/bindings/#kv-namespaces
    # [[kv_namespaces]]
    # binding = "MY_KV_NAMESPACE"
    # id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    
    # Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
    # Docs: https://developers.cloudflare.com/pages/functions/bindings/#queue-producers
    # [[queues.producers]]
    # binding = "MY_QUEUE"
    # queue = "my-queue"
    
    # Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files.
    # Docs: https://developers.cloudflare.com/pages/functions/bindings/#r2-buckets
    # [[r2_buckets]]
    # binding = "MY_BUCKET"
    # bucket_name = "my-bucket"
    
    # Bind another Worker service. Use this binding to call another Worker without network overhead.
    # Docs: https://developers.cloudflare.com/pages/functions/bindings/#service-bindings
    # [[services]]
    # binding = "MY_SERVICE"
    # service = "my-service"
    
    # To use different bindings for preview and production environments, follow the examples below.
    # When using environment-specific overrides for bindings, ALL bindings must be specified on a per-environment basis.
    # Docs: https://developers.cloudflare.com/pages/functions/wrangler-configuration#environment-specific-overrides
    
    ######## PREVIEW environment config ########
    
    [env.preview]
    name = "todo-cloudflare-d1-preview"
    compatibility_date = "2024-06-05"
    
    [[env.preview.d1_databases]]
    binding = "DB" # [[d1_databases]]のbindingの値と同じものを設定
    database_name = "本記事で作成したプレビュー環境用D1のデータベース名"
    database_id = "本記事で作成したプレビュー環境用D1のデータベースID"
    
    # [env.preview.vars]
    # API_KEY = "xyz789"
    
    # [[env.preview.kv_namespaces]]
    # binding = "MY_KV_NAMESPACE"
    # id = "<PREVIEW_NAMESPACE_ID>"
    
    ######## PRODUCTION environment config ########
    
    # [env.production.vars]
    # API_KEY = "abc123"
    
    # [[env.production.kv_namespaces]]
    # binding = "MY_KV_NAMESPACE"
    # id = "<PRODUCTION_NAMESPACE_ID>"
    
    ```

1. `package.json`のscriptsの`"preview": "npm run build && wrangler pages dev",`の記載を下記のように変更

    ```package.json
    "preview": "npm run build && wrangler pages deploy --branch preview",
    ```

1. `package.json`のscriptsにプレビュー用DBに変更を加えるコマンドを追加

    ```package.json
    "preview-seed": "./execute_seeds.sh --preview",
    "preview-migrate": "npx wrangler d1 migrations apply todo-cloudflare-d1 --preview --remote",
    "preview-migrate-fresh": "npx wrangler d1 execute todo-cloudflare-d1 --preview --remote --file ./seeds/drop_tables.sql",
    "preview-migrate-reset": "npm run preview-migrate-fresh && npm run preview-migrate",
    "preview-migrate-reset-and-seed": "npm run preview-migrate-reset && npm run preview-seed",
    ```

1. 最終的に`package.json`のscriptsの中身は下記の状態

    ```package.json
    "scripts": {
      "build": "remix vite:build",
      "deploy": "npm run build && wrangler pages deploy",
      "dev": "remix vite:dev",
      "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
      "start": "wrangler pages dev ./build/client",
      "typecheck": "tsc",
      "typegen": "wrangler types",
      "preview": "npm run build && wrangler pages deploy --branch preview",
      "cf-typegen": "wrangler types",
      "local-seed": "./execute_seeds.sh --local",
      "local-migrate": "npx wrangler d1 migrations apply todo-cloudflare-d1 --local",
      "local-migrate-fresh": "npx wrangler d1 execute todo-cloudflare-d1 --local --file ./seeds/drop_tables.sql",
      "local-migrate-reset": "npm run local-migrate-fresh && npm run local-migrate",
      "local-migrate-reset-and-seed": "npm run local-migrate-reset && npm run local-seed",
      "preview-seed": "./execute_seeds.sh --preview",
      "preview-migrate": "npx wrangler d1 migrations apply todo-cloudflare-d1 --preview --remote",
      "preview-migrate-fresh": "npx wrangler d1 execute todo-cloudflare-d1 --preview --remote --file ./seeds/drop_tables.sql",
      "preview-migrate-reset": "npm run preview-migrate-fresh && npm run preview-migrate",
      "preview-migrate-reset-and-seed": "npm run preview-migrate-reset && npm run preview-seed",
      "remote-seed": "./execute_seeds.sh --remote",
      "remote-migrate": "npx wrangler d1 migrations apply todo-cloudflare-d1 --remote",
      "remote-migrate-fresh": "npx wrangler d1 execute todo-cloudflare-d1 --remote --file ./seeds/drop_tables.sql",
      "remote-migrate-reset": "npm run remote-migrate-fresh && npm run remote-migrate",
      "remote-migrate-reset-and-seed": "npm run remote-migrate-reset && npm run remote-seed"
    },
    ```

1. 下記を実行してpreviewブランチを作成してスイッチ

    ```shell
    git branch preview
    git switch preview
    ```

1. 下記を実行してマイグレーション、seed、プレビュー環境へのデプロイをそれぞれ実行

    ```shell
    npm run preview-migrate
    npm run preview-seed
    npm run preview
    ```

1. `npm run preview`の実行結果に表示されているリンクにブラウザからアクセス

    ![CleanShot 2024-06-19 at 16.04.04@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/ffec3791-4c63-570f-357d-ef9d51fd60e2.png)

1. 下記のように表示され、動作もローカル同様動くことを確認

    ![CleanShot 2024-06-19 at 16.05.52@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/d87a0fed-e0b4-d244-21c7-f7cb0f1f2a87.png)

1. 本当にpreview用のD1を見に行っているか不安なので`seeds/task_category_masters_seed.sql`を下記のように修正

    ```seeds/task_category_masters_seed.sql
    -- InsertTable
    INSERT INTO task_category_masters (name) VALUES ('Work_PREVIEW');
    INSERT INTO task_category_masters (name) VALUES ('Study_PREVIEW');
    INSERT INTO task_category_masters (name) VALUES ('Other_PREVIEW');
    ```

1. 下記を実行してマイグレーションのリセットとseedの実行

    ```shell
    npm run preview-migrate-reset-and-seed
    ```

1. プレビュー環境に画面からアクセスすると下記のようにプレビュー用のD1のテーブルの中の情報が表示されているのでちゃんとプレビュー環境はプレビュー環境用D1を見れてそう

    ![CleanShot 2024-06-19 at 17.18.05@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/5c7107dd-7187-1689-5af4-06c9c2df6b88.png)

1. `seeds/task_category_masters_seed.sql`を下に戻しておく

    ```seeds/task_category_masters_seed.sql
    -- InsertTable
    INSERT INTO task_category_masters (name) VALUES ('Work');
    INSERT INTO task_category_masters (name) VALUES ('Study');
    INSERT INTO task_category_masters (name) VALUES ('Other');
    ```

## 注意事項

- `npm run preview`のコマンドは現在のコードを単純にビルドしてCloudFlare上のpreviweブランチに反映する。そのためおそらくローカルのリポジトリでpreviewブランチに移動する必要は無いはず。

## 参考文献

https://developers.cloudflare.com/d1/build-with-d1/local-development/

https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases

https://github.com/cloudflare/wrangler-legacy/issues/209#issuecomment-541654484