Theme app extension - JS script appended to DOM element ends with "Maximum call stack size exceeded"

lpici
Shopify Partner
5 0 0

Hello.

 

I search a way to embed my Vue application in Shopify theme. This Vue app is distributed as npm ready package, it executes 100% in the browser, no external hosting is used.

I managed to append this app to my Shopify theme by extension which adds app block to a static page.

I make build of my Vue app, then this build is copied to /assets in my Shopify extension tree, then I call:

<script src="{{ 'vue-middleware.js' | asset_url }}" defer></script>

within my .liquid file. This vue-middleware.js file has direct calls to my Vue app. So the flow is:

Browser page (Shopify page) -> Shopify extension -> vue-middleware.js -> Vue app.

 

The problem is, this embedded Vue app starts but soon halts execution with error "RangeError: Maximum call stack size exceeded".

I narrowed the problem as good as I could:

- error is thrown when Shopify extension calls method in my Vue app, which appends Vue app to specific DOM element,

- this Vue app do not throw this RangeError (and starts without problems) when embedded within standard HTML static page / standard vanilla JS project.

 

The Vue app also changes URL, by appending anchor link to current URL. I suspect this could brake something within Shopify.

Another thing - this error about call stack... Does Shopify manage page DOM internally? You know, my Vue app modifies DOM, Shopify registers this and modify DOM, then my app sees those changes and once more modify DOM and BOOM, infinite loop.

 

Is there something specific to Shopify about which I don't know?

 

Replies 5 (5)

Rishihuptech
Shopify Partner
601 108 121

Hello @lpici 

This issue arises when multiple Shopify section blocks are added. When your app is included in multiple block sections, Vue.js may be initialized multiple times, potentially causing this error. To resolve this, you can follow the below steps
1. add the below code to your liquid file

 

 <script>
    if(!window.vueApp){
    window.vueApp = {}
     }
    window.vueApp.Jsfile = "{{ 'vue-middleware.js' | asset_url }}"; 
  </script>
  <script src="{{ 'renderApp.js' | asset_url }}" defer></script>

2. create renderApp.js in your asset folder and add the code below.

var checkScriptAvailable = document.querySelector("script.vue-app")// you can add your unique class name
if (!checkScriptAvailable) {
    const script = document.createElement('script');
    script.src=window.vueApp.Jsfile;
    script.className = "vue-app"
    script.defer = true
    document.body.appendChild(script);
}

renderApp.js is responsible for downloading vue js code only once time. if this solution does not work then Please let me know if I can be of any assistance

 

If the solution presented meets your needs and addresses your query effectively, I encourage you to accept it as the chosen answer. This will acknowledge the support you received and aid fellow community members in identifying reliable and effective solutions for their similar concerns.
Thank you.

 

If you found this response helpful, please do like and accept the solution. Thanks!
Need support with Customizing your Shopify store?
Feel free to contact me at info@huptechweb.com or Visit our website Huptech Web.
Instant Shortcode Builder: Integrate customizable UI features anywhere in your store - No coding knowledge required
lpici
Shopify Partner
5 0 0

My 'test' page has header, footer and template which only has one block coming from extension, so no multiple extension blocks on one page.

 

Good point with "Vue may be initialized multiple times". The code you provided did not resolve my problem, but I will look deeper into that topic.

I see my Vue app creates new instance of Vue, exactly in the problematic method where Vue app appends to a DOM element.

 

Has Shopify some kind of "global" Vue object which I can use to $mount my app?

lpici
Shopify Partner
5 0 0

Update - I managed to run my Vue App from extension, but there is one quirk - I used development build of my Vue app.

 

Any idea what makes the difference which holds back Shopify from executing production build of Vue app? Vue app uses Webpack to create appropriate build (dev / prod).

lpici
Shopify Partner
5 0 0

Bump.

lpici
Shopify Partner
5 0 0

Update: I narrowed the problem to the terser-webpack-plugin. When not used, everything is fine. When used, stack size is exceeded. I tried to add:

 

new TerserPlugin({
    terserOptions: {
        compress: {
            sequences: 2
        }
    },
}),

 

instead of default 200 sequences, file is slightly bigger but error still occurs. I use this plugin in latest version (5.3.10).

 

Can I somehow tune-up this plugin to satisfy Shopify limitations?

 

I'll try other minifiers as a workaround.