“document is not defined” in Nuxt.js

2020-05-27 11:07发布

问题:

I am trying to use Choices.js within a Vue component. The component compiles successfully, but then an error is triggered:

[vue-router] Failed to resolve async component default: ReferenceError: document is not defined

In the browser I see:

ReferenceError document is not defined

I think this has something to do with the SSR in Nuxt.js? I only need Choices.js to run on the client, because it's a client only aspect I guess.

nuxt.config.js

build: {
  vendor: ['choices.js']
}

AppCountrySelect.vue

<script>
import Choices from 'choices.js'

export default {
  name: 'CountrySelect',
  created () {
    console.log(this.$refs, Choices)
    const choices = new Choices(this.$refs.select)
    console.log(choices)
  }
}
</script>

In classic Vue, this would work fine, so I'm very much still getting to grips with how I can get Nuxt.js to work this way.

Any ideas at all where I'm going wrong?

Thanks.

回答1:

It's a common error when you start a Nuxt project ;-)

The Choices.js lib is available only for client-side! So Nuxt tried to renderer from server-side, but from Node.js window.document doesn't exist, then you have an error.
nb: window.document is only available from the browser renderer.

Since Nuxt 1.0.0 RC7, you can use <no-ssr> element to allow your component only for client-side.

<template>
  <div>
    <no-ssr placeholder="loading...">
      <your-component>
    </no-ssr>
  </div>
</template>

take a look at the official example here: https://github.com/nuxt/nuxt.js/blob/dev/examples/no-ssr/pages/index.vue



回答2:

The accepted answer (while correct) was too short for me to understand it and use it correctly, so I wrote a more detailed version. I was looking for a way to use plotly.js + nuxt.js, but it should be the same as the OP's problem of Choice.js + nuxt.js.

MyComponent.vue

<template>
  <div>
    <no-ssr>
      <my-chart></my-chart>
    </no-ssr>
  </div>
</template>
<script>
export default {
  components: {
    // this different (webpack) import did the trick together with <no-ssr>:
    'my-chart': () => import('@/components/MyChart.vue')
  }
}
</script>

MyChart.vue

<template>
  <div>
  </div>
</template>
<script>
import Plotly from 'plotly.js/dist/plotly'
export default {
  mounted () {
    // exists only on client:
    console.log(Plotly)
  },
  components: {
    Plotly
  }
}
</script>


回答3:

I found that now the no-ssr is replace by , i am using echart and have the same problem but now it´s working!

    <client-only>
        <chart-component></chart-component>
    </client-only>


回答4:

You need to add it as a plugin and then disable SSR for it.

As document and window are not defined on the server side.

Your nuxt.config.js should look like below

plugins: [
{ src: '~/plugins/choices.js', ssr: false }
],


回答5:

<script>
import Choices from 'choices.js'

export default {
  name: 'CountrySelect',
  created () {
    if(process.client) {
      console.log(this.$refs, Choices)
      const choices = new Choices(this.$refs.select)
      console.log(choices)
    }
  }
}
</script>

I guess this should help, nuxt will touch insides of computed after it renders on server and window will be defined