菜单

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

2019年1月15日 - CSS/CSS3

干什么选用 Vue

对于笔者来说:

Vue 1.x -> Vue 2.0 的本子迁移用
vue-migration-helper
即可分析出大部分亟待变更的地点。

网上已有这些有关 Vue 的科目,故在此不再赘言。至此,Vue 部分介绍完毕。


HTTP 1.1

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

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

斜分割线

如图:图片 1

分割线可以经过 ::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))
实现。无论宽高怎样变,如故妥妥地自适应。

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]\.";

品类背景

用户琢磨的定量啄磨和轻量级数据处理中,均需对数据开展保洁处理,以剔除分外数据,保证数据结果的信度和效度。近来因调研数据和轻量级数据的多变性,对轻量级数据清洗往往使用人工清洗,缺乏统一、标准的清洗流程,但对此调研和轻量级的数据往往是内需保证数据稳定性的,因而,在对数码开展保洁时最好有标准的保洁方法。

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

自身近期也平日面试外包同事。面试的时候,总会有个问题,“你说一下特性优化的手段”。百分之八十的人都会说,压缩js和css之类的。分明那些都是必须做的,而且已经根本不是重要的属性优化的关键点。如果您只会说这个,只可以证实你是个过时的前端工程师。

属性优化过程中,大家需要面对的更多是DMS解析过程,服务器缓存和浏览器缓存机制。

贯彻思路

  1. 由此 js-xlsx 将 Excel 文件分析为 JSON 数据
  2. 遵照筛选标准对 JSON 数据举行筛选过滤
  3. 将过滤后的 JSON 数据转换成 js-xlsx 指定的数据结构
  4. 应用 js-xlsx 对转移后的多少生成 Excel 文件

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

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">

记念关闭 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’
})
 

vue组件keep-alive

倘使你做用一个重型web的spa的时候,你有许多router,对应的是诸四个页面。在页面的敏捷切换中,为了确保页面加载的效用,除了缓存机制之外,vue的keep-alive组件可以帮的上忙。

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

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

Vue 全家桶

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

服务器缓存

为了增强服务器获取数据的进度,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;
}

打赏援助我写出更多好小说,谢谢!

任选一种支付模式

图片 2
图片 3

1 赞 2 收藏
评论

vue,vuex和vue-router

在webpack配置文件中external设置,把这多少个场用包排除这些操作,紧即便把这两个包从vendor.js分开。

说到底当然需要在html标签上添加上额外cdn的link或者script。

渲染进程

渲染进程是利用的一个浏览器窗口。与主进程不同,它能存在五个(注:一个
Electron
应用只好存在一个主进程)并且互动独立(它也能是隐藏的)。主窗口一般被命名为
index.html。它们就像超人的 HTML 文件,但 Electron 赋予了它们完整的
Node API。因而,这也是它与浏览器的分别。

图片 4

Last-Modified和Etags

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

Etags不同的是,ETag是基于实体内容生成一段hash字符串,是标识资源的情事。它由服务端暴发来判断文件是否有革新。

参考资料:

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

实践是印证真理的唯一标准

在知晓上述知识后,下边就谈谈在该品种举行中总结出来的技术、难点和严重性

JS分包

前方说的两有些都足以说是偏后端的活,假诺真的在此以前端方面考虑,我们恐怕会含有入手。正因为vue的脚手架搭建的品类,webpack的安排当中就富含了压缩js,css和html的减弱。所以,当我们的单页面越做越大的状况下,重要的一步就是包含。

vue官方称gzip压缩后只有20kb,不过你通常的打包形式也有100kb,再加上你自己的逻辑代码,全体包的体积也挺大的。直接影响首屏页面加载的功能。下边介绍一下两种含有的章程:

主进程

主进程,平时是一个命名为 main.js 的公文,该公文是每个 Electron
应用的输入。它决定了拔取的生命周期(从打开到关门)。它既能调用原生元素,也能创制新的(几个)渲染进程。此外,Node
API 是松开其中的。

图片 5

DLL打包

这种打包形式特别引用webpack官方的DllPluginDllReferencePlugin。DllPlugin会生成一个dll包的代码指纹manifest,管理额外的卷入。而在项目转移的长河中,DllReferencePlugin会参考manifest的情节去打包。额外生成的js文件应当被放置在vue项目的文件当中的static文件夹底下,以便于代码部署。

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

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

图片 6

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

图片 7

推而广之阅读

转载,请注脚出处。总目录前段收集器

性能优化

下边谈谈『性能优化』,这有些关系到运转功能内存占用量
注:以下内容均基于 Excel 样例文件(数据量为:1913 行 x 180
列)得出的定论。

浏览器缓存

浏览器缓存是透过html的头文件中的meta来支配。http-equiv是一个特别针对http的头文件,可以向浏览器传回一些实用的音信。与之对应的content,是逐一参数的变量值。

哪些在渲染进程调用原生弹框?

在渲染进程中调用原本专属于主进程中的 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: ‘你的梦想是什么?’
}
 

预加载

预加载技术(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
应用尚未提供自动更新效率,那么就代表用户想体验新开发的功力或用上修复
Bug
后的新本子,只可以靠用户自己积极地去官网下载,这无疑是欠好的体会。Electron
提供的 autoUpdater
模块可实现自动更新效能,该模块提供了第三方框架
Squirrel 的接口,但 Electron 如今只内置了
Squirrel.Mac,且它与
Squirrel.Windows(需要卓殊引入)的处理情势也不雷同(在客户端与服务器端两上边)。因而一旦对该模块不精晓,处理起来会绝对相比麻烦。具体可以参见笔者的另一篇译文《Electron
自动更新的完整教程(Windows 和
OSX)》

眼前 Electron 的 autoUpdater 模块不协助 Linux 系统。

此外,XCel 近期并不曾运用 autoUpdater 模块实现自动更新效率,而是使用
Electron 的
DownloadItem
模块实现,而服务器端则使用了 Nuts

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()则是再次来到并行请求中首先回到的哀告的不得了结果。它们的运用可以有效地减小数量拿到的时日。

为 DOM 的 File 对象增加了 path 属性

Electron 为 File 对象额外增了 path
属性,该属性可取得文件在文件系统上的真人真事路径。由此,你可以行使 Node
为所欲为。应用场景有:拖拽文件后,通过 Node 提供的 File API
读取文件等。

支付体验如何?

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

有关技能

若果对某项技术相比熟悉,则可略读/跳过。

支撑周边的编写功效,如粘贴和复制

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);
}
 

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 ✨✨✨

Electron

汇成一句话

Electron 应用就像 Node 应用,它也依靠一个 package.json
文件。该文件定义了哪个文件作为主进程,并据此让 Electron
知道从何启动应用。然后主进程能创设渲染进程,并能使用 IPC
让相互间举办音讯传递。

图片 8

至今,Electron
的基础部分介绍完毕。该部分是遵照笔者从前翻译的一篇作品《Essential
Electron》
,译文可点击
这里


把它们想象成这么

Chrome(或其他浏览器)的每个标签页(tab)及其页面,就好比 Electron
中的一个独自渲染进程。就算关闭所有标签页,Chrome 仍然留存。那好比
Electron 的主进程,能开拓新的窗口或关闭这个动用。

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

图片 9

多进程!!!

眼前说道,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 了。当然,在此笔者不会进展这个优化。

不要为了优化而优化,否则得不偿失。 —— 某网友

互动通讯

由于主进程和渲染进程各自承担不同的天职,而对此急需一起完成的任务,它们需要互相通讯。IPC就为此而生,它提供了经过间的简报。但它只好在主进程与渲染进程之间传递信息(即渲染进程之间不能拓展间接通讯)。

图片 11

内存占有量过大

釜底抽薪了推行效能和渲染问题后,发现也存在内存占用量过大的题材。当时预计是以下几个原因:

  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 渲染进程 )

图片 12

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

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

鉴于 JavaScript 近日不持有积极回收资源的法力,所以不得不积极将目的设置为
null,然后等待 GC 回收。

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

由上述可得,页面渲染进程由于页面元素和 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%: 图片 16
此外,对于不需要响应的数目,可通过 Object.freeze()
冻结起来。这也是一种优化手段。但该工具最近并不曾使用到。

从这之后,优化部分也讲演完毕了!


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

你们的举报(可提交 issues /
pull
request
)能让那么些工具在应用和效率上不断完善。

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

打赏协助自己写出更多好小说,谢谢!


打赏作者

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/。但在本案例中笔者并没有应用此办法。

特性一览

思路与贯彻

据悉用研组的需要,利用 Electron 和 Vue 的表征对该工具举办付出。

五个过程(重点)

Electron
有二种进程:『主进程』和『渲染进程』。部分模块只可以在两岸之一上运行,而略带则无界定。主进程更多地担任幕后角色,而渲染进程则是应用程序的逐一窗口。

注:可通过任务管理器(PC)/活动监视器(Mac)查看过程的有关音讯。

为啥它如此重大?

常备来说,每个操作系统的桌面应用都由个另外原生语言举行编制,这代表需要
3 个公司分别为该采纳编写相应版本。而 Electron 则允许你用 Web
语言编写一遍即可。

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
}
 

技能选型

它由什么组成?

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

图片 17

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

强大的 GPU 加速

将拼接的字符串插入 DOM
后,出现了其它一个题材:滚动会很卡。估摸这是渲染问题,毕竟 34
万个单元格同时设有于界面中。

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

新生,考虑到用户并不需要查看所有数目,只需出示部分数据让用户举办参考即可。大家对此只渲染前
30/50 行数据。这样即可进步用户体验,也能更为优化性能。

高亮 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 等
}
 

为 Electron 应用生成 Windows 安装包

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

图片 18
Mac 常见的安装情势,将“左侧的拔取图标”拖拽到“左边的 Applications”即可

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

图片 19
Windows 安装时 默认显示的 gif
动画

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

注:electron-builder
也提供了变动安装包的配置项,切切实实查看>>

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

由来,CSS、JavaScript 和 Electron 相关的知识和技能部分演说完毕。


实施功能和渲染的优化

Electron 是什么?

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

更近乎原生应用

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》

相关文章

发表评论

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

网站地图xml地图