-1

I'm getting this error : Cannot read property match of undefined.

Cannot read property 'match' of undefined

This is the line in polyfills.js pointed by the error message:

process.version.match

I do not have any clue about this kind of problem, because it doesn't point to any specific file. Would you be so kind in having a look at this github repo.

https://github.com/raphael10-collab/ElectronVueTypeScriptScaffolding

Update 1)

Thanks to Elias comment, I realized that vue.config.js was messed-up. Now vue.config.is is :

// https://nklayman.github.io/vue-cli-plugin-electron-builder/guide 
/guide.html#web-workers
const WorkerPlugin = require('worker-plugin')

module.exports = {
  // options...
  publicPath: '',
  pluginOptions: {
    electronBuilder: {
      // Prevent bundling of certain imported packages and instead 
retrieve these external dependencies at runtime.
      // In order to connect to websocket.
      externals: ['ggc'],
      builderOptions: {
        productName: 'GGC',
        win: {
          icon: './public/app.ico'
        },
        mac: {
          icon: './public/icons/Icon.icns',
          target: [
            'pkg',
            'dmg',
            'zip',
          ],
        },
        linux: {
          icon: './public/app.png'
        }
      },
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/configuration.html#webpack-configuration
      chainWebpackRendererProcess: (config) => {
        // Chain webpack config for electron renderer process only
        // The following example will set IS_ELECTRON to true in your 
app
        config.plugin('define').tap((args) => {
          args[0]['IS_ELECTRON'] = true
          return args
        })
      },
      mainProcessFile: 'src/background.js',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/configuration.html#typescript-options
      disableMainProcessTypescript: false, // Manually disable 
typescript plugin for main process. Enable if you want to use regular 
js for the main process (src/background.js by default)
      mainProcessTypeChecking: false, // Manually enable type checking
 during webpck bundling for background file.
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/guide.html#preload-files
      preload: 'src/preload.js',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/security.html#node-integration
      nodeIntegration: true
    },
    // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/guide.html#web-workers
    configureWebpack: {
      plugins: [new WorkerPlugin()]
    }
  }
}

Regarding nodeIntegration, I disabled it in /src/background.js because I read it is more secure to have preload.js file

This is my new webpack.config.js (it was messed up as well, like vue.config.is, with each module.exports overriding the previous one):

module.exports = {
  entry: './src/background.js',
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'background.js'
  },
  // https://github.com/GoogleChromeLabs/worker-plugin
  plugins: [
    new WorkerPlugin()
  ]
}

I do not understand what should I enable here in webpack: https://webpack.js.org/plugins/define-plugin/

Update 2)

I disabled nodeIntegration in vue.config.js

vue.config.js :

// https://nklayman.github.io/vue-cli-plugin-electron-builder/guide 
/guide.html#web-workers
const WorkerPlugin = require('worker-plugin')

module.exports = {
  // options...
  publicPath: '',
  pluginOptions: {
    electronBuilder: {
      // Prevent bundling of certain imported packages and instead 
retrieve these external dependencies at runtime.
      // In order to connect to websocket.
      externals: ['ggc'],
      builderOptions: {
        productName: 'GGC',
        win: {
          icon: './public/app.ico'
        },
        mac: {
          icon: './public/icons/Icon.icns',
          target: [
            'pkg',
            'dmg',
            'zip',
          ],
        },
        linux: {
          icon: './public/app.png'
        }
      },
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/configuration.html#webpack-configuration
      chainWebpackRendererProcess: (config) => {
        // Chain webpack config for electron renderer process only
        // The following example will set IS_ELECTRON to true in your 
app
        config.plugin('define').tap((args) => {
          args[0]['IS_ELECTRON'] = true
          return args
        })
      },
      mainProcessFile: 'src/background.js',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/configuration.html#typescript-options
      disableMainProcessTypescript: false, // Manually disable 
typescript plugin for main process. Enable if you want to use regular 
js for the main process (src/background.js by default)
      mainProcessTypeChecking: false, // Manually enable type checking
 during webpck bundling for background file.
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/guide.html#preload-files
      preload: 'src/preload.js',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/security.html#node-integration
      nodeIntegration: false
    },
    // https://nklayman.github.io/vue-cli-plugin-electron-builder
/guide/guide.html#web-workers
    configureWebpack: {
      plugins: [new WorkerPlugin()]
    }
  }
}

and defined process in webpack.config.js

webpack.config.js :

module.exports = {
  entry: './src/background.ts',
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'background.js'
  },
  // https://github.com/GoogleChromeLabs/worker-plugin
  plugins: [
    new WorkerPlugin()
  ],
  // https://webpack.js.org/plugins/define-plugin/
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
  })
}

When running yarn electron:serve I now get Error: Cannot read property 'match' of undefined

Cannot read property 'match' of undefined

If I keep nodeIntegration:true in vue.config.js and change in src/background.js to :

webPreferences: {
  nodeIntegration: true,
  //nodeIntegration: false,
  //contextIsolation: true, // protects against prototype pollution
  //preload: path.join(__dirname, "../dist_electron/preload.js"),
},

when running yarn electron:serve I get this error: "Cannot read property 'app' of undefined"

Cannot read property 'app' of undefined

This is /src/store/modules/app.ts :

import Vue from 'vue'
import { loadSettings, setSettings } from '@/services/electron-
services/setting/setting'

const TOGGLE_THEME = 'TOGGLE_THEME'

const stateRecord: App = loadSettings()

const app = {
  state: {
    currentTheme: stateRecord.currentTheme || 'light',
  },
  mutations: {
    [TOGGLE_THEME](state: App, currentTheme: Theme) {
      state.currentTheme = currentTheme
    },
  },
  actions: {
    TOGGLE_THEME({ commit }: any, payload: App) {
      setSettings('settings.currentTheme', payload.currentTheme)
      commit(TOGGLE_THEME, payload.currentTheme)
    },
  },
}

export default app

But I would prefer to solve the problem while keeping nodeIntegration: false in order to keep the app safer

Update 3) I discovered that the problem "Cannot read property match of undefined" disappears once I comment this line

const theme = db.get<Theme>('settings.currentTheme');

in src/background.ts :

async function create Window() {
    const windowSize = db.get<WindowSizeModel>('windowSize');
    //const theme = db.get<Theme>('settings.currentTheme');
    win = new BrowserWindow({
      ...windowSize,
      webPreferences: {
        nodeIntegration: false,
        contextIsolation: true,
        preload: path.join(__dirname, "../dist_electron/preload.js"),
      },
  })

and db.get('settings.currentTheme') comes from this file:

src/services/electron-services/database/index.ts :

import Lowdb from 'lowdb'
import FileSync from 'lowdb/adapters/FileSync'
import path from 'path'
import fs from 'fs-extra'
import LodashID from 'lodash-id'
import { app, remote } from 'electron'

interface Schema {
  windowSize: {
    height: number
    width: number
  }
  settings: {
    currentLang: string
    currentTheme: string
  }
}

const isRenderer: boolean = process.type === 'renderer'
// Render process use remote app
const APP: Electron.App = isRenderer ? remote.app : app

const STORE_PATH: string = APP.getPath('userData')

// In production mode, during the first open application
// APP.getPath('userData') gets the path nested and the datastore.js  
is loaded.
// if it doesn't exist, create it.
if (!isRenderer) {
  if (!fs.pathExistsSync(STORE_PATH)) {
    fs.mkdirpSync(STORE_PATH)
  }
}

class DB {
  private db: Lowdb.LowdbSync<Schema>
  public constructor() {
    const adapter: Lowdb.AdapterSync<Schema> = new FileSync<Schema> 
(path.join(STORE_PATH, '/db.json'))
    this.db = Lowdb(adapter)
    // Use lodash-id must use insert methods
    this.db._.mixin(LodashID)
    if (!this.db.has('windowSize').value()) {
      this.db
        .set('windowSize', {
          width: 1025,
          height: 749,
        })
        .write()
    }
    if (!this.db.has('settings').value()) {
      this.db
        .set('settings', {
          //currentLang: 'en',
          currentTheme: 'light',
        })
        .write()
    }
    // Purple to Night
    if (this.db.get('settings.currentTheme').value() === 'purple') {
      this.db.set('settings.currentTheme', 'night').write()
    }
    if (!this.db.has('settings.currentLang')) {
      this.db.set('settings.currentLang', 'en').write()
    }
  }

  // read() is to keep the data of the main process and the 
rendering process up to date.
  public read() {
    return this.db.read()
  }
  public get<T>(key: string): T {
    return this.read().get(key).value()
  }
  public find<T>(key: string, id: string): T {
    const data: $TSFixed = this.read().get(key)
    return data.find({ id }).value()
  }
  public set<T>(key: string, value: T): T {
    return this.read().set(key, value).write()
  }
  public insert<T>(key: string, value: T): T {
    const data: $TSFixed = this.read().get(key)
    return data.insert(value).write()
  }
  public update<T>(key: string, id: string, value: T): T {
    const data: $TSFixed = this.read().get(key)
    return data.find({ id }).assign(value).write()
  }
  public remove<T>(key: string, id: string): T {
    const data: $TSFixed = this.read().get(key)
    return data.removeById(id).write()
  }
  public filter<T, K>(key: string, query: K): T {
    const data: $TSFixed = this.read().get(key)
    return data.filter(query).value()
  }
  public has(key: string): boolean {
    return this.read().has(key).value()
  }
}

export default new DB()
Raphael10
  • 2,508
  • 7
  • 22
  • 50
  • 1
    Whatever object you are calling `match` on, is in fact `undefined` and not an object at all. You need to verify that this object is being built properly. And please never expect us to go to a 3rd party site to view your code. Post the relevant code right here in your question. – Scott Marcus Aug 29 '20 at 18:26
  • @ScottMarcus I didn't know that github is a 3rd party site – Raphael10 Aug 29 '20 at 19:07
  • A 3rd party site is any site that is operated by a 3rd party (not you, Stack Overflow, but someone else). What happens if your Git repo goes away at some point? Then your question here would be meaningless. We always want everything relating to a question here. – Scott Marcus Aug 29 '20 at 22:48
  • @ScottMarcus as you can see above, once Elias kindly pointed me to vue.config.js and webpack.config.js I posted the relative code. At first, as explained before, I didn't know, because the error messages didn't contain any clues, where to look for, and therefore I thought posting the link the GitHub repo could be a starting point – Raphael10 Aug 31 '20 at 06:41

1 Answers1

1

Your problem is the vue.config.js only exports the last object, each module.exports overrides previous exports.

The other problem you may have is that you disabled nodeIntegration, thus process will indeed be undefined unless you enable webpacks definition.

Edit: To make require available on the renderer, you need to enable nodeIntegration in your background.ts file or disable it in vue.config.js.

Elias Schablowski
  • 2,619
  • 9
  • 19
  • thank you for pointing me to the messed-up vue.config.js (and webpack.config.js as well) file. I do not understand what should I enable in webpack.config.js. I updated my post with Update 1) – Raphael10 Aug 29 '20 at 19:34
  • @Raphael10, I updated my answer, also The define plugin is used to define variables in webpack, often also `process.env`, and sometimes patch `process.version` if required, which it apparently isn't in your case. – Elias Schablowski Aug 30 '20 at 06:26
  • I disabled nodeIntegration in vue.config.js and defined process in webpacks definition (not sure about what I did) and get the error: "Cannot read property 'match' of undefined". I updated my post with update 2). – Raphael10 Aug 31 '20 at 06:33
  • I discovered that the problem "Cannot read property match of undefined" disappears once I comment this line: const theme = db.get('settings.currentTheme'); in src/background.ts . I integrated my question with update 3) – Raphael10 Aug 31 '20 at 14:40
  • Now it works... Thank you very @Elias Schablowski for your kind suggestions – Raphael10 Aug 31 '20 at 15:42