博文

koa vs express

koa:洋葱圈模型,中间件调用类似函数执行机制,基于es6,不包含router,view。中间件返回context
express:中间件调用不会返回上一级,基于es5,默认包含router,view。中间件返回request,response

前端首屏渲染优化

如何让用户第一时间看到他们想要浏览的网站是前端工程师必须要解决的问题。本文就介绍几种优化的方案:

将客户端请求的资源放置在CDN上,这样可以让客户端从最快的节点下载相关资源,进而减少资源下载的时间。同时可以将资源进行gzip压缩,并且请求头加上gzip,可以让请求的资源文件大小减少50%左右。将已获得的静态资源(app shell,图片,css等)使用cache进行缓存,之后的访问直接从本地获取资源,方便下次加载。使用prefetch,preload预加载资源,并在css与js标签上加上async或defer属性实现异步加载。在webpack中可以使用script-ext-html-webpack-plugin实现相关功能。如果首页有较多图片资源,可以尝试将图片转化为webp格式来减小请求图片的大小,并设置图片懒加载。将首屏加载的资源单独打包,当用户访问首屏页面时仅给与首屏页面相关资源。针对部分简单的展示页面,也可考虑使用AMP来提供极速的页面加载。

selectionchange采坑记

应公司需求,要在游标发生变化时,监视游标的x,y坐标。于是,我便找到了selectionchange事件(当游标发生变化时就会触发selectionchange事件),看着很美,添加事件监听器就会触发callback。
       使用时,我想将它加在指定的DOM上,结果加了之后无论怎么操作都无法触发callback,重新查阅MDN,结果它仅支持在document,input,textarea上添加监听,后两者除了firefox外都没有实现。好吧,最终我只能加在document上了。
       但是,使用一段时间后发现敲击回车和删除整行的时候,不会触发callback事件,查看公司编辑器DOM发现,由于插入整行和删除整行都是以创建和删除DOM的方式运行,一阵苦思冥想之后总算明白原来selectionchange是通过监视游标在当前DOM的位置变化来触发callback的,由于添加和删除DOM元素,本身在当前DOM的位置并未发生变化,所以不会触发callback。
       总结,selectionchange虽然很不错,但还是要依据具体场景和情况使用的。

PWA小记

图片
PWA作为近期最为热门的前端技术,正被广泛应用与国外各大厂商的APP当中,例如,最近twritter就用PWA替换了windows10上的功能严重缺失且更新缓慢的UWP应用,微博也推出了PWA版的微博应用,无需下载即可使用(网友惊呼web赶超原生APP了)。
       本文就来简单介绍一下这项面向未来的黑科技。PWA最初由google于2014年提出,当时可能由于过于先进,只有chrome完美支持了PWA,因此影响力十分有限,时隔4年,PWA已经羽翼丰满(特别是safari支持了PWA之后),是时候大展身手了。
       首先,PWA最重要的一个部分是Service Worker,可以把它理解成是一个本地的server,它是独立于web网页的一个独立进程,因此在Service Worker中的任何操作都不会阻塞web进程的渲染与执行,这就相当于浏览器的实现的子进程,我们可以把耗时操作放在Service Worker中(如跑个AI什么的,配合tfjs也是杠杠的)。它还可以拦截请求,并进行缓存,预处理等等。另一个重要特性就是它能常驻后台,这使它能够完成服务端的消息推送以及应用载入时提供必要的页面资源(前提是已缓存)。
示例图        其次,便是manifest.json,这主要是与APP图标相关,它可以自定义APP图标与名称,并提供添加APP图标的横幅。按照标准实现后,以普通APP相差无几。        结语,Web的时代正在悄悄到来,随着Web应用用户体验的提升,Web应用跨平台的优势越来越明显,或许在2年后Web应用就会完全替代原生APP。 附PWA相关资源: PWA应用合集 https://pwa.rocks/ ServiceWorker框架 https://developers.google.cn/web/tools/workbox/

公司自动部署系统建设

图片
刚来到公司的时候,由于没有自动部署系统,导致每次提交完代码后都得手动scp到相应的服务器上,费时费力,还容易出错。于是,我便着手打造一套公司专用的内部部署系统。
       最开始的构想是使用drone配合gogs来完成一套部署系统,方便且功能强大。但实践的时候却由于drone文档不全,服务器空间不足(无法安装docker),git服务器配置差等因素被迫中止。        最后在结合实际情况考虑之后,打算自建部署服务器,通过git hooks与node server构建一套部署系统。        结构图如下

       首先是搭建node server,我采用express+ts-express-decorators的一个组合,ts-express-decorators使用大量装饰器取代了wrapper,使代码趋于整洁美观并提高了维护性与复用率。后端框架完成之后,便要考虑如何执行shell,这里我使用了shelljs(主要是对于child-process的一层封装),借助其强大的api,可以方便的执行各种shell命令。
       为了方便进程管理,我使用了pm2作为进程管理工具,并采用pm2-web进行相关进程的监控(不用进服务器查询进程信息了)。
       对于要使用自动部署的项目,只需在项目更目录下加上deploy.json(记录了要部署的服务器等信息)与deploy.sh(自动部署时要执行的脚本,如项目构建等)即可完成相应自动部署任务。
       遇到的问题:
       1.scp与git的权限问题:通过ssh-keygen生成rsa证书可以解决
       2.git脚本执行情况反馈:在执行git hooks的时候,发布代码的控制台会打印相关信息



tfjs源码笔记

tf.tensor:通过Tensor.make生成Tensor实例,默认根据util.inferShpe根据传入的values生成shape[]数组,也可自己传入shape[]
tf.scalar:是对tf.tensor传入values为number或boolean的封装,有更好的语义
tf.tensor1d:是对tf.tensor传入values为一元数组的封装,有更好的语义
tf.tensor2d:同上依次类推
tf.tensor3d:同上依次类推
tf.tensor4d:同上依次类推
tf.buffer:创建一个TensorBuffer实例,TensorBuffer与Tensor类似,但值可变
tf.fill:通过util.sizeFromShape将shape中的各值相乘,算出值的数量,然后通过util.getTypedArrayFromDType更具dtype生成对应的TypedArray,最后调用相应的fill填充数据