【PPic】项目中重要第三方组件集成打包测试


首先利用各个组件把项目的基础搭建起来,并测试打包等基础功能

1. 利用electron-vue搭建基础项目

至于vue-cli这些基础工具就不讲了

vue init simulatedgreg/electron-vue PPic      

? Application Name ppic
? Project description A Image Hosting
? Select which Vue plugins to install vue-electron
? Use linting with ESLint? Yes
? Which eslint config would you like to use? Standard
? Setup unit testing with Karma + Mocha? No
? Setup end-to-end testing with Spectron + Mocha? No
? What build tool would you like to use? builder
? author MaStone

   vue-cli · Generated "PPic".

说明下,本项目没有复杂的页面构成,所以关闭了vue-router以及vuex,同样也暂时关闭了测试…

cd PPic
npm run install
npm run build  //打包后的文件在build目录,打开测试之

【PPic】项目中重要第三方组件集成打包测试

安装过程中,可能遇到node或electron下载缓慢甚至下载失败,我们可以通过使用淘宝镜像网站解决这个问题,这个配置主要是在electron-downloade

ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/" npm install electron

项目初始化目录结构
【PPic】项目中重要第三方组件集成打包测试

2. 利用electron-window-manager进行窗口的管理

对项目进行规划后,存在主页面和设置页面

1)安装electron-window-manager
npm install --save electron-window-manager

安装完毕electron-window-manager,使用之,出现了默认错误,Cannot find module 'melanke-watchjs'安装之

npm install melanke-watchjs --save
2)重新调整目录结构,建立views目录,专用于页面

【PPic】项目中重要第三方组件集成打包测试

将最外层的App.vueindex.ejsmain.js移到renderer/views/main下,名在App.vue页面div内书写main字符串,同理,复制这些文件到renderer/views/setting下,修改字符串为setting

3)修改webpack.renderer.config.js配置多个入口,以及利用插件生成多个html入口文件
  entry: {
    renderer: path.join(__dirname, '../src/renderer/views/main/main.js'),
    setting: path.join(__dirname, '../src/renderer/views/setting/setting.js')
  },
  plugins: [
    new ExtractTextPlugin('styles.css'),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, '../src/renderer/views/main/index.ejs'),
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        removeComments: true
      },
      nodeModules: process.env.NODE_ENV !== 'production'
        ? path.resolve(__dirname, '../node_modules')
        : false,
      chunks: ['renderer']   //只载入renderer入口
    }),
    new HtmlWebpackPlugin({
      filename: 'setting.html',
      template: path.resolve(__dirname, '../src/renderer/views/setting/index.ejs'),
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        removeComments: true
      },
      nodeModules: process.env.NODE_ENV !== 'production'
        ? path.resolve(__dirname, '../node_modules')
        : false,
      chunks: ['setting']
    })
 ]
4)调整代码,在main中设置一个按钮,点击按钮打开Setting页面,为了更好的使用electron-window-manager,我写了一个辅助类,专门用户相关页面管理,打开,获取窗口句柄等。
'use strict'
import windowManager from 'electron-window-manager'
const homeURL = process.env.NODE_ENV === 'development'
  ? `http://localhost:9080/index.html`
  : `file://${__dirname}/index.html`

const settingURL = process.env.NODE_ENV === 'development'
  ? `http://localhost:9080/setting.html`
  : `file://${__dirname}/setting.html`

class Window {
  home () {
    var win = windowManager.get('home')
    if (win !== false) {
      return win
    }
    console.log('home', win)
    var homeWindow = windowManager.createNew('home', 'Welcome ...', homeURL, false, {
      'width': 998,
      'height': 600,
      'showDevTools': true,
      'resizable': true
    })
    return homeWindow
  }
  setting () {
    var win = windowManager.get('setting')
    if (win !== false) {
      return win
    }
    console.log('setting', win)
    var settingWindow = windowManager.createNew('setting', 'Welcome ...', settingURL, false, {
      'width': 600,
      'height': 450,
      'showDevTools': true,
      'resizable': true
    })
    return settingWindow
  }
}

export default new Window()

其中要说明的是export default new Window()通过导出new Window()可以保证任何使用 import window 的地方,都在使用同一实例,也就是类似单例模式(查资料所得,做了简单测试,如有错误,请指出)

//调整 `src/main/index.js`代码,使用 `window` 组件,并设置消息监听
import { app, ipcMain } from 'electron'
import window from './window'
function createWindow () {
  window.home().open()
}

ipcMain.on('openSetting', () => {
  window.setting().open()
})
5)views/main/App.vue 调整代码,点击Button,打开Setting
<template>
  <div id="app">
    <button @click="openSetting">设置</button>
  </div>
</template>

<script>
const { ipcRenderer } = require('electron')
export default {
  name: 'PPic',
  methods: {
    openSetting: () => {
      ipcRenderer.send('openSetting')
    }
  }
}
</script>
6)测试吧!
npm run dev
//顺便build观察是否引入了错误
npm run build

3.安装iView组件,进行UI基础组件库

npm install iview --save
//in views/main/main.js
import iView from 'iview'
import 'iview/dist/styles/iview.css'    // 使用 CSS
Vue.use(iView)
//in App.vue
<template>
  <div id="app">
    <Button type="primary" @click="openSetting">设 置</Button>
  </div>
</template>

4.安装 Sqlite3

npm install sqlite3 --save
//packages.json 添加命令
"postinstall": "install-app-deps"
//执行之,目的是利用`electron-builder`重新构建绑定了当下sqlite3版本的electron
npm run postinstall
//或者直接执行`electron-builder`的`install-app-deps`命令
./node_modules/electron-builder/out/cli/install-app-deps.js  

遇到一个问题 node-pre-gyp install --fallback-to-build 后一直就不动了,查资料后(参考:http://www.zgljl2012.com/node…

一个办法是挂VPN下载,另外就是可以手工下载对应版本软件,https://mapbox-node-binary.s3…,然后放在node_modules/sqlite3/lib/binding/node-v48-darwin-x64/node_sqlite3.node目录;分析这个问题最好的办法就是进入到node_modules/sqlite3目录,运行./node_modules/node-pre-gyp/bin/node-pre-gyp install --fallback-to-build命令,它会打印更多的信息,比如下载地址等;

同样在执行npm run postinstall 是可能遇到如下错误

Error output:
node-pre-gyp ERR! Tried to download(undefined): https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.9/electron-v1.7-darwin-x64.tar.gz 
node-pre-gyp ERR! Pre-built binaries not found for sqlite3@3.1.9 and electron@1.7.5 (electron-v1.7 ABI) (falling back to source compile with node-gyp) 
gyp WARN install got an error, rolling back install
gyp ERR! configure error 
gyp ERR! stack Error: connect ETIMEDOUT 54.231.40.147:443
gyp ERR! stack     at Object.exports._errnoException (util.js:1007:11)
gyp ERR! stack     at exports._exceptionWithHostPort (util.js:1030:20)
gyp ERR! stack     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14)
gyp ERR! System Darwin 16.6.0
gyp ERR! command "/Users/ipanda/.nvm/versions/node/v6.2.2/bin/node" "/Users/ipanda/.nvm/versions/node/v6.2.2/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "configure" "--fallback-to-build" "--module=/Users/ipanda/App/nwjs/panda_photo/node_modules/sqlite3/lib/binding/electron-v1.7-darwin-x64/node_sqlite3.node" "--module_name=node_sqlite3" "--module_path=/Users/ipanda/App/nwjs/panda_photo/node_modules/sqlite3/lib/binding/electron-v1.7-darwin-x64"
gyp ERR! cwd /Users/ipanda/App/nwjs/panda_photo/node_modules/sqlite3

又是连接超时,使用淘宝镜像地址

NPM_CONFIG_ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ ./node_modules/electron-builder/out/cli/install-app-deps.js

写一个小的测试函数:

import sqlite3 from 'sqlite3'
import fs from 'fs'
class db {
  initDb = () => {
    try {
      fs.mkdirSync('./data')
    } catch (e) {
      if (e.code !== 'EEXIST') {
        return
      }
      console.log(e)
    }

    this.db = new sqlite3.Database('data/PPic.db')

    this.db.run('select * from images limit 0,1', (err) => {
      if (err === null || err.code !== 'SQLITE_ERROR') {
        return
      }
      this.db.run('CREATE TABLE [images] (id integer PRIMARY KEY AUTOINCREMENT UNIQUE, ' +
        'filename varchar DEFAULT 未命名,url varchar NOT NULL,width integer,height integer,' +
        'storeType varchar NOT NULL, create_at timestamp NOT NULL,update_at timestamp)')
    })

    this.db.run('select * from config limit 0,1', (err) => {
      if (err === null || err.code !== 'SQLITE_ERROR') {
        return
      }
      this.db.run('CREATE TABLE [config] (id integer PRIMARY KEY AUTOINCREMENT UNIQUE, ' +
        'storeType varchar NOT NULL,accessKey varchar NOT NULL,secretKey  varchar NOT NULL, bucket varchar,' +
        'origin varchar,url varchar, create_at timestamp NOT NULL,update_at timestamp)')
    })
  }
}
export default new db
// src/main/index.js 引用之
import db from './db'
db.initDb()
// npm run dev && npm run build测试之

到此项目用到的第三方组件都已经集成并打包测试完毕,接下来可能会遇到某些小的辅助类,就不做重点介绍了,通常也不会引入其他错误。


发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>