RORK LABEN
DEADLINE — 8月31日から、Google Play の新規アプリと更新はすべて Android 16(API レベル36)を対象にする必要があります。残り7日ですEXTENSION — 条件を満たす場合は Play Console のフォームで11月1日までの延長を申請できますが、申請そのものを締切前に済ませる必要がありますMAX — Rork Max は React Native ではなくネイティブ Swift を生成し、クラウド上の Mac 群でビルドします。iPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessage が対象ですCOMPANION — Rork Companion アプリを使えば、有料の Apple Developer アカウントなしに実機の iPhone で動作を確認できます。設計・実装・テストをブラウザだけで回せる構成ですDEVTOOLS — Expo SDK 57 の React Native DevTools でライトモードとダークモードのエミュレーションが可能になりました。端末設定を切り替えずに両方の見え方を確認できますIOS27 — iOS 27 は9月に出ます。ベータ6が8月17日に配布され、RCS Universal Profile 3.0 対応で Android から届いたメッセージへの個別返信ができるようになりましたDEADLINE — 8月31日から、Google Play の新規アプリと更新はすべて Android 16(API レベル36)を対象にする必要があります。残り7日ですEXTENSION — 条件を満たす場合は Play Console のフォームで11月1日までの延長を申請できますが、申請そのものを締切前に済ませる必要がありますMAX — Rork Max は React Native ではなくネイティブ Swift を生成し、クラウド上の Mac 群でビルドします。iPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessage が対象ですCOMPANION — Rork Companion アプリを使えば、有料の Apple Developer アカウントなしに実機の iPhone で動作を確認できます。設計・実装・テストをブラウザだけで回せる構成ですDEVTOOLS — Expo SDK 57 の React Native DevTools でライトモードとダークモードのエミュレーションが可能になりました。端末設定を切り替えずに両方の見え方を確認できますIOS27 — iOS 27 は9月に出ます。ベータ6が8月17日に配布され、RCS Universal Profile 3.0 対応で Android から届いたメッセージへの個別返信ができるようになりました
記事一覧/アプリ開発
アプリ開発/2026-08-24上級

サムネイルの移設は、配信中の版が旧パスを要求し続ける前提で組みました

サーバー側で画像の置き場所を変えても、ストアで配信中の版はビルド時のパス組み立てを持ち続けます。旧新どちらのパスでも 200 を返す双方向フォールバック、画像とカタログの更新順序、CDN を挟んだまま実応答を確かめる手順を、壁紙アプリの運用で使っている形のまま共有します。

アセット配信3壁紙アプリ28Expo181運用設計8CDN2

プレミアム記事

6.5 インチ用に作り直したサムネイルを本ツリーへ移し終えて、あとはアップロードするだけ、というところで手が止まりました。

置き場所のディレクトリ名を変えたということは、いま App Store で配信されている版が組み立てる URL と、明日からサーバーに実体がある場所とが食い違う、ということです。手元のシミュレータでは最新のコードが動いていますので、この食い違いは開発中に一度も表へ出てきません。

個人開発で壁紙系のアプリを長く運用していると、この種の「サーバー側だけを整理する作業」が定期的に発生します。画像を1枚増やすたびに審査へ出すわけにはいきませんので、配信の実体はサーバー側へ寄せてあります。その結果、サーバーのディレクトリ構成を触る自由と、配信済みの版が焼き込んだ前提とが、正面からぶつかります。

移設そのものは10分で終わります。難しいのは、移設したあとで何を確認できたら「反映できた」と言い切ってよいのか、という部分でした。

配信済みの版が持ち続けるのは、画像ではなくパスの組み立て規則

リモート配信に切り替えたアプリがバイナリに持っているのは、画像そのものではありません。持っているのは、ID から URL を組み立てる規則です。

// 配信中の版(iOS 4.1.1)が持っている組み立て規則
const STORAGE_BASE = "https://storage.example.net";
const THUMB_DIR = "5_8inch/thumb_full";   // ビルド時に決まる
 
export function thumbUrl(app: string, id: number) {
  return `${STORAGE_BASE}/ios/wallpaper_apps/${app}/${THUMB_DIR}/${id}.jpg`;
}

この THUMB_DIR は、ユーザーの端末に入っている版が更新されるまで一文字も変わりません。サーバー側で 6_5inch/thumb_full/ へ移した瞬間から、配信中の版は存在しない場所を叩き続けます。

見落としやすいのは、この規則がアプリのバージョンごとに違うという点です。私が運用している壁紙アプリでは、iOS と Android で世代が揃っていません。iOS 側は 4.1.1、Android 側は 1.9.0 が主力で、それぞれ別のディレクトリ規約を持って出荷されています。移設の影響範囲は「アプリが何本あるか」ではなく、「いま実際に使われているバージョンが何種類あるか」で決まります。

ストア側の管理画面でバージョン別のアクティブ端末数を見ると、リリースから半年が経った版がまだ二桁パーセント残っていることは珍しくありません。自動更新をオフにしている方、通信環境の都合で更新が進まない端末、機種変更後に古いバックアップから復元された端末。旧パスは、こちらが移設を終えた翌日に消えてくれるものではありません。

リモート設定を入れても、効くのは「入れた版から」です

最初に考えたのは、THUMB_DIR をリモート設定から受け取る形へ直すことでした。

type RemoteConfig = { thumbDir?: string };
 
export async function loadThumbDir(): Promise<string> {
  try {
    const res = await fetch(`${API_BASE}/ios/wallpaper_apps/${app}/config.json`, {
      cache: "no-store",
    });
    const cfg = (await res.json()) as RemoteConfig;
    return cfg.thumbDir ?? "6_5inch/thumb_full";   // 取得できなければ現行既定
  } catch {
    return "6_5inch/thumb_full";                    // 通信不能でも組み立ては続ける
  }
}

設計としては素直です。ただ、これを入れても救えるのは「これを入れた版から先」だけでした。いま困っているのは、この分岐を持っていない版です。

ここが、私が最初に取り違えていた部分でした。リモート設定は将来の自由度を買う仕組みであって、過去に出荷した版へさかのぼって効くものではありません。過去に出した版を救えるのは、サーバー側の応答だけです。

同じ理由で、config.json のフォールバック既定値を固定文字列で書くのも避けています。既定値が実際の総数や置き場所とずれると、通信に失敗した端末だけが古い世界を見ることになります。配信中の総数を返す処理は、固定文字列をやめて同じ変数から組み立てる形へ直してあります。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
配信済みの版が何を前提にしているかを棚卸しして、サーバー側の整理をいつ・どの順で始めてよいかを自分で判断できるようになります
旧パスへのリクエストが残っているうちに移設して、ユーザーの端末でサムネイルだけが欠けるという事故を未然に防げるようになります
画像は上がっているのに一覧の総数が古い、という中途半端な反映を、CDN を挟んだまま4か所の実応答で数分のうちに切り分けられるようになります
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-06-13
壁紙パックをアプリ審査なしで配る — リモートアセットのバージョニングと差分配信を6本で運用する設計
新しい壁紙を追加するたびにアプリを再申請していると、運用が止まります。マニフェスト方式のバージョニングと差分ダウンロード、キャッシュ無効化とロールバックを、6本並行運用の実装と転送量の実測値とともに整理しました。
アプリ開発2026-06-09
壁紙アプリのバイナリサイズを抑える — 画像をバンドルから切り離す設計判断
壁紙アプリのバイナリサイズを抑えるため、画像を同梱からリモート配信へ切り離す設計判断を実測値とともに整理します。カタログ設計、初回表示を遅くしないプレフェッチ、On-Demand Resourcesの検討、フォーマット最適化、CDN運用の注意点まで扱います。
アプリ開発2026-07-14
壁紙を長押しして、プレビューと保存メニューを出す — Rork の Expo アプリで context menu を組む
壁紙ギャラリーのカードを長押ししても何も起きない。iOS利用者はプレビュー付きのメニューを期待します。Pressableだけでは届かない理由から、zeegoでのネイティブcontext menu実装、スクロールとの競合解消、保存・共有アクション、Android向けの自前フォールバックまで、動くコードでまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →