📚

【shopify】remixテンプレートでliquidを返す方法

2023/11/05に公開

追記

以下のissueにて、App proxyに関して議論されています。

https://github.com/Shopify/shopify-app-template-remix/issues/295#issuecomment-1714518931

そちらに、以下のようにすることで認証およびliquidを返すことを行うことができると記載があることを確認しました。

こちらの記述方法にて、動作することも確認済みです。

tsxではなくtsなので注意(最初ミスってて、全然動きませんでした)

// app/routes/**\/.ts
import {authenticate} from '~/shopify.server';

export async function loader({request}) {
  const {liquid} = authenticate.public.appProxy(request);

  return liquid('Hello {{shop.name}}');
}

はじめに

shopifyのアプリ開発でApp Proxyを使うとき、レスポンスのContent-Typeapplication/liquidにすると、ストアからリクエストされた際に「外部URLにリダイレクトする」のではなくて、「レスポンスをストアに直接埋め込む」ことができます。

一見すればすぐに実現できそうなことですが、意外とハマりポイントがあったのでメモ代わりに残します。

remixの環境構築の際にはshopify/app 3.50.2を使用しました。)

※ まだremix経験が浅いため、より良い解決策をご存知の方がいらっしゃいましたらご教授いただきたいです。

結論

例えば app/routes/proxy.tsx app/routes/proxy.ts にて、GETリクエストが来た時にliquidを返したい場合は、proxy.tsxにて以下のようにheadersexportしてあげて、 proxy.tsの内容を以下のようにしてあげればいいです

import type { LoaderFunctionArgs } from "@remix-run/node";
import { authenticate } from "../shopify.server";

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const { liquid } = await authenticate.public.appProxy(request);

  return liquid("Hello {{shop.name}}");
}

app/entry.serever.tsxを以下のように編集してあげれば動きます。 以下の修正は不要。

❯ git diff app/entry.server.tsx
diff --git a/app/entry.server.tsx b/app/entry.server.tsx
index 0df007c..e27645a 100644
--- a/app/entry.server.tsx
+++ b/app/entry.server.tsx
@@ -10,6 +10,11 @@ import { addDocumentResponseHeaders } from "./shopify.server";
 
 const ABORT_DELAY = 5000;
 
+function isContentTypeLiquid(headers: Headers) {
+  const contentType = headers.get("Content-Type");
+  return contentType?.includes("application/liquid");
+}
+
 export default async function handleRequest(
   request: Request,
   responseStatusCode: number,
@@ -33,7 +38,11 @@ export default async function handleRequest(
           const body = new PassThrough();
           const stream = createReadableStreamFromReadable(body);
 
-          responseHeaders.set("Content-Type", "text/html");
+          if (isContentTypeLiquid(responseHeaders)) {
+            responseHeaders.set("Content-Type", "application/liquid; charset=utf-8");
+          } else {
+            responseHeaders.set("Content-Type", "text/html");
+          }
           resolve(
             new Response(stream, {
               headers: responseHeaders,

ハマりポイント

app/entry.server.tsxを編集するところがミソ。

こいつは、app/routes/以下の処理よりも後に実行されるので、ここを編集しないと必ずtext/htmlで上書きされてしまう。

もしかしたら、こいつを動かさないように記述する方法もあるんだろうけど、自分では見つけられなかったので一旦これで解決とした。

より良い解決策があったので内容を修正。

ハマりポイントとしては、tsxを使うのではなくてtsを使うところです。

Discussion