菜单

XCel 项目总括:Electron 与 Vue 的性质优化

2019年1月19日 - JavaScript

XCel 项目总结:Electron 与 Vue 的属性优化

2017/03/01 · 基础技术 ·
Javascript,
算法

本文小编: 伯乐在线
刘健超-J.c
。未经小编许可,禁止转发!
欢迎到场伯乐在线 专栏作者

XCEL 是由京东用户体验设计部凹凸实验室推出的一个 Excel
数据清洗工具,其通过可视化的法子让用户轻松地对 Excel 数据开展筛选。

XCEL 基于 Electron 和 Vue 2.x,它不仅跨平台(windows 7+、Mac 和
Linux),而且丰富利用 Electron 多进度任务处理等成效,使其性能非凡。

落地页:https://xcel.aotu.io/ ✨✨✨
品种地址:https://github.com/o2team/xcel ✨✨✨

Vue笔记六:Vue项目标属性优化之路

本身多年来也时时面试外包同事。面试的时候,总会有个问题,“你说一下性能优化的手法”。百分之八十的人都会说,压缩js和css之类的。分明那一个都是必须做的,而且已经根本不是重视的性能优化的关键点。如果您只会说这个,只好评释你是个过时的前端工程师。

属性优化进程中,我们需求直面的越多是DMS解析进度,服务器缓存和浏览器缓存机制。

项目背景

用户研商的定量探究和轻量级数据处理中,均需对数据开展保洁处理,以剔除相当数据,保险数据结果的信度和效度。近年来因调研数据和轻量级数据的多变性,对轻量级数据清洗往往接纳人工清洗,紧缺统一、标准的清洗流程,但对此调研和轻量级的数码往往是需求保障数据稳定性的,因而,在对数据开展保洁时最好有规范的涤荡方法。

gzip压缩

在颇具的web前端项目,静态资源中央都置身cdn上,gzip的滑坡是不行必要的,它一贯改动了js文件的尺寸,裁减两到三倍。

参考加速nginx:
开启gzip和缓存
,nginx的gzip配置很是简单,在您对号入座的域名底下,添加上面的配备,重启服务即可。gzip_comp_level的值大于2的时候并不肯定,提出设置在1或者2里边。

# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 2;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";

特点一览

服务器缓存

为了升高服务器获取数据的快慢,nginx缓存着静态资源是可怜须求的。借使是测试服务器对html应该不安装缓存,而js等静态资源条件因为文件尾部会助长一个hash值,那可以使得落到实处缓存的主宰。

location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ { 
  access_log   off; 
  expires      30d;
}
location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
  access_log   off;
  expires      24h;
}
location ~* ^.+\.(html|htm)$ {
  expires      1h;
}

思路与得以完成

据悉用研组的急需,利用 Electron 和 Vue 的特点对该工具举办开发。

浏览器缓存

浏览器缓存是经过html的头文件中的meta来决定。http-equiv是一个特地针对http的头文件,可以向浏览器传回一些可行的信息。与之相应的content,是逐一参数的变量值。

技术选型

HTTP 1.0

在HTTP1.0中通过Pragma支配页面缓存,可以安装为Pragmano-cache。在不让浏览器或中等缓存服务器缓存页面的处境下,平日设置的值为no-cache,不过那么些值不那样有限支持,常常还助长Expires置为0来落成目的。Expires可以用于设定网页的到期时间。一旦网页过期,必须到服务器上再也传输获取新的页面新闻。PS:内容必须使用GMT的光阴格式。

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">

得以完成思路

  1. 由此 js-xlsx 将 Excel 文件分析为 JSON 数据
  2. 基于筛选标准对 JSON 数据进行筛选过滤
  3. 将过滤后的 JSON 数据转换成 js-xlsx 指定的数据结构
  4. 选拔 js-xlsx 对转移后的多寡生成 Excel 文件

纸上得来终觉浅,绝知此事要躬行

HTTP 1.1

在HTTP1.1中通过Cache-Control支配页面缓存,可以安装为no-cacheprivateno-storemax-agemust-revalidate等,默认为private。

<meta http-equiv="Cache-Control" content="no-cache">

连锁技能

一旦对某项技术比较熟谙,则可略读/跳过。

Last-Modified和Etags

Last-Modified服务器端文件响应头,描述最终修改时间。当浏览器再一次进行呼吁时,会向服务器传送If-Modified-Since报头,询问时间点之后资源是否被涂改过,从而区分200和304的伸手状态码,304则采纳浏览器缓存。

Etags不一样的是,ETag是根据实体内容生成一段hash字符串,是标识资源的情状。它由服务端发生来判定文件是否有更新。

参考资料:

Electron

JS分包

眼前说的两部分都得以说是偏后端的活,要是真的在此在此之前端方面考虑,我们可能会含有入手。正因为vue的脚手架搭建的项目,webpack的布署当中就包罗了压缩js,css和html的削减。所以,当我们的单页面越做越大的动静下,首要的一步就是带有。

vue官方称gzip压缩后唯有20kb,不过你见惯司空的打包格局也有100kb,再拉长你协调的逻辑代码,全部包的体积也挺大的。直接影响首屏页面加载的频率。上边介绍一下二种含有的艺术:

Electron 是什么?

Electron 是一个得以用 JavaScript、HTML 和 CSS
构建桌面应用程序的。那几个应用程序能打包到 Mac、Windows 和 Linux
系统上运行,也能上架到 Mac 和 Windows 的 App Store。

vue,vuex和vue-router

在webpack配置文件中external设置,把那三个场用包排除那几个操作,首如若把那两个包从vendor.js分开。

末段当然要求在html标签上添加上额外cdn的link或者script。

干什么它如此重大?

司空见惯来说,每个操作系统的桌面应用都由个其余原生语言进行编辑,那意味须求3 个团体分别为该应用编写相应版本。而 Electron 则允许你用 Web
语言编写一回即可。

DLL打包

那种打包格局越发引用webpack官方的DllPluginDllReferencePlugin。DllPlugin会生成一个dll包的代码指纹manifest,管理额外的卷入。而在项目转移的历程中,DllReferencePlugin会参考manifest的内容去打包。额外生成的js文件应当被放置在vue项目标文件当中的static文件夹底下,以便于代码安排。

参考PaicFE/vue-multi中的配置文件webpack.dll.config.js的写法。

它由什么组成?

Electron 结合了 ChromiumNode.js 和用于调用操作系统本地成效的
API(如打开文件窗口、布告、图标等)。

图片 1

预加载

预加载技术(prefetch)是在用户要求前大家就将所需的资源加载已毕,不是享有浏览器都援救,首如若Chrome浏览器。

DNS prefetch
分析这几个页面须求的资源四处的域名,浏览器空闲时提前将那几个域名转化为 IP
地址,真正请求资源时就防止了上述那些进程的日子。—-HTML5
prefetch

是因为域名转换成为IP的进程是老大耗时的一个过程,DNS
prefetch可以减去那有些的年月。

<meta http-equiv='x-dns-prefetch-control' content='on'>
<link rel='dns-prefetch' href='http://g-ecx.images-amazon.com'>
<link rel='dns-prefetch' href='http://z-ecx.images-amazon.com'>
<link rel='dns-prefetch' href='http://ecx.images-amazon.com'>
<link rel='dns-prefetch' href='http://completion.amazon.com'>
<link rel='dns-prefetch' href='http://fls-na.amazon.com'>

预加载也得以对某个静态资源起到尤其的功能。

<link rel='subresource' href='libs.js'>

预渲染(pre-rendering)是以此页面会提前加载好用户即将访问的下一个页面。

<link rel='prerender' href='http://www.pagetoprerender.com'>

支付体验怎么样?

基于 Electron 的花费就像是在开发网页,而且可以无缝地 使用
Node
。或者说:在构建一个 Node 应用的还要,通过 HTML 和 CSS
构建界面。其它,你只需为一个浏览器(最新的
Chrome
)举办统筹(即无需考虑包容性等)。

vue组件keep-alive

设若您做用一个大型web的spa的时候,你有那多少个router,对应的是成百上千个页面。在页面的敏捷切换中,为了有限支撑页面加载的成效,除了缓存机制之外,vue的keep-alive组件可以帮的上忙。

它会把组件保存在浏览器内存当中,方便你火速切换。

百度的lavas品种中就在vue-router当中使用keep-alive的零件,用它包裹着router-view。使用了keep-alive的组件内的数目将会保留,“是否须要重新联合数据”可以在vue-router的钩中路由所带的参数执行判断。

多少个经过(重点)

Electron
有二种进度:『主进度』和『渲染进度』。部分模块只好在两者之一上运行,而有些则无界定。主进度越多地担任幕后角色,而渲染进度则是应用程序的一一窗口。

注:可经过义务管理器(PC)/活动监视器(Mac)查看进程的连带信息。

Promise请求

es6的里边一个风味就是原生匡助promise。在此地,我先不说异步编程里的generatoraync/await的性质。它们成效的落到实处都是根据promise。

Promise的性状在于:

那边尤其讲一下,ES6在性能优化上得以运用promise或者async/await去减弱请求时间。在过去,很多jquery的页面在调用接口请求都是一个接口等另一个接口,串行执行所有请求,最终在成就末段的回调函数,如此类推。那样的写法会直接导致“回调地狱”。即便你用vue-resource,我也review到不行多的“回调地狱”的境况。为了从根本上解决那么些问题并提升开支功用,我提出事先使用promise。(async/await不急着投入使用),考虑到还有好多同事还在全速地付出工作代码。

现在的vue-resource曾经协理promise的写法,为了更好地让技艺向后发展,我提出将pagekit/vue-resource轮换称为mzabriskie/axioswebmodules/jsonpaxios是可以而且知足服务端和浏览器端,同构的写法有助于将来将技能栈往SSR(服务端渲染)发展。jsonp本条库则是为了包容jsonp的请求要求,要求对它举办了promise的包装。

export function getJsonp(urlHost, key, data, _params) {
  return new Promise((resolve, reject) => {
    let url = urlHost + key;
    if (data) url += `?${querystring.stringify({ ...data, temp: new Date().getTime() })}`;
    const params = _params || { timeout: 15000 };
    if (!params.timeout) params.timeout = 15000;
    jsonp(url, params, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
}

Promise的选用须要防止以下的写法,

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

尽量采取链式写法,

promise.then(function(value) {
  // step1
}).then(function(value){
  // step2
}).catch(function(value){
  // failure
})

相互的操作紧即使Promise.all(),它可以将Promise操作的数组并行执行完结然后在进展串行的操作。Promise.race()则是回去并行请求中第三遍到的请求的充足结果。它们的施用可以使得地压缩数量获得的岁月。

主进程

主进度,日常是一个命名为 main.js 的文件,该文件是各种 Electron
应用的进口。它控制了选拔的生命周期(从打开到关闭)。它既能调用原生元素,也能创设新的(三个)渲染过程。其余,Node
API 是置于其中的。

图片 2

伸张阅读

转发,请注明出处。总目录前段收集器

渲染进度

渲染进度是选用的一个浏览器窗口。与主进度分歧,它能存在八个(注:一个
Electron
应用只可以存在一个主进度)并且相互独立(它也能是隐藏的)。主窗口一般被取名为
index.html。它们就像是超人的 HTML 文件,但 Electron 赋予了它们完整的
Node API。由此,那也是它与浏览器的不一样。

图片 3

把它们想象成那样

Chrome(或任何浏览器)的种种标签页(tab)及其页面,就好比 Electron
中的一个单身渲染进度。即便关闭所有标签页,Chrome 依旧留存。那好比
Electron 的主进程,能开拓新的窗口或关闭那个利用。

注:在 Chrome
浏览器中,一个标签页(tab)中的页面(即除去浏览器本身部分,如搜索框、工具栏等)就是一个渲染进程。

图片 4

相互之间通讯

由于主进度和渲染进度各自承担差距的义务,而对此急需一起完结的天职,它们必要互相通讯。IPC就为此而生,它提供了经过间的报道。但它不得不在主进度与渲染进度之间传递信息(即渲染进度之间不可能举办直接通讯)。

图片 5

汇成一句话

Electron 应用如同 Node 应用,它也依靠一个 package.json
文件。该文件定义了哪位文件作为主进程,并因此让 Electron
知道从何启动应用。然后主进程能创立渲染进度,并能使用 IPC
让双方间展开信息传递。

图片 6

时至后天,Electron
的底子部分介绍落成。该部分是按照小编此前翻译的一篇小说《Essential
Electron》
,译文可点击
这里


Vue 全家桶

该工具使用了 Vue、Vuex、Vuex-router。在工具基本定型阶段,由 1.x 升级到了
2.x。

何以选用 Vue

对于作者来说:

Vue 1.x -> Vue 2.0 的版本迁移用
vue-migration-helper
即可分析出半数以上需要改变的地方。

网上已有比比皆是有关 Vue 的科目,故在此不再赘言。至此,Vue 部分介绍落成。


js-xlsx

该库支持各个电子表格格式的剖析与变化。它由 JavaScript 完结,适用于前者和
Node。详情>>

如今协助读入的格式有(不断更新):

扶助写出的格式有:

当下该库提供的 sheet_to_json 方法能将读入的 Excel 数据转为 JSON
格式。而对此导出操作,大家需求为 js-xlsx 提供指定的 JSON 格式。

越多关于 Excel 在 JavaScript
中拍卖的学识可查阅凹凸实验室的《Node读写Excel文件探讨实践》。但该作品存在两处问题(均在
js-xlsx 实战的导出表格部分):

  1. 扭转头部时,Excel 的列音讯简单地通过 String.fromCharCode(65+j)
    生成。当列大于 26 时会出现问题。这几个题目会在末端章节中付出解决方案;
  2. 转换成 worksheet
    须要的构造处,出现逻辑性错误,并且会促成严重的特性问题。逻辑问题在此不讲述,大家看看性能问题:
    随着 ECMAScript 的不断更新,JavaScript
    变得更为强大和易用。固然如此,大家依旧要成功『物尽所用』,而不要『大材小用』,否则恐怕会得到“反效果”。那里导致性能问题的难为
    Object.assign()
    方法,该办法可以把自由多少个源对象的可枚举属性拷贝至目的对象,并赶回目的对象。由于该方式本身的达成机制,会在此案例中发生大量的冗余操作。在本案例中,单元格新闻是唯一的,所以间接通过
    forEach 为一个空对象赋值即可。进步 N
    倍性能的同时,也把逻辑性错误解决了。

原来的:

JavaScript

var result = 某数组.reduce((prev, next) => Object.assign({}, prev,
{[next.position]: {v: next.v}}), {});

1
2
var result = 某数组.reduce((prev, next) =&gt; Object.assign({}, prev, {[next.position]: {v: next.v}}), {});
 

改为:

JavaScript

var result = 某数组.forEach((v, i) => data[v.position]= {v: v.v})

1
2
var result = 某数组.forEach((v, i) =&gt; data[v.position]= {v: v.v})
 

执行是查看真理的唯一标准

在精通上述知识后,下边就谈谈在该品种进行中计算出来的技能、难点和主要

CSS、JavaScript 和 Electron 相关的学问和技巧

高亮 table 的列

Excel 单元格采取 table 标签显示。在 Excel
中,被选中的单元格会高亮相应的『行』和『列』,以提示用户。在该使用中也有做相应的拍卖,横向高亮选用
tr:hover 已毕,而纵向呢?那里所使用的一个技艺是:

假如 HTML 结构如下:

JavaScript

div.container table tr td

1
2
3
4
5
div.container
  table
    tr
      td
 

CSS 代码如下:

JavaScript

.container { overflow:hidden; } td { position: relative; }
td:hover::after { position: absolute; left: 0; right: 0; top: -1个亿px;
// 小目的完结,但是是负的😭 bottom: -1个亿px; z-index: -1; //
避免遮住自己和同列 td 的内容、border 等 }

1
2
3
4
5
6
7
8
9
10
11
.container { overflow:hidden; }
td { position: relative; }
td:hover::after {
  position: absolute;
  left: 0;
  right: 0;
  top: -1个亿px; // 小目标达成,不过是负的&#x1f62d;
  bottom: -1个亿px;
  z-index: -1; // 避免遮住自身和同列 td 的内容、border 等
}
 

斜分割线

如图:图片 7

分割线可以由此 ::after/::before 伪类元素完成一条直线,然后经过
transform:rotate();
旋转特定角度完成。但那种完毕的一个题材是:由于宽度是不定的,因而必要通过
JavaScript 运算才能获取确切的对角分割线。

从而,那里可以通过 CSS 线性渐变
linear-gradient(to top right, transparent, transparent calc(50% - .5px), #d3d6db calc(50% - .5px), #d3d6db calc(50% + .5px), transparent calc(50% + .5px))
完成。无论宽高怎么样变,依然妥妥地自适应。

Excel 的列转换

JavaScript

// 将盛传的当然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
function getCharCol(n) { let temCol = ”, s = ”, m = 0 while (n >=
0) { m = n % 26 + 1 s = String.fromCharCode(m + 64) + s n = (n – m) / 26
} return s }

1
2
3
4
5
6
7
8
9
10
11
12
13
// 将传入的自然数转换为26进制表示。映射关系:[0-25] -&gt; [A-Z]。
function getCharCol(n) {
  let temCol = ”,
    s = ”,
    m = 0
  while (n &gt;= 0) {
    m = n % 26 + 1
    s = String.fromCharCode(m + 64) + s
    n = (n – m) / 26
  }
  return s
}
 

JavaScript

// 将盛传的26进制转换为自然数。映射关系:[A-Z] ->[0-25]。
function getNumCol(s) { if (!s) return 0 let n = 0 for (let i = s.length

1
2
3
4
5
6
7
8
9
10
11
12
// 将传入的26进制转换为自然数。映射关系:[A-Z] -&gt;[0-25]。
function getNumCol(s) {
  if (!s) return 0
  let n = 0
  for (let i = s.length – 1, j = 1; i &gt;= 0; i–, j *= 26) {
    let c = s[i].toUpperCase()
    if (c &lt; ‘A’ || c &gt; ‘Z’) return 0
    n += (c.charCodeAt() – 64) * j
  }
  return n – 1
}
 

为 DOM 的 File 对象扩充了 path 属性

Electron 为 File 对象额外增了 path
属性,该属性可获取文件在文件系统上的诚实路径。因而,你可以运用 Node
专横跋扈。应用场景有:拖拽文件后,通过 Node 提供的 File API
读取文件等。

支撑周边的编纂作用,如粘贴和复制

Electron 应用在 MacOS
中默许不援救『复制』『粘贴』等广泛编辑成效,因而需要为 MacOS
显式地安装复制粘贴等编制作用的菜单栏,并为此设置相应的急忙键。

JavaScript

// darwin 就是 MacOS if (process.platform === ‘darwin’) { var template =
[{ label: ‘FromScratch’, submenu: [{ label: ‘Quit’, accelerator:
‘CmdOrCtrl+Q’, click: function() { app.quit(); } }] }, { label: ‘Edit’,
submenu: [{ label: ‘Undo’, accelerator: ‘CmdOrCtrl+Z’, selector:
‘undo:’ }, { label: ‘Redo’, accelerator: ‘Shift+CmdOrCtrl+Z’, selector:
‘redo:’ }, { type: ‘separator’ }, { label: ‘Cut’, accelerator:
‘CmdOrCtrl+X’, selector: ‘cut:’ }, { label: ‘Copy’, accelerator:
‘CmdOrCtrl+C’, selector: ‘copy:’ }, { label: ‘Paste’, accelerator:
‘CmdOrCtrl+V’, selector: ‘paste:’ }, { label: ‘Select All’, accelerator:
‘CmdOrCtrl+A’, selector: ‘selectAll:’ }] }]; var osxMenu =
menu.buildFromTemplate(template); menu.setApplicationMenu(osxMenu); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// darwin 就是 MacOS
if (process.platform === ‘darwin’) {
    var template = [{
      label: ‘FromScratch’,
      submenu: [{
        label: ‘Quit’,
        accelerator: ‘CmdOrCtrl+Q’,
        click: function() { app.quit(); }
      }]
    }, {
      label: ‘Edit’,
      submenu: [{
        label: ‘Undo’,
        accelerator: ‘CmdOrCtrl+Z’,
        selector: ‘undo:’
      }, {
        label: ‘Redo’,
        accelerator: ‘Shift+CmdOrCtrl+Z’,
        selector: ‘redo:’
      }, {
        type: ‘separator’
      }, {
        label: ‘Cut’,
        accelerator: ‘CmdOrCtrl+X’,
        selector: ‘cut:’
      }, {
        label: ‘Copy’,
        accelerator: ‘CmdOrCtrl+C’,
        selector: ‘copy:’
      }, {
        label: ‘Paste’,
        accelerator: ‘CmdOrCtrl+V’,
        selector: ‘paste:’
      }, {
        label: ‘Select All’,
        accelerator: ‘CmdOrCtrl+A’,
        selector: ‘selectAll:’
      }]
    }];
    var osxMenu = menu.buildFromTemplate(template);
    menu.setApplicationMenu(osxMenu);
}
 

更接近原生应用

Electron
的一个瑕疵是:即使你的选拔是一个简便的时钟,但它也不得不包罗完整的基础设备(如
Chromium、Node
等)。由此,一般意况下,打包后的主次至少会高达几十兆(依据系统项目举行转变)。当你的应用越繁杂,就越可以忽略文件体积问题。

众目睽睽,页面的渲染难免会导致『白屏』,而且那里运用了 Vue
那类框架,处境就更是不好了。此外,Electron
应用也幸免不了『先开辟浏览器,再渲染页面』的手续。下边提供二种方法来减轻这种处境,以让程序更贴近原生应用。

  1. 指定 BrowserWindow 的背景颜色;
  2. 先隐藏窗口,直到页面加载后再突显;
  3. 封存窗口的尺寸和地点,以让程序下次被打开时,依旧保存的等同大小和产出在同样的职责上。

对于第一点,若使用的背景不是纯白(#fff)的,那么可指定窗口的背景颜色与其同一,以避免渲染后的急转直下。

JavaScript

mainWindow = new BrowserWindow({ title: ‘XCel’, backgroundColor:
‘#f5f5f5’, };

1
2
3
4
5
mainWindow = new BrowserWindow({
    title: ‘XCel’,
    backgroundColor: ‘#f5f5f5’,
};
 

对于第二点,由于 Electron
本质是一个浏览器,须求加载非网页部分的资源。因而,大家可以先隐藏窗口。

JavaScript

var mainWindow = new BrowserWindow({ title: ‘ElectronApp’, show: false,
};

1
2
3
4
5
var mainWindow = new BrowserWindow({
    title: ‘ElectronApp’,
    show: false,
};
 

等到渲染进度始起渲染页面的那一刻,在 ready-to-show
的回调函数中浮现窗口。

JavaScript

mainWindow.on(‘ready-to-show’, function() { mainWindow.show();
mainWindow.focus(); });

1
2
3
4
5
mainWindow.on(‘ready-to-show’, function() {
    mainWindow.show();
    mainWindow.focus();
});
 

对于第三点,小编并从未得以完结,原因如下:

  1. 用户一般是基于当下的动静对先后的尺寸和地点展开调整,即视景况而定。
  2. 以上是本身个人臆测,首借使自我懒。

其完结方式,可参看《4 must-know tips for building cross platform
Electron
apps》

怎么在渲染进度调用原生弹框?

在渲染进度中调用原本专属于主进度中的 API (如弹框)的章程有三种:

  1. IPC 通讯模块:先在主进度通过 ipcMain 进行监听,然后在渲染进度经过
    ipcRenderer 进行接触;
  2. remote 模块:该模块为渲染进度和主进度之间提供了长足的杂志发表格局。

对于第二种格局,在渲染进程中,运行以下代码即可:

JavaScript

const remote = require(‘electron’).remote remote.dialog.showMessageBox({
type: ‘question’, buttons: [‘不报告你’, ‘没有梦想’], defaultId: 0,
title: ‘XCel’, message: ‘你的期待是何等?’ }

1
2
3
4
5
6
7
8
9
10
const remote = require(‘electron’).remote
 
remote.dialog.showMessageBox({
  type: ‘question’,
  buttons: [‘不告诉你’, ‘没有梦想’],
  defaultId: 0,
  title: ‘XCel’,
  message: ‘你的梦想是什么?’
}
 

自动更新

如若 Electron
应用尚未提供自动更新功用,那么就意味着用户想体验新开发的成效或用上修复
Bug
后的新本子,只能够靠用户自己积极地去官网下载,那的确是不佳的体会。Electron
提供的 autoUpdater
模块可完结自动更新作用,该模块提供了第三方框架
Squirrel 的接口,但 Electron 方今只内置了
Squirrel.Mac,且它与
Squirrel.Windows(须求至极引入)的处理格局也分歧等(在客户端与服务器端两下边)。因而只要对该模块不领悟,处理起来会相对相比繁琐。具体可以参照作者的另一篇译文《Electron
自动更新的总体教程(Windows 和
OSX)》

时下 Electron 的 autoUpdater 模块不协助 Linux 系统。

别的,XCel 方今并从未利用 autoUpdater 模块落成自动更新效率,而是采纳Electron 的
DownloadItem
模块落成,而服务器端则应用了 Nuts

为 Electron 应用生成 Windows 安装包

通过 electron-builder 可一贯生成常见的
MacOS 安装包,但它生成的 Windows 的安装包却略显简洁(默许选项时)。

图片 8
Mac 常见的装置格局,将“左边的应用图标”拖拽到“左侧的 Applications”即可

因此 electron-builder 生成的 Windows 安装包与大家在 Windows
上广泛的软件安装界面不太雷同,它从不设置向导和点击“下一步”的按钮,只有一个设置时的
gif 动画(默许的 gif 动画如下图,当然你也得以指定特定的 gif
动画),因而也就关门了用户挑选安装路径等义务。

图片 9
Windows 安装时 默许突显的 gif
动画

假定你想为打包后的 Electron 应用(即由此electron-packager/electron-builder
生成的,可直接运行的先后目录)生成拥有点击“下一步”按钮和可让用户指定安装路径的大面积安装包,可以尝试
NSIS 程序,具体可看这篇教程 《[教學]只要10分鐘學會使用 NSIS
包裝您的桌面軟體–安裝程式打包。完全免費。》

注:electron-builder
也提供了变更安装包的配备项,实际查看>>

NSIS(Nullsoft Scriptable Install System)是一个开源的 Windows
系统下安装程序制作程序。它提供了安装、卸载、系统安装、文件解压缩等效率。正如其名字所讲述的那样,NSIS
是透过它的脚本语言来叙述安装程序的表现和逻辑的。NSIS
的脚本语言和广泛的编程语言有近似的构造和语法,但它是为安装程序那类应用所安插的。

迄今,CSS、JavaScript 和 Electron 相关的文化和技艺部分演说完成。


特性优化

下边谈谈『性能优化』,这一部分涉嫌到运转效能内存占用量
注:以下内容均基于 Excel 样例文件(数据量为:1913 行 x 180
列)得出的下结论。

实践效能和渲染的优化

Vue 性能真的好?

Vue 一向标榜着自己性能卓越,但当数据量上涨到一定量级时(如 1913 x 180 ≈
34 万个数据单元),会出现严重的特性问题(未做相应优化的前提下)。

如间接通过列表渲染 v-for 渲染数据时,会招致程序卡死。
答:通过查看有关资料可得, v-for
在初次渲染时,要求对每个子项举办早先化(如数据绑定等操作,以便拥有更快的翻新速度),那对于数据量较大时,无疑会促成深重的习性问题。

立马,我想到了三种缓解思路:

  1. Vue 是数额驱动视图的,对数据分段 push,即将一个高大的天职务割为 N
    份。
  2. 投机拼接 HTML 字符串,再经过 innerHTML 三次性插入。

末尾,我选择了第二条,理由是:

  1. 属性最佳,因为老是执行多少过滤时,Vue 都要拓展 diff,性能不佳。
  2. 更切合当下利用的急需:纯展现且无需动画过渡等。
  3. 心想事成更简短

将原本繁重的 DOM 操作(Vue)转换为 JavaScript
的拼接字符串后,性能得到了很大升级(不会导致程序卡死而渲染不出视图)。这种优化措施难道不就是
Vue、React
等框架解决的题目之一吧?只可是框架考虑的场所更广,有些地点需求大家温馨根据实际情状进行优化而已。

在浏览器当中,JavaScript 的演算在当代的引擎中那一个快,但 DOM
本身是不行缓慢的事物。当您调用原生 DOM API 的时候,浏览器须求在
JavaScript 引擎的语境下去接触原生的 DOM
的贯彻,这么些历程有一定的习性损耗。所以,本质的勘察是,要把费用时间的操作尽量放在纯粹的持筹握算中去做,保障最后统计出来的内需实际接触实际
DOM 的操作是最少的。 —— 《Vue
2.0——渐进式前端解决方案》

自然,由于 JavaScript
天生单线程,即便举办数速度再快,也难免会导致页面有短暂的日子不容用户的输入。此时可通过
Web Worker 或其余方法解决,那也将是我们三番几次讲到的题目。

也有网友提供了优化多量列表的艺术:https://clusterize.js.org/。但在本案例中笔者并没有动用此形式。

强大的 GPU 加速

将拼接的字符串插入 DOM
后,出现了其余一个问题:滚动会很卡。猜测那是渲染问题,毕竟 34
万个单元格同时存在于界面中。

添加 transform: translate3d(0, 0, 0) / translateZ(0) 属性启动 GPU
渲染,即可解决那一个渲染性能问题。再次惊叹该属性的有力。

新生,考虑到用户并不需求查看所有多少,只需出示部分数据让用户展开参考即可。大家对此只渲染前
30/50 行数据。那样即可提高用户体验,也能更为优化性能。

回想关闭 Vuex 的从严形式

其它,由于投机学艺不精和疏于,忘记在生育条件关闭 Vuex
的『严酷格局』。

Vuex 的严厉情势要在生养环境中关闭,否则会对 state 树举办一个深观察(deep
watch),发生不要求的性能损耗。也许在数据量少时,不会小心到这么些问题。

卷土重来当时的场景:导入 Excel 数据后,再进行相互(涉及 Vuex
的读写操作),要求等几秒才会响应,而一向通过纯 DOM
监听的轩然大波则无此问题。因而,判断出是 Vuex 问题。

JavaScript

const store = new Vuex.Store({ // … strict: process.env.NODE_ENV !==
‘production’ })

1
2
3
4
5
const store = new Vuex.Store({
  // …
  strict: process.env.NODE_ENV !== ‘production’
})
 

多进程!!!

前边说道,JavaScript
天生单线程,固然再快,对于数据量较大时,也会产出拒绝响应的题目。因此需求Web Worker 或类似的方案去化解。

在此地我不拔取 Web worker 的原因有如下几点:

  1. 有其余更好的代表方案:一个主进度能成立多个渲染进度,通过 IPC
    即可进展多少交互;
  2. Electron 不协理 Web
    Worker!(当然,可能会在新本子帮衬,最新音讯请关心官方)

Electron 作者在 2014.11.7 在《state of web worker support?》 issue
中復苏了以下这一段:

Node integration doesn’t work in web workers, and there is no plan to
do. Workers in Chromium are implemented by starting a new thread, and
Node is not thread safe. Back in past we had tried to add node
integration to web workers in Atom, but it crashed too easily so we
gave up on it.

于是,大家最终选取了创立一个新的渲染进度 background process
进行处理多少。由 Electron 章节可知,每个 Electron
渲染进度是独立的,由此它们不会相互影响。但那也拉动了一个题材:它们不可以相互通讯?

错!上面有 3 种格局开展报导:

  1. Storage
    API
    :对某个标签页的
    localStorage/sessionStorage 对象开展增删改时,其余标签页能通过
    window.storage 事件监听到。
  2. IndexedDB:IndexedDB
    是一个为了可以在客户端存储可观数额的结构化数据,并且在那么些数据上采取索引进行高性能检索的
    API。
  3. 经过主进度作为中转站:设主界面的渲染进度是 A,background process
    是 B,那么 A 先将 Excel 数据传递到主进度,然后主进程再倒车到 B。B
    处理完后再原路再次来到,具体如下图。当然,也能够将数据存储在主进度中,然后在多少个渲染进程中选择remote 模块来访问它。

该工具接纳了第二种艺术的第一种情景:
图片 10

1、主页面渲染进度 A 的代码如下:

JavaScript

//① ipcRenderer.send(‘filter-start’, { filterTagList:
this.filterTagList, filterWay: this.filterWay, curActiveSheetName:
this.activeSheet.name }) // ⑥ 在某处接收 filter-response 事件
ipcRenderer.on(“filter-response”, (arg) => { // 拿遍地理数据 })

1
2
3
4
5
6
7
8
9
10
11
12
//①
ipcRenderer.send(‘filter-start’, {
    filterTagList: this.filterTagList,
    filterWay: this.filterWay,
    curActiveSheetName: this.activeSheet.name
})
 
// ⑥ 在某处接收 filter-response 事件
ipcRenderer.on("filter-response", (arg) =&gt; {
    // 得到处理数据
})
 

2、作为中转站的主进度的代码如下:

JavaScript

//② ipcMain.on(“filter-start”, (event, arg) => { // webContents
用于渲染和操纵 web page
backgroundWindow.webContents.send(“filter-start”, arg) }) // ⑤
用于收纳再次回到事件 ipcMain.on(“filter-response”, (event, arg) => {
mainWindow.webContents.send(“filter-response”, arg) })

1
2
3
4
5
6
7
8
9
10
11
//②
ipcMain.on("filter-start", (event, arg) =&gt; {
    // webContents 用于渲染和控制 web page
    backgroundWindow.webContents.send("filter-start", arg)
})
 
// ⑤ 用于接收返回事件
ipcMain.on("filter-response", (event, arg) =&gt; {
    mainWindow.webContents.send("filter-response", arg)
})
 

3、处理繁重数据的 background process 渲染进度 B 的代码如下:

JavaScript

// ③ ipcRenderer.on(‘filter-start’, (event, arg) => { // 举行演算 …
// ④ 运算完结后,再通过 IPC 原路重返。主进度和渲染进程 A
也要建立相应的监听事件 ipcRenderer.send(‘filter-response’, { filRow:
tempFilRow }) })

1
2
3
4
5
6
7
8
9
10
11
// ③
ipcRenderer.on(‘filter-start’, (event, arg) =&gt; {
    // 进行运算
    …
 
    // ④ 运算完毕后,再通过 IPC 原路返回。主进程和渲染进程 A 也要建立相应的监听事件
    ipcRenderer.send(‘filter-response’, {
        filRow: tempFilRow
    })
})
 

迄今,大家将『读取文件』、『过滤数据』和『导出文件』三大耗时的数额操作均转移到了
background process 中处理。

那里,大家只开创了一个
background process,借使想要做得更极致,大家可以新建『CPU 线程数- 1 』
个的 background process
同时对数码举行拍卖,然后在主进程对拍卖后数据进行拼接,最后再将拼接后的数据重回到主页面的渲染进度。那样就可以尽量榨干
CPU 了。当然,在此作者不会开展这一个优化。

毫不为了优化而优化,否则惜指失掌。 —— 某网友

内存占有量过大

缓解了执行作用和渲染问题后,发现也存在内存占用量过大的问题。当时预计是以下多少个原因:

  1. 三大耗时操作均放置在 background process
    处理。在简报传递数据的过程中,由于不是共享内存(因为 IPC 是按照Socket
    的),导致出现多份数据副本(在写那篇作品时才有了那相对方便的答案)。
  2. Vuex
    是以一个大局单例的格局开展田间管理,但它会是不是对数码做了一些封装,而导致性能的用度呢?
  3. 是因为 JavaScript
    方今不拥有积极回收资源的力量,所以只能积极对闲置对象设置为
    null,然后等待 GC 回收。

鉴于 Chromium 拔取多进程架构,因而会涉嫌到进程间通信问题。Browser
进度在启动 Render 进度的历程中会建立一个以 UNIX Socket 为根基的 IPC
通道。有了 IPC 通道之后,接下去 Browser 进度与 Render
进度就以新闻的方式展开通信。大家将那种音讯称为 IPC
消息,以界别于线程音讯循环中的信息。
——《Chromium的IPC信息发送、接收和分发机制分析》

概念:为了简单了解,以下『Excel 数据』均指 Excel 的满贯得力单元格转为
JSON 格式后的多寡。

最简单处理的的确是第三点,手动将不再需求的变量及时安装为
null,但效益并不明显。

新生,通过操作系统的『活动监视器』(Windows
上是天职管理器)对该工具的每阶段(打开时、导入文本时、筛选时和导出时)进行不难的内存分析,得到以下报告:

—————- S:报告分割线 —————-
经观察,主要耗内存的是页面渲染进度。上面通过截图申明:
PID 15243 是主进度
PID 15246 是页面渲染进度
PID 15248 是 background 渲染进程

a、第一次开行程序时(第 4 行是主进度;第 1 行是页面渲染进程;第 3 行是
background 渲染进度 )

图片 11

b、导入文本(第 5 行是主进度;第 2 行是页面渲染进度;第 4 行是
background 渲染进程 )
图片 12

c、筛选数据(第 4 行是主进度;第 1 行是页面渲染进度;第 3 行是
background 渲染进程 )
图片 13

出于 JavaScript 近期不抱有积极回收资源的功效,所以不得不积极将指标设置为
null,然后等待 GC 回收。

从而,经过一段时间等待后,内存占用如下:
d、一段时间后(第 4 行是主进程;第 1 行是页面渲染进度;第 3 行是
background 渲染进程 )
图片 14

由上述可得,页面渲染进程由于页面元素和 Vue 等 UI
相关资源是永恒的,占用内存较大且不可以回收。主进度占用资源也无法得到很好释放,暂时不亮堂原委,而
background 渲染进程则较好地放走资源。

—————- E:报告分割线 —————-

根据报告,开端得出的下结论是 Vue 和简报时占用资源较大。

据悉该工具的实在利用场景:Excel
数据只在『导入』和『过滤后』多少个等级须要出示,而且突显的是透过
JavaScript 拼接的 HTML 字符串所组成的 DOM 而已。由此将表格数据放置在
Vuex 中,有点滥用资源的多疑。

另外,在 background process 中也有存有一份 Excel
数据副本。因而,索性只在 background process 存储一份 Excel
数据,然后每当数据变动时,通过 IPC 让 background process 重回拼接好的
HTML
字符串即可。那样一来,内存占有量马上跌落许多。其余,那也是一个一举多得的优化:

  1. 字符串拼接操作也转移到了
    background process,页面渲染进程进一步压缩耗时的操作;
  2. 内存占有量大大减小,响应速度也得到了晋级。

实则,那也有点像 Vuex 的『全局单例情势管理』,一份数据就好。

本来,对于 Excel 的着力新闻,如行列数、SheetName、标题组等均如故保留在
Vuex。

优化后的内存占有量如下图。与上述报告的第三张图比较(同一等级),内存占有量下降了
44.419%: 图片 15
此外,对于不须求响应的多寡,可通过 Object.freeze()
冻结起来。那也是一种优化手段。但该工具近期并没有运用到。

时至今天,优化部分也讲演达成了!


该工具方今是开源的,欢迎我们使用或引进给用研组等有亟待的人。

你们的反映(可提交 issues /
pull
request
)能让那么些工具在选择和功效上不断完善。

最后,感谢 LV
在成品设计、界面设计和优化上的强力协理。全文完!

打赏支持我写出越来越多好文章,谢谢!


打赏小编

打赏帮衬我写出更多好作品,谢谢!

任选一种支付格局

图片 16
图片 17

1 赞 2 收藏
评论

关于作者:刘健超-J.c

图片 18

前端,在路上…http://jchehe.github.io
个人主页
·
我的小说
·
19
·
    

图片 19

相关文章

发表评论

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

网站地图xml地图