jl0w
jl0w

Reputation: 181

Loading D3 with Nuxt/Vue

I am trying to implement D3 in an app I am building with Nuxt. I have successfully imported it into a view in the <script> section with import * as d3 from 'd3' however because the app is being rendered server-side D3's functionality doesn't work (i.e. d3.select(...)) due to the lack of browser. In the Nuxt plugin documentation it suggests a pattern for client-only external plugins:

module.exports = {
  plugins: [
    { src: '~plugins/vue-notifications', ssr: false }
  ]
}

I attempted to implement the pattern in the nuxt.config.js of my project:

module.exports = {
  head: {
    title: 'My Demo App',
    meta: [...],
    link: [...]
  },

  loading: {...},

  plugins: [
     { src: '~node_modules/d3/build/d3.js', ssr: false}
  ]
}

However D3 throws a ReferenceError while looking for document and Nuxt throws a SyntaxError in the console pointing to something in the plugins field of nuxt.config.js.

For reference, demo.vue:

<template>
  <div class="demo-container"></div>
</template>

<script>
  import * as d3 from 'd3';
  d3.select('.demo-container');
</script>

Would someone be able to point to what I'm doing wrong?

Upvotes: 14

Views: 7947

Answers (3)

J3soon
J3soon

Reputation: 3153

Here's a simple step-by-step tutorial:

  1. Create a new NuxtJS project (Skip this step if you have an existing project)

    npm init nuxt-app nuxtjs-d3js-example
    
  2. Install D3JS

    npm install d3
    npm install @types/d3 --save-dev
    
  3. Import D3JS and add a target

    HTML:

    <p id="d3-target"></p>
    

    JavaScript:

    import * as d3 from 'd3'
    export default {
      name: 'NuxtTutorial',
      mounted: function() {
        d3.select("#d3-target").text("This text is manipulated by d3.js")
      },
    }
    
  4. Fix ES Module error (mentioned by @agm1984)

    Error:

    require() of ES Module /home/johnson/projects/nuxtjs-d3js-example/nuxtjs-d3js-example/node_modules/d3/src/index.js from /home/johnson/projects/nuxtjs-d3js-example/nuxtjs-d3js-example/node_modules/vue-server-renderer/build.dev.js not supported. Instead change the require of index.js in /home/johnson/projects/nuxtjs-d3js-example/nuxtjs-d3js-example/node_modules/vue-server-renderer/build.dev.js to a dynamic import() which is available in all CommonJS modules. 
    

    nuxt.config.js:

    build: {
      standalone: true,
    }
    

A minimal project example can be found at: https://github.com/j3soon/nuxtjs-d3js-example, with each step detailed in the Git commit history.

Upvotes: 1

agm1984
agm1984

Reputation: 17132

I was getting an error:

Must use import to load ES Module: .../node_modules/d3/src/index.js require() of ES modules is not supported. require() of .../node_modules/d3/src/index.js from .../node_modules/vue-server-renderer/build.dev.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules. Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from .../node_modules/d3/package.json.

I solved it by reading this: https://github.com/nuxt/nuxt.js/issues/9223

which indicates you can add this to your nuxt.config.js file:

  build: {
    standalone: true,
  }

This allowed the d3 import to work.

import * as d3 from "d3";

Upvotes: 5

ba_ul
ba_ul

Reputation: 2209

For anyone coming to this page looking for a solution, these suggestions from piyushchauhan2011 here on GitHub sent me in the right direction.

All I needed to do:

  • import d3 in my single-file component, and then
  • do any DOM manipulation with d3 only within mounted()

Before all this, I had to of course add d3 to my project with yarn add d3 (or npm install d3).

[Edit: removed link that no longer works. It wasn't that relevant anyway.]

Upvotes: 13

Related Questions