Vue-devtools: Devtools crash the page

Created on 17 Sep 2018  ยท  6Comments  ยท  Source: vuejs/vue-devtools

Version

5.0.0-beta.3

Browser and OS info

Windows 10, Chrome 69.0.497.92

Steps to reproduce

When the extension is enabled, my current application in a dev server becomes a white page. The following error shows in the console:

Uncaught TypeError: Cannot read property 'getters' of undefined
    at numberOfClients (webpack-internal:///715:189)
    at wrappedGetter (webpack-internal:///7:632)
    at Vue$3.computed.(:3066/anonymous function) (webpack-internal:///7:435:42)
    at Watcher.get (webpack-internal:///1:3114)
    at Watcher.evaluate (webpack-internal:///1:3221)
    at Vue$3.computedGetter [as auth/numberOfClients] (webpack-internal:///1:3473)
    at Object.get [as auth/numberOfClients] (webpack-internal:///7:437)
    at l (<anonymous>:1:1915)
    at l (<anonymous>:1:1912)
    at i (<anonymous>:1:2190)
npm list | grep vue
โ”‚ โ””โ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”ฌ [email protected]
โ”œโ”€โ”ฌ [email protected]
โ”‚ โ”œโ”€โ”€ [email protected]
โ”‚ โ”œโ”€โ”ฌ [email protected]
โ”‚ โ””โ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”ฌ [email protected]
โ”œโ”€โ”ฌ [email protected]
โ”œโ”€โ”ฌ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
// store/modules/auth/getters.js
import store from 'store';

// Some more things

export function numberOfClients(state) {
  let clients = store.getters['auth/clients'];
  return clients.length;
};

What is expected?

The page keeps functioning and the devtools do something that helps me develop the application

What is actually happening?

White screen. Page does not reach the first render cycle, while without the dev tools the page renders just fine.

need repro

Most helpful comment

Hi I get the same/simular. (white page)
"vue": "^2.5.17",
"vuex": "^3.0.1",
Chrome: 69.0.3497.100 (64-bit)

When I use 4.1.5 beta extension everything works fine landing page ok, no errors in console
When I use 5.0.0 beta 3 the app "doesn't start" (white page)

With 5.0.0 beta 3 error in console:

vue.esm.js?efeb:3147 Uncaught TypeError: Cannot read property 'Value' of undefined
    at highBandwidth (getters.js?73dc:6)
    at wrappedGetter (vuex.esm.js?358c:734)
    at Vue.computed.(:8080/anonymous function) (webpack-internal:///./node_modules/vuex/dist/vuex.esm.js:541:42)
    at Watcher.get (vue.esm.js?efeb:3142)
    at Watcher.evaluate (vue.esm.js?efeb:3249)
    at Vue.computedGetter [as settings/highBandwidth] (vue.esm.js?efeb:3507)
    at Object.get [as settings/highBandwidth] (vuex.esm.js?358c:536)
    at l (<anonymous>:1:1915)
    at l (<anonymous>:1:1912)
    at i (<anonymous>:1:2190)

getters.js in state module settings:

const highBandwidth =
  state => state.settingGroups.map(group => group.Settings).reduce((a, b) =>
    a.concat(b), []).find(s => s.Name === 'HighBandwidth').Value === 'true'

At landing/login page highBandwidth is not available yet. (settings is retrived on login)
but highBandwidth is not used yet either
highBandwidth is used in the navbar component
the navbar component is used in app.vue but disabled with v-if="showNavBar" (false)
at the login/landing page. Only login dialog/view is present.

<template>
  <div id="app">
    <navbar-element v-if="showNavBar" :live="live" @toggleLiveMode="toggleLiveMode" @refresh="refresh()"/>
    <router-view ref="view"/>
  </div>
</template>

It looks like the new dev tool tool crawls through my getters even though they have not yet been used
and then crashes the app when the highBandwidth getter is not ready.

Hope this helps.
Thank you for your effort to the vue community.

All 6 comments

We need a minimal reproduction, this works fine in our tests.

To reproduce use the following code and enable the 5.0.0-beta3 version of the dev tools. The page will crash with a Uncaught TypeError: Cannot read property 'getters' of undefined and not render anything. If disabled in the modules from /store/index.js it will show the test text. If the extension is disabled, the text will also show. If the 4.1.5 beta version of the dev tools is enabled, it will also show the text.

// src/js/main.js
import Vue from 'vue';
import router from './router';
import store from './store';
import App from 'components/App';

/* eslint-disable no-new */
(function(vue) {
  console.log(store, vue);
})(new Vue({
  el: '#app',
  store,
  router,
  template: '<App/>',
  components: { App },
}));
// src/js/components/App.vue
<template>
  <div id="app">
    This is a test
  </div>
</template>

<script>
export default {
  name: 'app'
}
</script>
// src/js/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import auth from './modules/auth';

Vue.use(Vuex);

const appStore = {
  modules: {
    auth,
  },
};

const store = new Vuex.Store(appStore);

export default store;
// src/js/store/modules/auth/index.js
import * as getters from './getters';
export default {
  namespaced: true,
  getters,
};
// src/js/store/modules/auth/getters.js
import store from 'store';
export function numberOfClients(state) {
  let clients = store.getters['auth/clients'];
  return clients.length;
};
// src/js/router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

const routes = [];

const Router = new VueRouter({
  routes
});

export default Router;
// build/webpack.base.conf.js
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  entry: {
    app: './src/js/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'src': resolve('src'),
      'assets': resolve('src/assets'),
      'components': resolve('src/js/components'),
      'config': resolve('config'),
      'styles': resolve('src/scss'),
      'api': resolve('src/js/api'),
      'router': resolve('src/js/router'),
      'helpers': resolve('src/js/helpers'),
      'constants': resolve('src/js/constants'),
      'store': resolve('src/js/store'),
      'vendor': resolve('src/js/vendor'),
      'theme': resolve('src/js/theme'),
    }
  },
  module: {
    rules: [
      {
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        enforce: 'pre',
        include: [resolve('src'), resolve('config'), resolve('test')],
        options: {
          formatter: require('eslint-friendly-formatter')
        }
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('config'), resolve('test')]
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        query: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
      { test: /\.(ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" },
    ]
  }
}
// build/webpack.dev.conf.js
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
  baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

module.exports = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
  },
  // eval-source-map is faster for development
  devtool: 'eval', // #inline-source-map',
  output: {
    devtoolModuleFilenameTemplate: info => {
      let filename = info.resourcePath;
      if (info.resource.match(/\.vue$/)) {
        filename = info.allLoaders.match(/type=script/) ? info.resourcePath : 'generated';
      }
      return filename;
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': config.dev.env
    }),
    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    new FriendlyErrorsPlugin()
  ]
})

@Akryum Please let me know if you need anything else

Hi I get the same/simular. (white page)
"vue": "^2.5.17",
"vuex": "^3.0.1",
Chrome: 69.0.3497.100 (64-bit)

When I use 4.1.5 beta extension everything works fine landing page ok, no errors in console
When I use 5.0.0 beta 3 the app "doesn't start" (white page)

With 5.0.0 beta 3 error in console:

vue.esm.js?efeb:3147 Uncaught TypeError: Cannot read property 'Value' of undefined
    at highBandwidth (getters.js?73dc:6)
    at wrappedGetter (vuex.esm.js?358c:734)
    at Vue.computed.(:8080/anonymous function) (webpack-internal:///./node_modules/vuex/dist/vuex.esm.js:541:42)
    at Watcher.get (vue.esm.js?efeb:3142)
    at Watcher.evaluate (vue.esm.js?efeb:3249)
    at Vue.computedGetter [as settings/highBandwidth] (vue.esm.js?efeb:3507)
    at Object.get [as settings/highBandwidth] (vuex.esm.js?358c:536)
    at l (<anonymous>:1:1915)
    at l (<anonymous>:1:1912)
    at i (<anonymous>:1:2190)

getters.js in state module settings:

const highBandwidth =
  state => state.settingGroups.map(group => group.Settings).reduce((a, b) =>
    a.concat(b), []).find(s => s.Name === 'HighBandwidth').Value === 'true'

At landing/login page highBandwidth is not available yet. (settings is retrived on login)
but highBandwidth is not used yet either
highBandwidth is used in the navbar component
the navbar component is used in app.vue but disabled with v-if="showNavBar" (false)
at the login/landing page. Only login dialog/view is present.

<template>
  <div id="app">
    <navbar-element v-if="showNavBar" :live="live" @toggleLiveMode="toggleLiveMode" @refresh="refresh()"/>
    <router-view ref="view"/>
  </div>
</template>

It looks like the new dev tool tool crawls through my getters even though they have not yet been used
and then crashes the app when the highBandwidth getter is not ready.

Hope this helps.
Thank you for your effort to the vue community.

May be related to #443

@Akryum This issue differs from the one linked, in that this issue refers to an issue where the Vue devtools crash (or used to crash, haven't tested it in a while) if you do an import store from './store' (at least, I believe that was this issue). For some reason instead of getting an actual store, you get undefined with the devtools open. With the devtools closed, it works as expected.

The issue referenced simply complains about getters being automatically calculated when opening the devtools, sometimes causing errors to be printed in the console even though no code referencing the getters was being called.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

davestewart picture davestewart  ยท  3Comments

sithuaung picture sithuaung  ยท  4Comments

Gedminas picture Gedminas  ยท  3Comments

sparlos picture sparlos  ยท  3Comments

stiltet picture stiltet  ยท  3Comments