简体   繁体   中英

Cannot read property `match` of undefined. I have no clues about it, since it doesn't point to any files

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

无法读取未定义的属性“匹配”

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"

无法读取未定义的属性“app”

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()

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM