How to resolve the Hot Module Replacement issue while testing your Vue-Meteor App on Actual Device

Vishnu Teja Bandi
Fasal Engineering
Published in
4 min readApr 16, 2021

When you are trying to run your Vue + Meteor app on a mobile platform using Cordova, if your app which is running okay in the browser is facing issues like Styles not coming up or MeteorWebApp: Asset /socket.io/ not found in the bundle, below workaround, might help you.

We at Fasal recently started using the VueJS front-end library in our meteor app. I tried running our app on mobile(Android and IOS) using Cordova. I noticed that styles for VueJs components are not coming up. This is not the case for other platforms.

I searched for it and I found out that styles for VueJs components in the Meteor are loaded through Hot Module Replacement (HMR) during development.

According to Webpack, “Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running, without a full reload. This can significantly speed up development in a few ways: Retain application state which is lost during a full reload.”

I tried running our app without HMR which can be done by running our app after setting the NO_HMR or — production flags as shown below.

$ export NO_HMR=1
$ meteor run android-device --mobile-server=http://<IPv4 of your computer>:3000
---OR----
$ meteor run --production android-device --mobile- server=http://<IPv4 of your computer>:3000

The styles for our VueJs components are now working as expected. This meant that there is something wrong with HMR. As far as we are concerned, If we want to make a mobile-based feature (eg: QR scanner) we have to rebuild for mobile every time we change something in our code, which happens a lot during development and that’s a lot of time waste.

And so, I opened our chrome dev tools to inspect the app when run on mobile and found this,

This means that the client(mobile app) is listening to “undefined” for hot module replacement. The code where the HMR server URL is assigned to the meteor client is in the package akryum:vue-component-dev-client.

Alternatively, you can see the source code by clicking the link shown alongside the log above.

vue-component-dev-client/client/dev-client.js

Since devUrl is undefined, the object __meteor_runtime_config__ does not have a property named VUE_DEV_SERVER_URL. This is only happening on mobile platforms. In the other platforms, VUE_DEV_SERVER_URL is being set by default to ( can be changed manually) -

http://<IPv4 of your computer>:<port on which your app is running + 3>

What Exactly Is Happening here?

When we run the command,

meteor run android-device --mobile- server=http://<IPv4 of your computer>:3000

meteor creates two server instances which serve at localhost:3000 and at http://<IPv4 of your computer>:3000. You can check this by going to these URLs in your browser. The mobile app will have the ROOT_URL set to http://<IPv4 of your computer>:3000. In the mobile platform client __meteor_runtime_config__ has the following value

__meteor_runtime_config__’s value on mobile platform.

As shown above, there is no property named VUE_DEV_SERVER_URL in this object. Therefore, undefined is being assigned to the devServer variable, which is the cause of our problem.

Since the mobile client has ROOT_URL set, we could use this to get HMR URL by adding 3 to its port, which will be http://<IPv4 of your computer>:3000. The following fix uses the ROOT_URL to derive the HMR URL.

Finally, the fix.

Add a folder named packages in your meteor app’s root folder and download the atmosphere package akryum:vue-component-dev-client and modify vue-component-dev-client/client/dev-client.js as shown below,

Add these 5 lines before devUrl is initialized inside Meteor.startup callback

if(Meteor.isCordova){const root = new URL(__meteor_runtime_config__.ROOT_URL)__meteor_runtime_config__.VUE_DEV_SERVER_URL    = root.protocol+'//'+root.hostname+':'+(parseInt(root.port)+3)+'/';}

Don’t forget to import url after all the imports at the beginning of the file.

const url = require('url');

I know this is a naive fix but, until this issue is patched by akryum or Cordova this works for the time being.

I created a pull request for the official repo. Check it out here.

Also read —

--

--