Shopify / shopify-app-template-remix

352 stars 149 forks source link

Defer not working inside iframe #694

Open alexanderhupfer opened 6 months ago

alexanderhupfer commented 6 months ago

Issue summary

Before opening this issue, I have:

defer is not working inside the iFrame / embedded app. However it works outside the iFrame,

Expected behavior

Page should render immediately, then the deferre content should appear once the promise has resoled.

Actual behavior

Page does not render until promise has resolved when inside iFrame

Steps to reproduce the problem

import { defer } from "@remix-run/node";
import { Suspense } from "react";
import { Await, useLoaderData } from "@remix-run/react";

export const loader = async ({ request }) => {
  async function simulateLongRunningTask() {
    console.log('Task started...');
    const result = await new Promise(resolve => {
      setTimeout(() => {
        resolve(null);
      }, 3000);
    });
    console.log('Task completed after 3 second.');
    return result;
  }

  return defer({
    message: "Hello from a loader function!",
    result: simulateLongRunningTask(),
  });
};

export default function App() {
  const { message, result } = useLoaderData();

  return (
    <div className="index">
      <div className="content">
        <Suspense fallback={<div>Loading...</div>}>
          <Await resolve={result}>{console.log(result)}Deferred Task Done</Await>
        </Suspense>
        <h1>{message}</h1>
      </div>
    </div>
  );
}
[remix-serve] http://localhost:57256 (http://192.168.178.100:57256)
console.js:38
Task started...
console.js:38
[shopify-app/INFO] Authenticating admin request
console.js:38
browser request
console.js:38
Promise {[[PromiseState]]: 'pending', [[PromiseResult]]: undefined, _tracked: <accessor>, Symbol(async_id_symbol): 456, Symbol(trigger_async_id_symbol): 453, …}
console.js:38
Task completed after 3 second.

The browser log reports no hydration errors

Please not that there is a related issue to cloudflared due to which defer won't work with cloudflare tunnels: https://github.com/cloudflare/cloudflared/issues/1095

Hence I used ngrok for testing, for which defer works as expected, just not inside the admin iFrame.

paulomarg commented 6 months ago

Hey, thanks for raising this. We believe this is a consequence of how cloudflare tunnels (which the CLI uses by default for development) work. They seem to buffer the deferred response and return a single chunk, which seems to "break" the Suspense component's expected behaviour.

We've added some documentation to the template to help work around this issue.

Please let us know if that solves it!

alexanderhupfer commented 6 months ago

Hi thanks for looking into this - I'm aware of the cloudflare issue as stated at the bottom of my issue report. However the issues does also occur using ngrok but seems clearly related to the iFrame since it is working fine outside the iFrame.

paulomarg commented 6 months ago

Oh sorry, I failed to see you mentioned that. I'll start tracking this issue and we'll look into it.

FWIW I tried running your code and I saw the symptom you reported, but I also got a hydration error around the use of Suspense. I haven't dug into it yet, but could that be related to the issue?

alexanderhupfer commented 6 months ago

Hi, thank you for looking into this. As I mentioned in my report I did not observe the hydration error. The issue I linked mentioned the hydration error and related it to the then current react version as the error was resolved by upgrading to the now current react version.

alexanderhupfer commented 5 months ago

@paulomarg Is there anything else you need from my side? I see the issue marked as "waiting for response"

paulomarg commented 5 months ago

Hey, sorry for the delayed response. I'll remove that label. I've added it to our backlog, so no other action needed now!

alexanderhupfer commented 5 months ago

@paulomarg Is there any ETA on this? I'm having a couple of feature on the roadmap that rely on this

paulomarg commented 5 months ago

We have some other things that will take precedence here so I can't give any dates, but this is in our immediate list of items to investigate!

paulomarg commented 5 months ago

Hi, we've investigated this issue and it doesn't seem to be anything that the app itself is doing - I was able to reproduce your scenario with the code you provided (thanks!), and if I load that within an iframe outside of the Shopify admin, deferring works. That points to there being an issue in the admin itself and how it's loading the app.

I've forwarded this to the team that manages that part of the code, and they're going to look into it. However, this is probably not an easy fix, so it might take a while to resolve. In the meantime, I would suggest not using deferred requests in your app so it doesn't affect your performance metrics.

I'll keep you posted if I hear anything back from them! Thanks again for raising this issue.

samueldurantes commented 4 days ago

@paulomarg Any feedback about this question?