Error initializing App Bridge with React

kyle_truong
Shopify Partner
59 6 16

I just started learning about the AppBridge and wanted to give it a shot while developing the admin portion of my app using React and Polaris. Using create-react-app, I spin up my react app and I'm met with this error: 

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://example-test-app.myshopify.com') does not match the recipient window's origin ('http://localhost:3000').

The only way I've found to bypass this is to build my react app after every change and have it served as static files through my node server, but builds this way take ~20 seconds compared to the ~1 second needed without making a full build. Is there any way around this so I can maintain create-react-app's faster hot-module reloading while making changes to files?

const appBridgeConfig = {
    apiKey: process.env.REACT_APP_SHOPIFY_API_KEY as string,
    shopOrigin: shopDomainName,
  };

  return (
    <AppProvider i18n={{}}>
      <Provider config={appBridgeConfig}>
        <Page>
          <div className="animated fadeIn">
            <Dashboard />
          </div>
        </Page>
      </Provider>
    </AppProvider>
  );
};

// Dashboard.tsx
import { Context, Loading } from '@shopify/app-bridge-react';

export const Dashboard: React.SFC<DashboardProps> = () => {
  return (
    <Context.Consumer>
      {app => {
        console.log('app: ', app);
        console.log(
          'appstate: ',
          app?.getState().then(res => {
            console.log('res: ', res);
          }),
        );
        return (
          <div>
            <Loading />
            <div>testing</div>
          </div>
        );
      }}
    </Context.Consumer>
  );
};





Replies 8 (8)

kyle_truong
Shopify Partner
59 6 16

hannachen
Shopify Staff
54 8 17

Hi Kyle,

 

Thanks for your interest in using App Bridge React. Based on the error message, it sounds like you encountered a security restriction for embedded apps. The hostname of your app that was entered in the partner's dashboard (https://example-test-app.myshopify.com) must match that of your local environment (http://localhost:3000).

 

However, your localhost is probably not accessible online. (or did I miss a step where the static files are hosting online?) I would recommend using a tunnelling software (such as ngrok) to create a SSL tunnel to your localhost server. Your ngrok URL then can be entered as your app's URL in the partner's dash board. This way you can take advantage of create-react-app's hot module reloading for faster app development.

 

Hope this helps!

Hanna | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

kyle_truong
Shopify Partner
59 6 16

Hi Hanna,

Thanks for your response, I think that makes things a lot clearer, but could you please validate whether I'm thinking about this properly now:

I currently have ngrok proxying requests to my server, and it's my server that would normally serve my static files. In this case though, I don't want my server to handle static files because it requires a build after every change. I'm running the react portion of the app alongside my server but separately (just for development), which is where create-react-app and its hot module reloading come into play. Without the App Bridge or any authentication, I'm able to develop like this and have my frontend make API requests to my server, but if I'm reading into this right then it just means this is a security restriction and this is not the intended workflow I should be using.

Am I thinking in the right direction?

hannachen
Shopify Staff
54 8 17

My apologies, I might have mis-identified the error upon a closer inspection of the error message. Your setup sounds about right, the mismatch appears to be with the shop origin. I'm hoping to better understand the setup of your app setup:

 

From what I can understand, you have a node server to handle API requests (back-end), and static files (client-side) that makes calls to the back end, is that correct? Could you kindly share your app url that's set in your partner's dashboard?

 

Also, what does the scenario look like when developing without App Bridge and authentication? Do you mean developing your app outside of Shopify admin/embedded view?

Hanna | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

kyle_truong
Shopify Partner
59 6 16

No worries, glad to read that my setup looks normal. 

Yup, my node server handles back-end duties like API requests and authentication but it's also intended to serve static files that render what's seen in the merchant's Shopify Admin and make calls back to the server. My App url is https://ktruong008.ngrok.io/.

Developing without App Bridge and authentication is as you described: outside the Shopify admin/embedded view. Normally, I'd run through the complete Shopify flow once to install the app, and then I'd let my server just sit there as I develop my frontend. I find it handy because of how fast and convenient create-react-app is while developing. It works as long as all I need to do is develop components and talk to my server/db. Anything related to Shopify, which now seems to includes App Bridge, I'd have to make a frontend build after every change instead of relying on the webpack dev-server provided by create-react-app. It's not a huge problem but I figured I'd ask around just in case.

hannachen
Shopify Staff
54 8 17

Thanks for the additional information, I think I have a better understanding of your project setup now. The workflow for development outside Shopify admin doesn't seem ideal for an embedded app, as I imagine you'd need to test App Bridge functionalities. Let's see if we can figure out a workflow that will allow you to develop locally in the admin! I have a few follow-up questions:

 

- is the back-end node server and create-react-app server for client-side running on two separate node instances?

- does your client-side source live with back-end source under the same project?

- how is the client side js loaded/included in your setup?

- have you looked into using a framework like next.js?

Hanna | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

kyle_truong
Shopify Partner
59 6 16

Thanks for looking into this with me, I hope we can continue working towards a better process .

- is the back-end node server and create-react-app server for client-side running on two separate node instances?

I'm assuming you mean this is for development only, in which case the answer is yes. In one terminal I have node running, and in another I have create-react-app running. 

- does your client-side source live with back-end source under the same project?

Yes. I wanted them separate when I began looking into developing Shopify apps but I found very little information on this subject, and the tutorials seemed to assume a monolith configuration, or at least not account for different services. I still tried at a mini-microservice-like architecture where I'd have a cluster running nginx and routing requests to the main api server which would then redirect to a CDN or another server serving the static files that render on the Shopify Admin but I found this unnecessarily complex as it added more issues related to CORS, sameSite cookies, and deployment. I still keep my script tags in CDNs though. 

- how is the client side js loaded/included in your setup?

I literally just plopped a CRA output into my project under a folder named "frontend". Development-wise, it's as if they were completely different code-bases, there's no code shared between them. When it's time to build, to test an integration with Shopify in the Admin or pushing to prod, my npm script builds my frontend as any other CRA app and moves the build up into my backend code where it can be mounted and served as static files. In development, I would skip the build step and just run my frontend in another terminal and leverage CRA's built-in hot module reloading. 

- have you looked into using a framework like next.js?

Yes, but I don't like how abstracted it is. I've always enjoyed how simple CRA has been for developing React apps and my backend requires only node, nodemon, and a tsconfig. I find it simpler to glue two simple parts together than to manage something like Next.js. I'm sure Next.js is incredible but it has so many optimizations and configurations that I don't understand or necessarily even need to the point that I wouldn't feel confident in my abilities in debug if something went wrong.  

kyle_truong
Shopify Partner
59 6 16

For anyone else who encounters this problem, my current workaround is to use `npm-watch` 

https://github.com/M-Zuber/npm-watch

I have 1 terminal running ngrok, 1 running my server, and 1 running `npm-watch`, which will watch for changes in my frontend and re-build afterwards. It's not ideal but it's not too bad either. I've heard of some builds taking half an hour or more, so I'm glad mine only takes half a minute at most.