Search code examples
vue.jsvue-componentgridsome

Cannot build Gridsome project: modal causes 'window is not defined' error


My project runs ok in development mode but fails in build mode. The full error is

ReferenceError: window is not defined
at Object.<anonymous> (node_modules/vue-js-modal/dist/index.js:1:210)
at __webpack_require__ (webpack/bootstrap:25:0)
at Module.<anonymous> (assets/js/app.a0a1f9b3.js:5157:12)
at __webpack_require__ (webpack/bootstrap:25:0)
at Object.<anonymous> (assets/js/app.a0a1f9b3.js:2785:18)
at __webpack_require__ (webpack/bootstrap:25:0)
at assets/js/app.a0a1f9b3.js:118:18
at Object.<anonymous> (assets/js/app.a0a1f9b3.js:121:10)
at o (/home/nestor/progs/gridsome_blog/node_modules/vue-server-renderer/build.prod.js:1:77545)
at /home/nestor/progs/gridsome_blog/node_modules/vue-server-renderer/build.prod.js:1:78138

The only clue that gives me is the modal plugin. I've read that it's because of client side rendering but don't understand how to fix it in this case. In main.js I import and set the plugin with:

import VModal from 'vue-js-modal'
// other things
Vue.use(VModal, { dynamic: true , dynamicDefaults: { clickToClose: true }, injectModalsContainer: true})

and I use it in a vue file as a dynamic modal, so when a button is clicked the modal is created by a method defined in the export dictionary:

export default {
     // other things
     methods:{ show_modal(title_,company_,url_,text_){
          this.$modal.show({
            template: `
            <div id="modal_div" style="padding: 0px; overflow: auto;">
              <h4 id="#modal_title" style="margin:15px;">{{title}}</h4>
              <a target="_blank" :href="url"> <h5 id="#modal_subtitle" style="margin:15px;">{{company}}</h5></a>
              <p id="#modal_text" style="margin:15px;font-family:Muli;text-align:justify">{{text}}</p>
            </div>
              `,
              props: ['title','company','url','text']
            }, {
              title: title_,
              company: 'With: ' + company_,
              url: url_,
              text: text_
            }, {
              height: 'auto',
              adaptive: true,
              draggable: true
            }, {
              'before-close': (event) => { console.log('modal closed'); }
            })
    }
}

I'm new with Vue, any help would be appreciated.


Solution

  • You are right, this is because SSR - there is no window during build. One way is to use <ClientOnly> tags in your template and make all this things in mounted() in export.

    In this particular case you are lucky: there's a plugin for your component. Gridsome plugin library contains many wrappers for vue components, so you can use them easier.