Order of polaris / app-bridge scripts loading on the page

Found weird issue with order of polaris / app bridge scripts.

If I have (polaris first):

<script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script>
<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>

Then everything works just fine, but I see the warning in the Chrome Dev Console:

The script tag loading App Bridge should be the first script tag in the document. Loading other blocking scripts first can cause unexpected behavior.

If I switch the order to app-bridge first:

<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>
<script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script>

This breaks some features in my app, specifically s-select in the app bridge Modal:

I’m using Modal from @shopify/app-bridge-react as I need proper react logic inside the modal.

I guess this issue is not critical as “app-bridge first” message was just a warning in the console, but maybe it will be helpful to somebody to experiment with order of polaris/app-bridge in their apps.

Hey @andreas-x4149 - thanks for this, I can definitely look into this further on our end. Just a couple things that would help:

  1. Could you let me know if you’re using a Remix or CLI-scaffolded app setup, or are you manually including the polaris.js and app-bridge.js CDN script tags yourself in a custom setup?
  2. Is it just s-select that breaks inside the Modal when App Bridge loads first, or do other Polaris web components also break in that same context?

I would say that loading Polaris first is the right call temporarily if things are working correctly that way, and no other issues are popping up from what you can see, but it’s definitely not ideal.

Hope to hear from you soon!

Hi @alan_g,

Here is a bit more context…

In previous versions of my app I used Remix and React Router 7 (with react polaris components) but now I decided to migate everything to the new polaris web components and re-write my app from scratch.

Now I’m not using Remix, nor React Router, nor CLI scaffolding. I decided to go with Express (lower-level for more control of every part of logic & server optimizations). On client side, I use react 19 (No SSR).

Polaris and App Bridge I’m including like this

<script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script>
<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>

As for the modal, for this particluar modal I need responsivenes of react component, so <ui-modal> didn’t work (I have Shopify API pages loading before I can show list in <s-select> and I wanted primary button on the modal disabled until data is loaded). I couldn’t do it with <ui-modal>.

As for the <s-modal> I found some alignment issue compared to <ui-modal>. <s-modal> is not properly centered on the screen (it looks shifted down about 40 pixels or. so). Here I have a post about it: https://community.shopify.dev/t/weird-positioning-of-s-modal-compared-to-old-ui-modal-on-screen/32791

So I went with <Modal> from @shopify/app-bridge-react, so I have proper react integration.

It’s is this component that react badly on loading app-bridge script before the polaris on the page.

I just double checked, everything else functioning correctly when I load app-bridge before the polaris. So it’s only the <Modal> from @shopify/app-bridge-react that reacts badly to it.

I’m not sure if @shopify/app-bridge-react is still a priority for Shopify, or if it soon will be deprecated like polaris react components. So I also wonder, if this will be deprecated, how to create proper responsive / active functionality inside the <s-modal> modals with react.

Thank you!

Hey @andreas-x4149 - thanks for all the extra context here, really appreciated. I have some confirmation for you in terms of what you’re seeing.

On the script loading order, what we’re seeing there is a web component registration timing issue. When app-bridge.js loads before polaris.js, the Polaris web components (like s-select) haven’t been registered as custom elements yet. So when the <Modal> from @shopify/app-bridge-react tries to render them in the admin context, they just show up as unknown HTML elements. Loading polaris.js first makes sure all the s- components are registered before anything tries to use them, which is why things work in that order. I know the console warning isn’t ideal, but for now loading Polaris first is the right call, and I’m going to flag this internally though just to make sure we can give you and other folks in the dev community some concrete guidance.

When it comes to @shopify/app-bridge-react, it hasn’t been officially deprecated. The <Modal> component is still documented and supported, but you are right that the general direction is toward Polaris web components (the s- prefix components). We do consider the React components as being in “legacy mode”, but there’s no immediate deprecation timeline for @shopify/app-bridge-react . Since we’re moving toward the CDN as being our main componentization framework, I could see it just being a conflict between the two methods.

For reactive functionality inside <s-modal> with React, the <s-modal> uses a slot-based pattern where your child content gets projected in. Since web components are just standard HTML elements, React can render into them the same way it renders into a div. That said, you should be able to use React state (useState, useEffect, etc.) in components that render inside the <s-modal> slot, and React should handle the re-renders as normal.

I also saw your other thread on the <s-modal> positioning issue (thanks for sharing!). I’m going to look into that on our end as well and loop back with you there in that thread.

Let me know if I can clarify anything on our end here!

@alan_g, thank you for the detailed information!

So it seems I will wait for the <s-modal> fix, and then migrate the final part from the semi-legacy react app bridge package fully to Polaris Web Components & App Bridge. But for now, I just keep my code as it is…

Hey @andreas-x4149 - sounds good, that makes sense for now. Just wanted to let you know I’m looking into the <s-modal> positioning issue you flagged in that other thread now, so I’ll follow up with you there.