【shopify】remixテンプレートでliquidを返す方法
追記
以下のissueにて、App proxyに関して議論されています。
そちらに、以下のようにすることで認証および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-Type
をapplication/liquid
にすると、ストアからリクエストされた際に「外部URLにリダイレクトする」のではなくて、「レスポンスをストアに直接埋め込む」ことができます。
一見すればすぐに実現できそうなことですが、意外とハマりポイントがあったのでメモ代わりに残します。
(remix
の環境構築の際にはshopify/app 3.50.2
を使用しました。)
※ まだremix経験が浅いため、より良い解決策をご存知の方がいらっしゃいましたらご教授いただきたいです。
結論
例えば app/routes/proxy.tsx
app/routes/proxy.ts
にて、GETリクエストが来た時にliquid
を返したい場合は、proxy.tsx
にて以下のようにheaders
をexport
してあげて、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