Reputation: 9875
Background
I am currently working with Nuxt and need to render some C3 charts in a vue component. C3 is calling Window
in the library so it throws an error on the C3 library import statement.
window is not defined
I know this is happening because it is server side rendering and it needs the browser to access window
. I also know I need to tell Nuxt
to allow this specific component, or part of the component to be rendered once it is in the browser.
I know C3 is built on top of D3 so I figured I would try to get that to load as well. I read that this is how you handle non server side rendered libraries.
Example Code
nuxt.config.js
plugins: [
{ src: '~plugins/d3', ssr: false },
{ src: '~plugins/c3', ssr: false },
],
build: {
vendor: ['d3', 'c3'],
},
/plugins/d3.js
import * as d3 from 'd3';
export default d3;
/plugins/c3.js
import c3 from 'c3';
export default c3;
Once I add these configurations I then move to the component I want to use them in,
import * as d3 from 'd3';
import c3 from 'c3';
import 'c3/c3.css';
This allows D3 to work. But when I import C3, it still throws the same error. So, I read that I should try this,
let c3 = null;
if (process.browser) {
c3 = require('c3');
}
That still does not work and C3 still throws an error. The new error is,
c3 is not defined.
I am rendering the C3 Charts in mount
mounted() {
const chart = c3.generate({
bindto: '#result-chart',
data: {
columns: [['data1', 30], ['data2', 120]],
type: 'pie',
},
});
},
Question
As I understand it now the if statement is working and allowing the page to continue rendering while skipping over the import. But now that it has skipped over it, how do I actually render the graph once the page is available to the browser? With my current implementation C3 is never in scope.
One more error I saw at one point was generator is undefined. I could not figure out where that was coming from, but just in case that helps.
Upvotes: 6
Views: 1601
Reputation: 849
From your description you import d3 and c3 twice, by using nuxt plugin and in your component. I think you could do it in the following way:
/plugins/chart.js
import * as d3 from 'd3';
import c3 from 'c3';
export default (ctx, inject) => {
inject("d3", d3);
inject("c3", c3);
};
/nuxt.config.js
plugins: [
{ src: "~/plugins/chart", ssr: false }
]
inject
method will insert d3 and c3 object into nuxt context, so that you can call them using this.$d3
and this.$c3
, for instance:
mounted() {
const chart = this.$c3.generate({
bindto: '#result-chart',
data: {
columns: [['data1', 30], ['data2', 120]],
type: 'pie',
},
});
},
Upvotes: 1