Nuxt.js: window is not defined

Created on 21 Mar 2017  路  8Comments  路  Source: nuxt/nuxt.js

I feel there must be more to this error than what is described in the docs. I have spent a long time trying to get various scripts to work in Nuxt, and each time have failed to get passed the window is not defined error, despite adding:

if (process.BROWSER_BUILD) {
  require('external_library')
}

I won't list all the scripts I tried here, but I'll give one example: Vue.Isotope

nuxt.config.js

build: {
  vendor: [ 'vueisotope'],
}

.vue file

if (process.BROWSER_BUILD) {
  require('vueisotope')
}
import isotope from 'vueisotope'
export default {
  components: {
    isotope
  }
}

This question is available on Nuxt.js community (#c355)
help-wanted

Most helpful comment

Thank you @ausir0726 for your help

In the upcoming release, we are adding an ssroption in the plugins key of the nuxt.config.js, so you will be able to integrate Vue.Isotope this way @smth:

nuxt.config.js

module.exports = {
  plugins: [
    { src: '~plugins/vue-isotope.js', ssr: false }
  ],
  build: {
    vendor: ['vueisotope'],
    extend (config, { isClient }) {
      if (isClient) {
        config.resolve.alias = Object.assign(config.resolve.alias, {
          'masonry': 'masonry-layout',
          'isotope': 'isotope-layout'
        })
      }
    }
  }
}

plugins/vue-isotope.js

import Vue from 'vue'
import isotope from 'vueisotope'

Vue.component('isotope', isotope)

This option ssr: false is required until Vue.Isotope becomes compatible with SSR.

In the meantime, you will have this warning from Vue:

[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

All 8 comments

Hi , I tried your example component .
I have interest . especially I will use Isotope layout near future.

I provide my try for your reference

yarn add vueisotope

index.vue

<template lang="pug">
section
  vueisotope(:list="list",id="root_isotope",class="isoDefault",:options='option')
    div(v-for="element in list", :key="element.id")
      | {{element.name}}
      br
      | {{element.id}}

</template>
<script>
const vueisotope = process.BROWSER_BUILD ? require('vueisotope') : '';

export default {
  data() {
    return {
      list: [{ name: 'John', id: 25 },
      { name: 'Joao', id: 7 },
      { name: 'Albert', id: 12 },
      { name: 'Jean', id: 100 }],
      selected: null,
      option: {
        getSortData: {
          id: 'id',
        },
        sortBy: 'id',
      },
    };
  },
  head() {
    return {
      title: 'sitename',
    };
  },
  components: {
    vueisotope,
  },
};
</script>

I used eslint-config-airbnb-base , so , I need use global require here.

but I got some error message .

ERROR in ./~/isotope-layout/js/layout-modes/masonry.js
Module not found: Error: Can't resolve 'masonry/masonry' in 'C:\Users\ausir\nuxt-axios-exercise\node_modules\isotope-layout\js\layout-modes'
 @ ./~/isotope-layout/js/layout-modes/masonry.js 12:4-16:15
 @ ./~/isotope-layout/js/isotope.js
 @ ./~/vueisotope/dist/vue_isotope.min.js

so I tried find source , and I found this
http://isotope.metafizzy.co/extras.html#webpack
masonry.js

define( [
        '../layout-mode',
        'masonry/masonry'
      ],

so, I add 2 alias in nuxt.config..js

build: {
    /*
    ** Run ESLINT on save
    */
    extend(config, ctx) {
      config.resolve.alias['masonry'] = 'masonry-layout';  // <-- this
      config.resolve.alias['isotope'] = 'isotope-layout';  // <-- and this
      if (ctx.isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/,
        });
      }
    },
  },

vueisotope is work for me !

but I didn't try generate function yet ..

Thanks for the info @ausir0726

So it looks like the key difference is

const vueisotope = process.BROWSER_BUILD ? require('vueisotope') : '';

VS

if (process.BROWSER_BUILD) {
  require('vueisotope')
}
import isotope from 'vueisotope'

Maybe the former should be in the docs?

import need in first ( head ) line
then follow require .

but import will have error for SSR

so we need if ( process.BROWSER_BUILD )
but import can't use in if condition
so we just can use require

but for my eslint-config-airbnb-base rules
require also can't write in if(){} condition ( global-requrie )
so , I need wirte const vueisotope = process.BROWSER_BUILD ? require('vueisotope') : '';
then I can pass airbnb-base linter .

if you just use eslint-config-standard
I think you can just write require in if condition

if (process.BROWSER_BUILD) {
  const isotope = require('vueisotope');
}

It should be work ...

for some library you don't need a variable or import
like smoothscroll-polyfill

if (process.BROWSER_BUILD) {
  require('smoothscroll-polyfill').polyfill();
}

but usually need require assign variable
like. sweetalert2

if (process.BROWSER_BUILD) {
  const swal = require('sweetalert2');
}
swal('Any fool can use a computer');

Thank you @ausir0726 for your help

In the upcoming release, we are adding an ssroption in the plugins key of the nuxt.config.js, so you will be able to integrate Vue.Isotope this way @smth:

nuxt.config.js

module.exports = {
  plugins: [
    { src: '~plugins/vue-isotope.js', ssr: false }
  ],
  build: {
    vendor: ['vueisotope'],
    extend (config, { isClient }) {
      if (isClient) {
        config.resolve.alias = Object.assign(config.resolve.alias, {
          'masonry': 'masonry-layout',
          'isotope': 'isotope-layout'
        })
      }
    }
  }
}

plugins/vue-isotope.js

import Vue from 'vue'
import isotope from 'vueisotope'

Vue.component('isotope', isotope)

This option ssr: false is required until Vue.Isotope becomes compatible with SSR.

In the meantime, you will have this warning from Vue:

[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

It still doesn't work when using generate! Please reopen issue

ERROR in ./node_modules/isotope-layout/js/layout-modes/masonry.js
Module not found: Error: Can't resolve 'masonry/masonry' in '/nuxt-examples/node_modules/isotope-layout/js/layout-modes

Sorry, I fix it already. I had a wrong condition in nuxt.config if (ctx.dev && ctx.isClient) so it was working only in Dev.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gary149 picture gary149  路  3Comments

mikekidder picture mikekidder  路  3Comments

msudgh picture msudgh  路  3Comments

mattdharmon picture mattdharmon  路  3Comments

pehbehbeh picture pehbehbeh  路  3Comments