Record of electron stepping on the pit (3)

Time:2020-9-29

The content of this article is only applicable to the use ofelectron-vueTemplate generatedelectronEngineering, related configuration is also around it. Of course, usevuecli3GeneratedelectronEngineering can also refer to.

aboutelectron-vueEngineering, because theoretically default write dead9080The port may be occupied, so the applicationhttpServices should use self judgment to make ports available. ~~~~

Example of using flash plug-in package by electron

Realization of judgment logic

stay/lib/utils/Create file underportIsOccupied.jsTo realize the judgment of port occupation, and to process environmentprocess.envInjection variableDEV_PORTAnd return the available ports, so that the main process page can read the available ports through the process environment, or obtain the available ports through the process environmentPromise.resolve()Available ports returned.

const net = require('net')

function portIsOccupied(port) {

  const server = net.createServer().listen(port)
  
  return new Promise((resolve, reject) => {
  
    server.on('listening', () => {
      console.log(`the server is runnint on port ${port}`)
      server.close()
      //State sharing by injecting process environment variables
      process.env.DEV_PORT = port
      process.env.PROD_PORT = port
      //Return available ports
      resolve(port)
    })

    server.on('error', (err) => {
      if (err.code === 'EADDRINUSE') {
        //Pay attention to this sentence, such as occupying port number + 1
        resolve(portIsOccupied(port + 1))
        console.log(`this port ${port} is occupied.try another.`)
      } else {
        reject(err)
      }
    })
    
  })

}

export default portIsOccupied

Port in configuration development mode

Because the project is usedelectron-vueGeneration engineering, and the current mainstream use ofvuecli3GeneratedelectronThe engineering structure is different, but the logic is basically the same. Here’s a look atelectron-vueProject configuration.

Find the project/.electron/dev-runner.jsFile, you can see that the service is throughWebpackDevServerThe plug-in runs, and the port is dead9080

const server = new WebpackDevServer(
  compiler,
  {
    contentBase: path.join(__dirname, '../'),
    quiet: true,
    before (app, ctx) {
      app.use(hotMiddleware)
      ctx.middleware.waitUntilValid(() => {
        resolve()
      })
    }
  }
)


server.listen(9080)

With a little modification, the function written above can be used to determine whether to use the idle port to ensure the operation of the application.

const portIsOccupied = require('../lib/utils/portIsOccupied')

……
……

portIsOccupied(9080).then(port => {
  server.listen(port)
})

Because purenodeNot supported in environmentes6Ofimport/exportGrammar, so we need the help ofbabelTo make supportimport/export

Installation dependency:

$ npm install babel-cli -D
$ npm babel-preset-es2015 -D

to configure.babelrc

{
    "presets": [
        "es2015"
    ]
}

Modification package.js Script run command:

before :

{
    "scripts": [
        "dev": "node .electron-vue/dev-runner.js"
    ]
}

after :

{
    "scripts": [
        "dev": "babel-node .electron-vue/dev-runner.js"
    ]
}

Configure ports in production mode

In the main thread file/src/main/index.jsA judgment function is introduced in this paperexpressAs a local package filehttpStatic server, makingflashIt can load normally.

For the original write dead portlocalServerThe port judgment function is introduced.

before :

function localServer() {
  let server = express()
  server.use(express.static(__dirname))
  server.listen(9080)
}

after :

import portIsOccupied from '../../lib/utils/portIsOccupied'

function localServer() {
  //Using promise and await to realize synchronization
  return new Promise((resolve, reject) => {
    let server = express()
    server.use(express.static(__dirname))
    portIsOccupied(9080).then(port => {
      server.listen(port)
      resolve(port)
    })
  }) 
}

When executed in production modelocalServerAfter the function, the available ports can be read from the process environment at any location to ensure that the service is successfully started.

Complete logic

Here is the complete main thread file/src/main/index.jsThe specific logic is as follows:

import { app, BrowserWindow } from 'electron'
import express from 'express'

//Introduce the function of automatically judging the port available
import portIsOccupied from '../../lib/utils/portIsOccupied'

/**
 * Set `__static` path to static files in production
 * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
 */
if (process.env.NODE_ENV !== 'development') {
  global.__static = require('path').join(__dirname, '/static').replace(/\/g, '\\')
}

//By default, the packaged file is loaded with the "file: //" protocol
//Because flash is not allowed to load under the "file: //" protocol, in order to solve the security problem of flash loading
//Use express as the local server to make the page run on the local HTTP port service
function localServer() {
  //Using promise and await to realize synchronization
  return new Promise((resolve, reject) => {
    let server = express()
    server.use(express.static(__dirname));
    portIsOccupied(9080).then(port => {
      server.listen(port)
      resolve(port)
    })
  }) 
}

let mainWindow

let flashPlugins = process.arch == 'x64' 
  ? require('path').resolve(__dirname, '../../lib/pepflashplayer64_29_0_0_238.dll')
  : require('path').resolve(__dirname, '../../lib/pepflashplayer32_29_0_0_238.dll')

if (__dirname.includes(".asar")) {
  flashPlugins = process.arch == 'x64' 
    ? require('path').join(process.resourcesPath + '/lib/pepflashplayer64_29_0_0_238.dll')
    : require('path').join(process.resourcesPath + '/lib/pepflashplayer32_29_0_0_238.dll')
}
app.commandLine.appendSwitch('ppapi-flash-path', flashPlugins);
app.commandLine.appendSwitch('ppapi-flash-version', '29.0.0.238');

async function createWindow () {

  if (process.env.NODE_ENV === "production") {
    //Using async / await to achieve synchronous waiting, ensure that process.env.PROD_ Assignment of port
    await localServer()
  }

  const winURL = process.env.NODE_ENV === 'development'
  ? `http://localhost:${process.env.DEV_PORT}`
  // : `file://${__dirname}/index.html`
  //To solve the problem that flash is not allowed to load under the "file: //" protocol
  : `http://localhost:${process.env.PROD_PORT}/index.html`

  /**
   * Initial window options
   */
  mainWindow = new BrowserWindow({
    height: 900,
    width: 1600,
    useContentSize: true,
    frame: false,
    center: true,
    Fullscreenenable: false, // allow full screen
    Center: true, // whether it appears in the center of the screen
    title: 'electron-rtmp',
    BackgroundColor: '# FFF', // background color, used for transparent and frameless windows
    Title barstyle: 'hidden' // the styles of title bar include hidden, hidden inset, custom buttons on hover, etc
    Resolvable: false, // stretch size allowed
    'webPreferences': {
      plugins: true,
      webSecurity: false,
      defaultFontFamily: {
        standard: "Microsoft YaHei",
        defaultEncoding: "utf-8"
      }
    }
  })

  if (process.env.NODE_ENV == 'development') {
    mainWindow.webContents.openDevTools()
  }
  
  mainWindow.loadURL(winURL)

  mainWindow.on('closed', () => {
    mainWindow = null
  })

}

app.on('ready', createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})