Blog
Blog copied to clipboard
Indeed insight in Full Stack
前端与算法
## 前言 最近举行了一场盛大的前端算法大比拼,题目从真实业务场景中抽取出来,童鞋们纷纷摩拳擦掌展示自己算法基本功。题目如下:  真实场景里面,有7M左右的JSON数据需要统一更新费率,据说一开始处理这堆数据一次就得耗费20+秒。在浏览器场景下,这意味着这段时间UI渲染被阻塞,用户交互完全无响应。最后经过调整的算法,也需要1秒左右的执行时间,非常影响用户体验。 略懂浏览器动画的童鞋都知道,在浏览器一帧里面`layout`、合成、渲染占据了不少CPU时间,真实交给js进行运行的时间只有不到10ms。在如此大数据量处理的场景下要保持丝般顺滑的用户体验,算法必不可少,可见算法对于前端依旧非常重要。 鄙人也参加了大比拼,分享一下自己的小小心得,总结一下如何将7M数据处理从1000ms降到10ms以下。 ## 基本思路 从题目的数据结构可以看到,这是一个多叉树,第一时间联想到的是树的遍历。 借鉴函数式编程思想,树的处理只需要三个步骤: 1. 函数递归遍历 2. 使用processor处理每一个树节点 3. 葛优躺... Talk is cheap, show me the code. 树的遍历: ``` javascript function trav(tree, processor){...
原文:[RIP CommonsChunkPlugin](https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693) webpack 4 移除 `CommonsChunkPlugin`,取而代之的是两个新的配置项(optimization.splitChunks 和 optimization.runtimeChunk),下面介绍一下用法和机制。 ## 默认方式 webpack模式模式现在已经做了一些通用性优化,适用于多数使用者。 需要注意的是:默认模式只影响按需(on-demand)加载的代码块(chunk),因为改变初始代码块会影响声明在HTML的`script`标签。如果可以处理好这些(比如,从打包状态里面读取并动态生成script标签到HTML),你可以通过设置`optimization.splitChunks.chunks: "all"`,应用这些优化模式到初始代码块(initial chunk)。 webpack根据下述条件自动进行代码块分割: * 新代码块可以被共享引用,OR这些模块都是来自`node_modules`文件夹里面 * 新代码块大于30kb(min+gziped之前的体积) * 按需加载的代码块,最大数量应该小于或者等于5 * 初始加载的代码块,最大数量应该小于或等于3 为了满足后面两个条件,webpack有可能受限于包的最大数量值,生成的代码体积往上增加。 我们来看一下一些例子: ### Example 1 ```js //...
 ### 前言 Hyperapp是一个轻量级视图库,拥有完备的界面渲染、以及视图数据交互更新能力。专注于视图渲染的核心部分,使得它的体积非常轻巧,也使得它具备"无限可能"。在设计上并无涉及太多复杂场景,尤为适用于轻量级的移动开发场景。 ### 特点 #### 1. 外置Action管理 `Hyperapp`仅关心状态渲染、调度生成后actions对象。在状态管理上,我们可以自主使用`flux`、`redux`,甚至无需使用任何状态管理库。 #### 2. 外置渲染模板(语法) `Hyperapp`提供`vnode`生成辅助函数,但并不限制渲染模板的选择,我们可以自由选择类似`JSX`,甚至类`VUE`的模板语言。 #### 3. 单向数据流原则 在`Hyperapp`初始渲染之后,触发视图更新的唯一方式是,通过调用`action`变更状态,从而触发视图更新。这使得我们可以建立易于跟踪、健壮、可维性强的应用。 ### 大话Hyperapp源码 详细的分析,可以在[源码注释仓库](https://github.com/yesvods/hyperapp/blob/master/src/index.js)下看到,里面有`hyperapp`各个源码重要细节的分析。下面来介绍一下`hyperapp`源码有意思的地方: #### 1. 麻雀虽小,五脏俱全 专注于视图渲染&数据交互更新,在实现上也是恰到好处地实现这些功能。具备内置状态驱动的视图更新引擎、标准`VNode`四板斧、`DOM-diff`机制。在这点来说,`hyperapp`处于新生期,需要具备完善的生态,才可以发挥出强大的内核能力。 VNode四板斧: ```js // 基本的HTML标签都可以被抽象成如下形式: //...
我们通过分析主流浏览器Chrome,来了解一个脚本从无到有再到运行作用,到底经历了什么。以下将会用`lodash`为作为例子,浏览器的脚本生命周期。 ### HTML解析 在浏览器中,在HTML解析过程中,当解析到带有`src`的`script`标签,便会即刻调度网络模块队列,网络模块在有空余请求线程时,会即刻执行队列的请求。 举个栗子: ``` console.log("Hello Tmall") ``` 浏览器会优先发起`lodash.js`的请求,而后执行`console.log`脚本。  ### 接收脚本数据 了解TCP/IP协议的童鞋都知道,网络服务器存在`慢启动`机制,数据包会以递增方式发送至客户端(浏览器),一个500KB左右的`lodash.js`会被以十多个包送达:  也许有童鞋已经发现,为了极致的性能,Chrome在接收到首个数据包时,已经开始脚本的解析工作。 ### 解析&编译&执行 随后,脚本的一系列连贯的生命周期,最后会发出一个load`事件`,表明脚本已就绪。  ### 小结 总体看起来,脚本的确会阻塞后续HTML解析,一个完整生命周期大概是酱紫的。  ### MultiScript 那么,当多个脚本并行加载,时间序列是怎样的呢:**脚本下载会并行发起,接收数据交替进行。而解析、编译、执行,会根据HTML声明顺序,串行进行** 以`react` `react-dom` `lodash`并行加载为例,整个时序是酱紫的:...
也许最近已经听说Chrome59将支持`headless`模式,`PhantomJS`核心开发者[Vitaly](https://github.com/Vitallium)表示自己将会失业了。 ### Headless模式解决了什么问题 3年前,无头浏览器`PhantomJS`已经如火如荼出现了,紧跟着`NightmareJS`也成为一名巨星。无头浏览器带来巨大便利性:页面爬虫、自动化测试、WebAutomation... ### 为啥Chrome又插了一脚 用过PhantomJS的都知道,它的环境是运行在一个封闭的沙盒里面,在环境内外完全不可通信,包括API、变量、全局方法调用等。一个之前写的[微信页面爬虫](https://github.com/yesvods/page-spider),实现内外通信的方式极其Hack,为了达到目的,不择手段,令人发指,看过的哥们都会蛋疼。 So, 很自然的,Chrome59版支持的特性,全部可以利用,简直不要太爽: * ES2017 * ServiceWork(PWA测试随便耍) * 无沙盒环境 * 无痛通讯&API调用 * 无与伦比的速度 * ... ### 技能树启动点 为了点亮技能树,我们需要以下配置: * Chrome Canary (What!还没装?[传送门](https://www.google.com/chrome/browser/canary.html)) * NodeJS...
### 前言 前端框架时代,为开发体验、效率与页面性能带来,非常大的革命。大家纷纷拿起一系列打包工具(webpack/parcel etc.),配合一系列加载器快速搭建起一个 SPA 页面。 SPA 应用带来的好处非常明显; * 提升页面切换体验 * 降低切换时间 * 易于部署&前后端分离 但是也带来一系列性能问题: * 初始加载脚本较大 * 首屏空白时间较长 * 页面返回时,数据被动重新拉取 这些问题是使用 SPA 模式不可避免的,通过了解 SPA 加载运行过程,可以逐渐看清楚引起性能问题的根本原因,通过精细化应用加载,来解决这些问题。 ### SPA 之殇 ####...
在大家的认知里,JSONP,往往是另外一种异步请求的方式,其主要优点是支持跨域数据请求。因此,JSONP往往是将一个Script节点动态插入document,随后浏览器会自动发起一个远程请求。 除了上述单一用法外,在PCWeb,JSONP具有非常巨大的性能&工程化价值。 ### 1.异步JSONP 通过【图说舌尖上的脚本】与【同步vs异步加载】了解到,PCWeb受限于插件环境,异步机制变得非常不吃香。异步发起的请求,无论是JSONP等资源加载,抑或XHR(fetch),都会被标记为低优先级。 * 同步插件脚本加载完才能发起请求 * 在主进程的编译与执行前,会被插件脚本抢占。 我们来看一下,发起6个异步JSONP是怎样的情况: ``` function appendScript(src){ var s = document.createElement('script') s.src = src document.body.appendChild(s) } for(let i=0;i
同步与异步加载,往往是指网络资源,像图片、样式、脚本等。本文探索在PCWeb下,同步&异步性能差距到底有多少?为何移动端的优秀方案到PCWeb,会造成性能问题? ### 同步加载 我们只声明单一的静态脚本资源。 ``` ```  ### 异步加载 使用简单脚本发起资源请求。 ``` var s = document.createElement('script') s.src="./react.js" document.body.appendChild(s) ```  ### 结果分析 看到结果很惊诧,仅仅是一个不一样的加载方式,导致的是40ms与400ms的差异。那么,这段时间里面,浏览器到底去干啥了。  通过图示,说明了几个问题 * HTML脚本执行优先于次于大多数插件脚本 * 异步发起的请求,属于低优先级任务 * 低优先级任务,容易被其他脚本执行而阻塞...
 ## 前言 前一篇文章介绍了webpack以及安装方法,本文将会介绍webpack在单页面应用程序(Single Page Application)与多页面站点不同场合的用法。 ## 输入与输出 跟其他模块加载器类似,webpack也是需要配置一个入口文件,比如是entry.js 有几种配置方式,下面来介绍一下直接把入口文件写在配置文件 webpack.config.js: ``` module.exports = { entry: { "entry":"./entry.js" }, output: { path: "build" filename: "bundle.js" } } ``` 通过命令行 ```...
## 前言 事情经过是这样的,某个阳光明媚的晚上,跟大多数人一样,在MacBook前静静地写着redux/flux“优美”的诗句。剧情急转直下: ``` └── constants ├── comA.js ├── comB.js ├── comC.js ├── comD.js ├── comE.js └── index.js ``` index.js看起来是这样的: ``` Javascript import * from './a'; import * from './b';...