Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defer not working inside iframe #694

Open
1 task
alexanderhupfer opened this issue Apr 29, 2024 · 14 comments
Open
1 task

Defer not working inside iframe #694

alexanderhupfer opened this issue Apr 29, 2024 · 14 comments

Comments

@alexanderhupfer
Copy link

alexanderhupfer commented Apr 29, 2024

Issue summary

Before opening this issue, I have:

  • [ x ] Upgraded to the latest version of the @shopify packages
    • Affected package and version:
    "@shopify/app": "3.58.2",
    "@shopify/app-bridge-react": "^4.1.3",
    "@shopify/app-bridge-types": "^0.0.13",
    "@shopify/cli": "3.59.1",
    "@shopify/polaris": "^13.2.0",
    "@shopify/shopify-api": "^10.0.0",
    "@shopify/shopify-app-remix": "^2.8.2",
    "@shopify/shopify-app-session-storage-prisma": "^4.0.5"
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  • Node version: v21.7.3 - Operating system: MacOS
  • Set { logger: { level: LogSeverity.Debug } } in my configuration
  • [ x ] Found a reliable way to reproduce the problem that indicates it's a problem with the package
  • [ x ] Looked for similar issues in this repository
  • [ x ] Checked that this isn't an issue with a Shopify API

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: cloudflare/cloudflared#1095

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

@paulomarg
Copy link
Contributor

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
Copy link
Author

alexanderhupfer commented May 1, 2024

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
Copy link
Contributor

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
Copy link
Author

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
Copy link
Author

alexanderhupfer commented May 13, 2024

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

@paulomarg
Copy link
Contributor

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
Copy link
Author

alexanderhupfer commented May 19, 2024

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

@paulomarg
Copy link
Contributor

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
Copy link
Contributor

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
Copy link

@paulomarg Any feedback about this question?

@alexanderhupfer
Copy link
Author

I can confirm this was fixed. Using it in production - works perfectly

@minhduc17801
Copy link

@alexanderhupfer Do I need to update any packages? My app still doesn't work as expected, defer does work but it seems like the client always waits for everything to load before starting to render, so I never see the fallback being rendered.

@samueldurantes
Copy link

@alexanderhupfer Do I need to update any packages? My app still doesn't work as expected, defer does work but it seems like the client always waits for everything to load before starting to render, so I never see the fallback being rendered.

Same problem here.

@alexanderhupfer
Copy link
Author

I just checked, still works. This are my package versions. I'm not using single-fetch on remix side

    "@remix-run/dev": "^2.12.0",
    "@remix-run/node": "^2.12.0",
    "@remix-run/react": "^2.12.0",
    "@remix-run/serve": "^2.12.0",
    "@sentry/remix": "^8.30.0",
    "@shopify/app": "^3.58.2",
    "@shopify/app-bridge-react": "^4.1.5",
    "@shopify/react-i18n": "^7.13.1",
    "@shopify/shopify-api": "^11.4.0",
    "@shopify/shopify-app-remix": "^3.3.0",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants