How to fix navigator / window / document is undefined in Nuxt
This is the solution to fix:
navigator is undefined
window is undefined
document is not defined
Here is an example on how you should wrap your logic JS code
<script>
import { jsPlumb } from 'jsplumb' // client-side library only, no SSR support
export default {
mounted() {
if (process.client) {
// your JS code here like >> jsPlumb.ready(function () {})
}
},
}
</script>
As shown here: https://nuxtjs.org/docs/2.x/internals-glossary/context
PS: mounted
+ process.client
are kinda redundant because mounted
only runs on the client.
Also, wrapping your component into <client-only>
if you want it to be only client side rendered is also a good idea.
<template>
<div>
<p>this will be rendered on both: server + client</p>
<client-only>
<p>this one will only be rendered on client</p>
</client-only>
<div>
</template>
The documentation for this one is here: https://nuxtjs.org/docs/2.x/features/nuxt-components/#the-client-only-component
PS: beware because this client-only
tag will only skip the rendering, not the execution, as explained here.
Some packages do not support SSR when you import them, for that you could either:
- use a condition with a dynamic import (if the library is meant to be used later on)
- directly like this (if you want to load a component like
vue-editor
)
export default {
components: {
[process.client && 'VueEditor']: () => import('vue2-editor'),
}
}
“window is not defined” in Nuxt.js
UPDATED AUGUST 2021
The Window is not defined error results from nodejs server side scripts not recognising the window object which is native to browsers only.
As of nuxt v2.4 you don't need to add the process.client
or process.browser
object.
Typically your nuxt plugin directory is structured as below:
~/plugins/myplugin.js
import Vue from 'vue';
// your imported custom plugin or in this scenario the 'vue-session' plugin
import VueSession from 'vue-session';
Vue.use(VueSession);
And then in your nuxt.config.js
you can now add plugins to your project using the two methods below:
METHOD 1:
Add the mode property with the value 'client' to your plugin
plugins: [
{ src: '~/plugins/myplugin.js', mode: 'client' }
]
METHOD 2: (Simpler in my opinion)
Rename your plugin with the extension .client.js and then add it to your plugins in the nuxt.config.js plugins. Nuxt 2.4.x will recognize the plugin extension as to be rendered on the server side .server.js
or the client side .client.js
depending on the extension used.
NOTE: Adding the file without either the .client.js
or .server.js
extensions will render the plugin on both the client side and the server side. Read more here.
plugins: ['~/plugins/myplugin.client.js']
navigator.mediaDevices.getUserMedia - UNDEFINED in Nuxt
Thanks to @kissun for pointing me in the right direction.
I reckon this is a recurring issue because one cannot use navigator.mediaDevices.getUserMedia
in dev mode.
I added this function in mounted
as suggested, however that did not work either.
After searching online, I discovered I had to use HTTPS in dev mode for it to ultimately work.
To do that, create your HTTPS certificate and key first, and then configure nuxt. Original, full, instructions can be found here How to run NUXT (npm run dev) with HTTPS in localhost?
To setup nuxt, add this into your server object, in your nuxt.config.js file:
import path from 'path'
import fs from 'fs'
server: {
https: {
key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
}
}
Now try using navigator.mediaDevices.getUserMedia
document is not defined in Nuxt.js
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
Update:
Since Nuxt >= 2.9.0, you have to use the <client-only>
element instead of <no-ssr>
:
<template>
<div>
<client-only placeholder="loading...">
<your-component>
</client-only>
</div>
</template>
To know more, see nuxt docs: https://nuxtjs.org/docs/2.x/features/nuxt-components#the-client-only-component
Nuxtjs document is not defined
A wrote a similar answer here but it was lacking some parts, so I feel like I can answer here too.
Your library is probably in the same state as vue2-editor, meaning that you need to load & import it only on the client. For that, you could use something like this
export default {
components: {
[process.browser && 'star-rating']: () => import('vue-star-rating'),
}
}
Nuxt.js: window is not defined apexcharts/vue-apexcharts
As explained in my linked answer (last sentence, with the direct component syntax), here is how you make a proper working setup:
<template>
<div id="chart">
<client-only>
<apexchart
type="donut"
width="380"
:options="chartOptions"
:series="series"
></apexchart>
</client-only>
</div>
</template>
<script>
export default {
name: 'Donut',
components: {
[process.browser && 'apexchart']: () => import('vue-apexcharts'),
},
data() {
return {
series: [44, 55, 41, 17, 15],
chartOptions: {
chart: {
type: 'donut',
},
responsive: [
{
breakpoint: 480,
options: {
chart: {
width: 200,
},
legend: {
position: 'bottom',
},
},
},
],
},
}
},
}
</script>
I've also removed a data
who was nesting the whole configuration, already inside of data()
. This was causing a non-match in terms of props as shown in the browser console errors.
jsPlumb integration with Nuxtjs throwing the error document is not defined
Instead of using process.client
I used the process.browser
and it worked fine for me. Please refer the link: https://stackoverflow.com/a/69822954/7584240
VueEditor document is not defined Nuxt.js
You can try to load it dynamically:
<template>
<div>
<SideBar />
<div class='content'>
<h1>Write article</h1>
<client-only>
<VueEditor
v-model='articleContent'
/>
</client-only>
<div style='margin-top: 15px'><button @click='postArticle'>Post article</button></div>
</div>
</div>
</template>
<script>
import SideBar from '../components/SideBar';
export default {
name: 'Articles',
components: {
SideBar,
VueEditor: () => process.client ? (await import("vue2-editor")).VueEditor : ""
},
data() {
return {
articleContent: null,
}
},
methods: {
postArticle() {
console.log(this.articleContent)
},
},
}
</script>
Related Topics
How to Implement Dynamic Getters/Setters in JavaScript
How to Make a JSONp Request from JavaScript Without Jquery
Request Header Field Access-Control-Allow-Headers Is Not Allowed by Access-Control-Allow-Headers
How to Reset a Form Using Jquery with .Reset() Method
Verify If a Point Is Land or Water in Google Maps
How to Convert a Currency String to a Double with JavaScript
How to Exchange Variables Between Two HTML Pages
JavaScript Marquee to Replace <Marquee> Tags
Programmatically Play Video with Sound on Safari and Mobile Chrome
Jquery - How to Select by Attribute
Why Does Jquery Only Affect the First Div Element
Why My Show Hide Button Needs Double-Click on First Time
Putting HTML Inside an Iframe (Using JavaScript)