weizhenye/vue-highcharts

Map/Stock not loading when packaged through webpack

thedamon opened this issue · 8 comments

I'm trying to initialize a highmap inside a ".vue" component being packaged by Webpack. I'm following the procedure to use Vue.use(VueHighcharts, { Highcharts }); with a Highcharts loaded from highmaps but in my template <highmaps> is not being registered as a vue component.. <highcharts> and <highcharts-renderer> are, though.

My component looks like this:
https://gist.github.com/thedamon/ed9dc91e65dfb014bc99206e46b0738d

As you import Highcharts from 'highcharts/highmaps', which is already include highmaps, you don't need load map from 'highcharts/modules/map' again.

import Vue from 'vue';
import VueHighcharts from 'vue-highcharts';
import Highcharts from 'highcharts/highmaps';

Vue.use(VueHighcharts, { Highcharts });

Live example: https://codesandbox.io/s/o48pkv67r9

Thanks for the example. I have exactly that code now except for the name of my main app.. but for me the component isn't working. I was using it as a component within another component, but re did it to look like the codesandbox. Really perplexed about what the difference might be

Maybe you can try to import highcharts and vue-highcharts in your entry file and Vue.use it.

It appears that highmaps won't work if it's being imported dynamically. My import was in this listener

document.addEventListener('DOMContentLoaded', function(event) {
  if (document.getElementById('fundData')) {
    import(/* webpackChunkName: "chartComponents" */ './chartComponentsIndex');
  }
});

And it failed silently. Can you think of why this would be and if there is a way around it? I want to confine the heavy highcharts related code to being loaded only when it's used.

Once I did as you suggested it started initializing highmaps, but my piechart and barchart components started throwing an error The requested series type does not exist.

I'm not clear about what is in ./fundDataIndex and which part of your code is imported dynamically. But if you want to load highmaps async, you should also load vue-highcharts async and then Vue.use it.

Example: https://codesandbox.io/s/xp7m85ypmo

The way I'm doing it is a little different with a dynamic import and then loading the data for the components via a service. I put the structure up on codesandbox, though it won't function without the endpoint and I'm not sure if codesandbox supports the dynamic webpack imports (it requires a babel plugin to support the import() syntax)

https://codesandbox.io/s/lx1yqq9nz9

If you see something that makes sense in keeping those from working.. the other types of charts are functioning exactly as expected. The loading process is a bit complex so I'm not sure how to mirror it online easily, but I'll try and work up a complete example maybe using require.ensure if nothing sticks out

OK, let me try to explain:

In chartRenderer.vue, you import pieChart.vue and then mapChart.vue, so we jump into pieChart.vue, you call Vue.use(VueHighcharts) without passing in a Highcharts object, vue-highcharts will import Highcharts from 'highcharts' by default, which point to highcharts/highcharts.js file. Then in mapChart.vue, you try to import Highcharts from 'highcharts/highmaps.js', a different file, means the two Highcharts object don't have same reference. But it's not the point, you then call Vue.use(VueHighcharts, { Highcharts }) again, Vue will automatically prevents you from using the same plugin more than once, so the Highcharts object inside vue-highcharts is still highcharts/highcharts.js.

To fix this problem, the key point is make sure all Highcharts have same reference. So always import Highcharts from 'highcharts' and use add-ons by loading corresponding modules.

// pieChart.vue
import Vue from 'vue';
import VueHighcharts from 'vue-highcharts';
import Highcharts from 'highcharts';

Vue.use(VueHighcharts, { Highcharts });
// mapChart.vue
import Vue from 'vue';
import VueHighcharts from 'vue-highcharts';
import Highcharts from 'highcharts';
import loadMap from 'highcharts/modules/map';

loadMap(Highcharts);

// maybe we don't want to figure out which fooChart.vue is loaded first,
// just write it and Vue will handle it.
Vue.use(VueHighcharts, { Highcharts });

I'm closing this issue for it is not about vue-highcharts itself, and my comment above should figure out the reason.